A while back my colleagues and me had some free time, so we had an idea to build an app that enables you to use a Yubikey to encrypt/decrypt files using any Android/iOS phone available as long as you have your Yubikey with you.
Our platform of choice is always Flutter. Unfortunately it didn’t have a plugin for communicating with a Yubikey, so we built that. It allows you to use low level APDU commands to communicate with a Yubikey (or any smart card that uses the same standards).
In addition to that we needed implement the high level stuff: Yubikey implements the OpenPGP Smart Card standard for communicating with it. Yubikeys also support PIV standard, but PIV only supports US government approved elliptic curves which do not include the currently recommended Curve25519. Since we started with it, the plugin has PIV support built in as well. For OpenPGP, we built another Dart library which implements some common OpenPGP smart card specification compliant actions you can take on your smart card. It doesn’t depend on the Flutter plugin, so it can be used on other platforms as well if needed.
Originally we wanted to go with OpenPGP as the encryption standard for communication because that’s what the Yubikey uses, but we really didn’t enjoy working with the standard so we found an alternative: age encryption. Why? Because age specification is really easy to follow and since there weren’t any OpenPGP implementations on Flutter that we could use. There is this, but it doesn’t support GNU PGP extensions that are used on your computer to trigger the smart card for encryption/signing actions so we would have needed to write our own OpenPGP implementation which is pretty crazy.
Instead, we built dage: a Dart implementation of age encryption that is fully v1 spec compliant and open sourced it, so it can be used by anybody. One of our goals from the start was that if for some reason we go out of business or our app is taken down you could still decrypt your data, so we built an option into dage to run it as a CLI program and use your Yubikey with your computer to decrypt the data. Of course this is mostly useful when you use your own data storage (or you have exported the encrypted files at any point the app was available) and not the one provided by us, but this feature is currently in the backlog.
- NFC is pretty unreliable for doing things that take time since you need to position the token behind your phone and not move it in any way for the duration of the action, so things like generating RSA keys is not really doable
- Renamed our app from Yubidrive to Secdrive (for now) for obvious reasons :)
- When you create an iOS app that uses a hardware device over Lightning, the hardware manufacturer needs to give you approval to use it, so you need to register your app and wait for a review, which for us took a few weeks
- We built a Flutter plugin for YubiKit
- We built a Dart library that implements OpenPGP smartcard interface
- We built a Dart library that implements age encryption
- Finally, we built the app
At some point I would like to write more about each of the open source components in separate blog posts as well so stay tuned!