jakob@nyx:~/blog$ cat posts/age-seed-keygen.md
< back to index // 2026-05-21 tools cryptography age bip39
← index
// 2026-05-21

age-seed-keygen — Backing Up Encryption Keys as Words

age-seed-keygen — Backing Up Encryption Keys as Words

Source: git.jakobhusu.com/jakobhusu/age-seed-keygen

I've been using age for a while now. It's a nice tool — simple, modern, no config file sprawl. But the backup story for the identity key always bugged me. The standard advice is "keep a copy somewhere safe," which in practice means copying a file to an encrypted drive or a password manager. That works until it doesn't. Drives fail, password managers get locked out, you forget which machine had the backup.

What I actually wanted was a paper backup. Not a QR code, not a base64 blob I'd have to type out by hand — something readable. Hardware wallet people solved this a decade ago with BIP39 mnemonic phrases: 24 common English words that encode the seed. So I built the same thing for age keys.

The idea

An age X25519 private key is 32 bytes of entropy. BIP39 can encode exactly 32 bytes as 24 words. That means the entropy itself can be the source of truth — generate some random bytes, turn them into a mnemonic and an age identity at the same time. Recovery is just the same thing in reverse.

The actual derivation is pretty short:

entropy = os.urandom(ENTROPY_BITS // 8)
words   = Mnemonic("english").to_mnemonic(entropy)
private_key = X25519PrivateKey.from_private_bytes(entropy)

After that it's just encoding — the private key goes through bech32 with the age-secret-key- prefix, the public key gets encoded as an age1… recipient. Both are the exact formats the age CLI expects, so the output file drops straight in as a normal identity.

Using it

$ python keygen.py generate
Generated X25519 age identity
  Identity file : /home/user/.config/age/key.txt
  Public key    : age1ql3z7hjy54fw3x5uw...

Your 24-word recovery mnemonic — write these down and store offline:

   1. crane        2. ribbon       3. napkin      4. frozen       5. walnut       6. draft

   7. pepper       8. sorrow       9. canoe      10. lemon       11. blanket     12. honest

  13. voyage      14. signal      15. copper     16. pebble      17. gentle      18. marble

  19. oyster      20. summit      21. velvet     22. fern        23. harvest     24. chorus

These words reconstruct your exact age identity. Keep them secret.

Write the words down, then put the paper somewhere physically secure. Recovery is:

$ python keygen.py recover crane ribbon napkin frozen walnut draft \
    pepper sorrow canoe lemon blanket honest \
    voyage signal copper pebble gentle marble \
    oyster summit velvet fern harvest chorus

You'll get back the same identity file with the same public key. If the public key doesn't match, a word is wrong somewhere.

The default output path is ~/.config/age/key.txt but you can override it with -o.

One thing to be clear about

The mnemonic isn't a hint or a backup code — it is the private key, just encoded differently. Anyone who gets those 24 words can reconstruct your identity and decrypt everything encrypted to it. Treat them at least as carefully as you'd treat the key file itself. Don't photograph them, don't type them into anything online, don't store them in the same place as the key file.

The identity file gets created with 0600 permissions. If you want an extra layer of protection on disk, you can encrypt the file itself with age:

$ age -p -o key.txt.enc key.txt

That doesn't affect the mnemonic — recovery still gives you the plaintext identity, and you can re-encrypt it after.

Is a paper backup actually better?

For most things, probably not worth the hassle. But for a long-term key — something you're using to encrypt backups or files you want to be able to read in five years — paper has some real advantages. It doesn't need power, it doesn't have a file format that becomes unreadable, and it survives the kind of cascading failures (dead machine, locked account, forgotten password manager password) that tend to happen all at once during an already bad day.

The everyday workflow stays the same: use the key file as normal. The mnemonic just sits in a drawer until you actually need it.

blog.jakobhusu.com [jakobhusu.com] [news] [git] [linkedin]