How do I add application level encryption to an Android BLE connection?

The Android Bluetooth Low Energy documentation recommends adding application layer encryption on-top of the BLE connection if the exchanged data is sensitive:

Caution: When a user pairs their device with another device using BLE, the data that's communicated between the two devices is accessible to all apps on the user's device. For this reason, if your app captures sensitive data, you should implement app-layer security to protect the privacy of that data.

As I would like to avoid "rolling my own encryption", I am looking for a production-ready way to encrypt packets. I have an out-of-band channel to exchange one message (e.g key) from one participant to the other (QR code). Both participants are Android devices, one operating in server mode (peripheral), and one as a client (central). I looked at the Noise Protocol Framework as a more lightweight alternative to TLS, but that feels like it is still to much manual work(?). Is there an easy solution? It seems like this has to be a solved problem.

asked Aug 17, 2020 at 17:09 43 4 4 bronze badges

1 Answer 1

First, a word of advice: StackExchange is not for recommending specific products, so I'm going to be relatively general here. Whoever reads this in the future may be in a world where there are new and much better alternatives, or even where the old guard has been found to be broken.

There are several high-level crypto libraries that - given a pre-shared key - will handle message or possibly stream encryption (and related security requirements such as data integrity) with a minimum of effort. Simply searching for "easy crypto library" will find you some candidates. Note that lots of people ignore the advice against rolling your own crypto, and some of them publish it, so you do want to make sure the library you pick is well-reviewed by experts, ideally unrelated to its development.

You'll also want to consider what exactly you want (and need) from your library. Does it need to support arbitrary-length encrypted streams (or very large messages that don't easily fit in memory), or will a simple message-based protocol work? Must the library be very small, in install footprint or RAM usage? Very fast, on a particular CPU? Compatible with any particular other library? Use specific ciphers or other primitives for compliance reasons (I hope not)? Available in a particular language?

For a few well-regarded examples as of mid-2020, consider LibSodium or Monocypher. Both are well-regarded, reviewed, and focused on ease of use. Other alternatives are NaCl, LibHydrogen, and so on. Note that not all of these focus equally on security, speed, or convenience; for example, TweetNaCl emphasizes minimal code size, sacrificing a lot of speed and potentially some security in the process, compared to the original NaCl.