Age Encryption with PKCS11 tokens

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. However, X25519 keys are just 256 bits, and conveniently the tokens I have do support elliptic curve keys which can be used for ECDH to derive a shared secret. Yes, it’s the NIST P-256 curve, which you may have feelings on, but I’m not yet ready to shell $500 on a Yubico HSM. Yet.

That shared secret is what I’m going to be using. In lieu of of the age private key, you generate an elliptic curve key pair off the token, and then throw away the private half - you won’t need it. The public half then in effect becomes a “key handle”, which when combined with the private half of the key locked away in your token can generate a 256 bit shared secret, which you then use as the age private key. The “key handle” is useless without the token, so you don’t have to protect it. It also isn’t the resultant age public key; rather, you’ll use the shared secret generated to instantiate an age private key, then spit out the public side of it.

Code is up here and is very rough. Right now it assumes you’ve handed it a 256 bit EC public key, and all it generates is the shared secret. And there’s a bunch of hardcoded stuff and little error checking. But it’s taken a solid two days of work to get that far, and I’m happy with that.