Better security for KeePassNFC
Update 2016-08-09: I've now got an experimental version of KeePassNFC working with the scheme below, and everything seems to work fine. If I can't break it in the next couple of days I'll start uploading source.
My NFC authentication app for KeePassDroid is fine as long as your phone is secure, but if your phone is stolen, or someone gets root access on it, then all they need to do is scan your NFC tag (remotely!) to get access to your KeePass database (or perhaps someone scanned for NFC tags first to determine the type of person who may have interesting stuff on their phone). This isn't a great failure mode.
The problem is that the key is easily read by anybody in the vicinity. It can't be used without privileged access to the phone, but it would be much better if it were not available at all. You could address this with a JavaCard applet running on a contactless smartcard. Applets can contain private data, so they can be written to never reveal the secret key. Additionally, JavaCard supports on-card generation of encryption keys, which is quite nice because it means that there is no time in which snooping on NFC communications will give an attacker any useful information.
The design is in two parts.
Part 1: Storing a secret key
Encrypted with public key (RSA):
Encrypted with password key (AES):
Encrypted with transaction key (AES):
In the first part, the phone encrypts the sensitive information (e.g. the database password and keyfile) using the password key. It then transmits the password key to the smartcard, by first encrypting it with the card's public key (the smartcard having previously been instructed to generate a public/private key pair). The phone can then discard the password key.
Part 2: Decrypting secret data
At this point, the password key is only stored on the card. Decryption then necessarily involves the card. The idea here is to have the card decrypt the data using its secret key, but to re-encrypt it using a temporary key before sending it to the phone
The phone first generates a transaction key and transmits it to the card securely (by encrypting it with the card's public key). It then transmits the encrypted sensitive information to the card and requests that it be decrypted. The card first decrypts the information, using its previously-stored password key, and then re-encrypts it using the transaction key before transmitting it back to the phone. When the phone has received the data, it decrypts it and throws the transaction key away.
It should also be possible to do something similarly secure (in terms of NFC snoop resistance) using a PGP applet running on the card. Another alternative, would be to store the sensitive information on the card directly, but that creates its own set of problems around attestation and traffic sniffing.
Thanks to Bill Broadley for the email discussion which led to me implementing this.