Today I discovered you absolutely can import an externally generated age key into one or more YubiKeys, allowing you to have backups of it. Since I replaced GnuPG with age, this has been my only gripe: I want a backup of my key, both as additional YubiKeys but also as a paper printout.

I was told you are not supposed to do this. "Just have multiple keys and age-encrypt to all of them". People are probably right, but I have evaluated the risks for myself and know how to use an airgapped device. I'm not telling you, you should do this, but other people seem to want this too, so here is how - do with this information what you want.

Certificate Format

age-plugin-yubikey looks for certificates in the "retired slots" (82-95, also called slots 1-20) with:

Subject DN: CN=<name>,OU=<version>,O=age-plugin-yubikey

The plugin also reads PIN and touch policies from a certificate extension with OID 1.3.6.1.4.1.41482.3.8. The value is two bytes encoded as DER:XX:YY where the first byte is the PIN policy and the second is the touch policy:

PolicyPINTouch
Never0101
Once02-
Always0302
Cached-03

For example, DER:01:01 means PIN=Never, Touch=Never. If this extension is missing, the plugin may not correctly detect the policy requirements.

Generating the Key

Generate P-256 key externally using openssl, then import it to slot 82 (retired slot 1):

openssl ecparam -name prime256v1 -genkey -noout -out age-key.pem
openssl ec -in age-key.pem -pubout -out age-key.pub
ykman piv keys import 82 age-key.pem

Generating the Certificate

We also need a certificate in the expected format with the OID extension for PIN/touch policy. Use openssl to create a self-signed certificate (this example uses PIN=Never, Touch=Never):

openssl req -new -x509 -key age-key.pem \
    -subj '/CN=My Backup Key/OU=0.5.0/O=age-plugin-yubikey/' \
    -days 3650 \
    -addext '1.3.6.1.4.1.41482.3.8=DER:01:01' \
    -out age-cert.pem

Then import it to the YubiKey:

ykman piv certificates import 82 age-cert.pem

Test Encryption/Decryption

Export the identity file and verify you can encrypt and decrypt correctly:

age-plugin-yubikey --list
age-plugin-yubikey --identity --serial 22412951 --slot 1 > age-yubikey-identity.txt
echo "test secret" | age -r age1yubikey1xxxxxxxxxxxxxxxxx -o test.age
age -d -i age-yubikey-identity.txt test.age

Additional YubiKeys

For any additional keys, import the same key and the same certificate:

ykman piv keys import 82 age-key.pem
ykman piv certificates import 82 age-cert.pem

You will have multiple age identities with a common recipient. If you encrypt to that recipient, you will be able to decrypt with any of the keys. The identities differ because each YubiKey has a unique serial number.

You can concatenate both identity files, so that any key works for decryption later. If you don't do this, it will ask you for "Key with serial XXXX" on decryption.

Backup

Store age-key.pem and age-cert.pem securely - these two files are all you need to restore the identity to a new YubiKey.