My last project was building an Android password store based on Bletchley and I’m going to describe the process I went through along with some of the issues I had in the process.
I started by making Bletchley run on Android… which required a bit of work. First, nothing worked since converter lookup failed for some random object field. After a bit of debugging I found that Android was adding a couple of transient shadow fields to every object and Bletchley’s converter lookup failed for them. This issue was easily solved by adding a filter for transient fields during object inspection.
Then Bletchley failed at runtime while logging processing of items in the InferenceEngine. This made calls to a prettyprint module that uses base64 encoding and failed because some library’s version used by Android was older than what Bletchley was expecting. Since I did not need any of that I simply commented it out.
There weren’t any more issues with Bletchley and developing the app’s UI took the expected amount of reading guides, StackOverflow answers and experimentation with a few occasional frustrations.
A most notable issue I had was adding search functionality. It took an unreasonable amount of time to implement this as Google’s guides show inconsistent code samples on how to do it and the search bar view simply did not get created for me. In short, the example I followed (seemed to be the best one) told me to include the following in an xml file describing menu items in the app toolbar:
What I found I should have done was the following (just change the namespace):
The password store is split into a few directories: git repository tracks keys and secrets (encrypted passwords), local directory contains private keys and an index with a list of trusted public signing keys and a list of (password name -> encrypted file name) objects. Bletchley uses NSA suiteb cryptography.
Our primary objective here is to store encrypted passwords (they’re signed as well), so let’s define a small class PasswordItem for a password: it has the password itself and a name for it. We want this class to extend ActionType so that when we process an encrypted password item with InferenceEngine, we can just do engine.getSoleAction(PasswordItem) to get it if it was successfully decrypted. For that to work we need to construct an Action instance with PasswordItem as payload whenever we construct messages so that InferenceEngine can process it.
Then we want to have a private-public pair of signing and encryption keys (four in total). We’ll use the public signing key to identify users and public encryption key to let others encrypt passwords only we can decrypt. We sign our public encryption key so that others know it belongs to us. In general, to share a password we only need to know the recipient’s signing key since Bletchley can find the right encryption key by processing all the signed keys in the repository. The only keys extracted are the ones signed by the recipient we’re sharing with (provided key’s trust is not limited). Users can put trust limits on keys and this way there should only be one encryption key available to share with.
To be able to extract an encryption key just by processing a list of files, wrap it in another class RecipientEncryptionKey that extends ActionType. We do engine.processTrusted(recipient signing key) to trust items signed by the corresponding user and then process every file in the directory. The encryption key wrapper object will appear in engine.actions.
To put a trust limit on an encryption key we need to first create a temporary signing key. We use this key to sign our public encryption key. What we’re going to store is a Sequence(Limit, signed encryption key) signed with our main signing key (not limited). Limit specifies the conditions of trust for its subject, in our case the signing key.
With the above, we can start making a secret (encrypted password). We are producing a sequence of items that the InferenceEngine will process in order to extract a PasswordItem (an ActionType) from it. We generate an AesKey to encrypt the password data and an ephemeral key (PrivateEncryptionKey, used to generate shared secret key) to encrypt the AesKey for each recipient public encryption key. Sign the password and encrypt that with the AesKey. We now have all we need to construct a Bletchley message which is a Sequence(public ephemeral key, sequence of encrypted AesKeys, encrypted signed password).
When the InferenceEngine on the recipient’s side processes this Sequence it will first derive a PrivateEncryptionKey to decrypt the AesKey and add it to the engine. The next item in the sequence is the encrypted signed password, which is an AesPacket that specifies the key id used to encrypt data. This key is looked up in the InferenceEngine and since we just added it using the first sequence item we can successfully extract the signed password data. This is another sequence of items and here we need to have the signing key of the recipient trusted. If it is then the InferenceEngine will process the signed item (an Action instance with PasswordItem as payload) thus adding it to InferenceEngine.actions list.