Couchbase-Lite Android Encryption

#1

I’m working on an Android project that utilizes Couchbase-Lite (1.1.0) and the requirements are that all data (the documents themselves and any Couchbase attachments) is encrypted prior to storage.

I had originally envisioned encrypting the entire database file using something like SQLCipher, but I haven’t been able to find a straightforward implementation for that (I know that the Couchbase-Lite implementation for iOS uses this approach, but the Android build is a bit behind), so instead my plan is to encrypt the documents (the JSON representation) and the attachments (the stream) before saving them into Couchbase-Lite database.

My questions: What are the recommendations for this kind of encryption? What methodology / libraries? I assume AES-256, but should I build it myself or utilize a 3rd party library (any suggestions)?

What’s the best way to maintain a passphrase within the device that is more secure than hardcoding it within the app (which is really, really bad)?

Has anyone seen something similar to this (my googling ability has left me high and dry) that could point me to a similar use case?

Thanks!

#2

One of the rules of cryptography is to never implement anything yourself. Always choose something that has been peer-reviewed and tested. This goes for algorithms and implementations.

To give the cynical answer: There is no way to secure something completely on a device. If someone wants it badly enough then it is just a matter of time before they get it. Mobile devices are inherently insecure because everything required to perform an action is right there (unlike a server where the requests and logic are separate).

That being said, cryptography on the device is all about making it more trouble to get to the information than it is worth to the malicious party. There are a few approaches out there such as:

A) Choosing a pass key based on a hardware identifier (it becomes more and more difficult to do this on Apple devices though)
B) Generate a random passkey based on UUID
C) Use a rotating passkey scheme (think Google Authenticator)
D) Store the password unencrypted in a plaintext file in your app bundle (just kidding, wanted to make sure you were still focused ^^)

The problem then becomes where to store this password to make it difficult to access. The most common place in iOS is the keychain, but even this is not foolproof. In fact I refer back to my cynical point, there is nowhere on the device that you can store this that will prevent someone from getting it. iOS filesystem encryption helps somewhat, but that is only as strong as the user using it (so…not strong at all usually) since most users are annoyed at passcodes.

You could do something like have your key be a hash of the database / attachment filename, or some other scheme like that. It’s not impossible to break, of course, if someone can see your source or bytecode but there is really not much you can do about that. Although I know Android has some sort of secure file partition that encrypts data on it using hardware keys on the device itself, so maybe you could store the key there.

#3

The problem with encrypting the docs this way is that they’ll still be encrypted wherever else they get replicated to. So any place those documents will be used needs a copy of the key, otherwise they’re unreadable. Now you have a key distribution problem (how to convey the key safely) and also your server and all clients have to use the same key, which basically means hardcoding it into the app, which as you noted is very insecure.

Actually it gets worse, now that I think about it — if the docs are encrypted then your map functions in any views have to decrypt them before they can work with the data. That’s going to slow indexing down a lot. And then if the keys emitted into the index are sensitive (which is likely) you’re stuck, because if you encrypt them they won’t sort correctly, so range queries won’t work.

It would be much more practical to integrate SQLCipher. The amount of code needed for it in Couchbase Lite was fairly small. It took more work to encrypt the attachments, but it’s still not that bad.

#4

An encryption key stored in the Keychain is exactly as secure as the existing iOS filesystem encryption, because the latter stores its keys in the Keychain too. So there’s not much point in it … unless you mark the key as requiring TouchID authentication. This adds another layer of encryption using a key that never leaves the “secure enclave” on the CPU. Reading that key would involve taking apart the CPU packaging and doing some pretty involved microscopic poking around. (It’s probably more feasible to construct a fake fingerprint that can fool the reader.)

#5

Ideally I’d be able to implement SQLCipher in the Android environment with Couchbase Lite, but I’m not sure what would go into that – you mention that the amount of code for implementing it on the iOS side (with attachments) was fairly small. Can you provide instruction or pointers for doing so on the Android side?

#6

I don’t work on the Android version of CBL, but it’s derived from the Objective-C version so the architecture and code structure should be similar.

Here’s the commit that added SQLCipher support. I think this would be pretty easy to port over by finding the comparable methods in the Java code.

Here’s the commit that added encryption of attachments; as I said before, it’s a lot more involved. I suspect this would be easier to implement in Java because unlike Cocoa there are already high-level encryption APIs.

#7

Don’t forget that you also need to bundle in your own version of the sqlite library that has these extensions compiled into it, and use that instead of the system sqlite library.

#8

thanks for the information and suggestions!

#9

thanks for this – I’ll have to take a look and see what I can come up with

#10

thank you for the tip!