Age encryption cookbook

Many locks for one secret

One of the niftiest tools that I have been using a lot nowadays is the deceptively simple encryption/decryption command line tool called age by Filippo Valsorda.

Encrypting secrets using keypairs instead of a single passphrase is obviously a more secure option, as it separates the concerns for encryption and decryption. Therefore you can share around the public key without fear for others to encrypt data for you that only you can decrypt.

Traditionally, we have been using tools like gpg e.g. while using eyaml in Puppet, etc. However, gpg comes with its own overhead of key management - multiple keyrings, tool configuration, etc. which makes the use case of simple encryption to be fairly complicated.

age packs a lot of functionality into its dead simple CLI interface - a single file to “manage” the keypair. It requires zero configuration. More importantly, it supports not just its own X25519-based key pair format, but it can even use SSH key pairs for encryption. For simple use cases, it even supports symmetric passphrases.

I have been keeping this document in my PKM for a while, and I thought it best to share in public as a cookbook as well.


I mostly work on Mac nowadays, and prefer to use homebrew for installing age. Instructions for other platforms are in the official docs.

$ brew install age


Key generation

Before you can accept encrypted content, you need to generate your keypair. Key generation gives us a public key and a private key. The public key is also referred to as a recipient in the tool documentation.

$ age-keygen
# created: 2023-07-06T22:35:40-04:00
# public key: age1lm45u4v4nka4s3uv68dpfv2c33fdgak6mjvdn5sfsv8rlvss9vyss927mg

Specifying a file to save, using -o, will store the previously shown output to the file. But it hides the secret key from being displayed to the console. It still displays the public part.

$ age-keygen -o key.txt
Public key: age1l36wdcfx825h727h5wjs7swh675f3jd4qde0zj47gyslmuja3agspge22t

$ cat key.txt
# created: 2023-07-06T22:39:59-04:00
# public key: age1l36wdcfx825h727h5wjs7swh675f3jd4qde0zj47gyslmuja3agspge22t

You can extract the public key from a key file using age-keygen -y, similar to how you might have used ssh-keygen -y for ssh keys.

$ age-keygen -y key.txt

However, unlike ssh-keygen, you can extract public keys from a bunch of age identity files in one shot.

$ cat key*.txt | age-keygen -y


You encrypt using a recipient name. The output is by default in an efficient binary form. You can use the -a option to armor the output into a printable version.

$ cat /etc/hosts | age -r age1l36wdcfx825h727h5wjs7swh675f3jd4qde0zj47gyslmuja3agspge22t -o hosts-1.age

$ file hosts-1.age
hosts-1.age: data

$ cat /etc/hosts | age -r age1l36wdcfx825h727h5wjs7swh675f3jd4qde0zj47gyslmuja3agspge22t -a

Repeated encryption of the same file for the same recipient will give different output. Good thing to keep in mind if you were planning on using file hashes to check if the encrypted files have been generated by the same key. You shouldn’t.

$ cat /etc/hosts | age -r age1l36wdcfx825h727h5wjs7swh675f3jd4qde0zj47gyslmuja3agspge22t -o hosts-2.age
$ diff -u hosts-1.age hosts-2.age
Binary files hosts-1.age and hosts-2.age differ

You can specify multiple recipients by repeating the -r parameter, or put them all in a recipients file and specifying the file using -R.

$ age-keygen -o key-alt.txt
Public key: age1sa3srvuxwx4g4sshgxvgc0cx8c5kwukv5kmvsmnp3d43levctehsla3m2f

$ cat key*.txt | age-keygen -y > recipients.txt

$ cat recipients.txt

$ cat /etc/hosts | age -R recipients.txt -o hosts-3.age

The same encrypted file can be decrypted by both the recipients. That is, you don’t have to generate different encrypted versions for each recipient.

The recipients file format supports comments, so you can document the recipient keys.

$ cat recipients.txt
# Build key

# QA key

You can mix SSH public keys and age public keys in the recipients file.

$ cat ~/.ssh/ ~/.ssh/ > r.txt

$ age-keygen -y ~/.age-chezmoi.txt >> r.txt

$ age -R r.txt -a < /etc/hosts


Here the same file encrypted for both the recipients can be decrypted with their respective private keys.

$ age -d -i key.txt hosts-3.age
# Host Database

$ age -d -i key-alt.txt hosts-3.age
# Host Database

Identity encryption

Normally the encrypted file can only be decrypted by the recipient public key. Even you cannot decrypt it afterwards.

You can specify your own public key as recipient to work around it. Or you can just specify your key file (using -i), containing your private key, for an identity encryption.

Here the file is being encrypted for a different recipient, as well as for the person having a private key locally.

$ age -e -i key.txt -r $(age-keygen -y key-alt.txt) -a /etc/hosts | age -d -i key.txt
# Host Database
To use the -i parameter, you have to explicitly use the -e or --encrypt parameter to specify you are trying to do encryption.

Using SSH keys for encryption

New versions of age can also use your existing SSH key pairs for encryption/decryption.

$ cat /etc/hosts | age -R ~/.ssh/ -o hosts-4.age

$ age -d -i ~/.ssh/id_rsa hosts-4.age
# Host Database

While doing decryption, if your SSH private key was encrypted, you will be asked for the passphrase.

Using a simple password for encryption instead of a key pair

For even simpler use cases, age also supports simple passphrase based encryption.

$ cat /etc/hosts | age -p -o hosts-5.age
Enter passphrase (leave empty to autogenerate a secure one):
Confirm passphrase:

$ age -d hosts-5.age
Enter passphrase:
# Host Database

Other uses

age is a simple data encryption/decryption tool. It is not aware of file formats. So if you wanted to encrypt just a single key value in an YAML file, you will need to extract the value from the file, provide it to age for encryption, and then add the (probably armored) value back to the file.

Higher level tools like Mozilla SOPS understand file structure of formats like YAML, JSON etc. and can use age for encryption/decryption for individual values in these data structures.

Converting audio to text from command line using commercial and opensource tools