This weekend I made another addition to age-pkcs11, to follow best practices for HKDF key expansion from the shared secret at the core of the program. I’d been wanting to do this for a while, after reviewing some stuff I wrote about age and looking at the new V1 API there.
If you recall back in June when I went into detail on the X25519 cryptography in Age, near the end Age builds up a salt which, when combined with a label and supplied to the HKDF function ties the derived key to a specific context.
I’ve been dealing a lot with the age encryption protocol lately, and had a rough idea of how the scheme worked, but I finally wanted to sit down and work it out until it actually made sense.
As background, we have two parties, a sender, someone who wants to encrypt and send a file. We denote that party as U. Second, we have the recipient, that will receive that file and be able to decrypt it.
I came across this pull request in rage, the Rust implementation of age. There’s been some discussion of building a plugin system for age, and the rage implementer has started work for using a PIV device to store an age-compatible key. When the plugin system for age is decided, this will likely be the first implementation.
Looking at it, parts of it are remarkably similar to what I came up with, which is reassuring to me, as I was at least heading down a similar path.
My code to use age encryption with a PKCS11 token has drastically improved in the past couple days. Fewer things hardcoded, although it still assumes you have a NIST P-256 curve on both sides of the exchange. But it derives a shared secret, passes that through a HKDF to make it a reliable key, and can output an age-formatted private or public key. It’s rapidly approaching rough usability.
Some TODO items remain:
I’ve got a handful of the sub-50 Euro USB-based HSM tokens, the Smartcard-HSM 4K and the Nitrokey HSM. I’ve also started using age encryption for file encryption.
I’d like to merge the two. Using a PKCS11 token is something (reluctantly) on the age wishlist, but I got bored this weekend and decided to poke at it.
The stock AGE key, if you’re not deriving it from something like an SSH key or typing in a password, is an X25519 key, which none of my tokens support.