A passphrase is a shared secret. Anyone who knows it can decrypt the file. A key pair has a public key for encryption and a secret key for decryption.
This distinction helps when someone must send you a private file. You give that person your public key. That person can encrypt the file without your secret key or a shared passphrase.
This example uses X25519 keys. X25519 is a cryptographic key agreement algorithm. age supports other recipient types that this example does not include.
Make a key pair
These commands use age 1.3.1. The first post gives the installation command for macOS.
-
Make a new directory for this example:
mkdir age-key-demo -
Change to that directory:
cd age-key-demo -
Generate the key pair:
age-keygen -o key.txt -
Show only the public key:
age-keygen -y key.txt
The public key starts with age1. Your generated value will differ from the values in other examples. The identity file, key.txt, contains the secret key and comments.
The secret key starts with AGE-SECRET-KEY-1. An identity is secret information that age uses for decryption. A recipient is public information that age uses for encryption.
Keep key.txt private. Keep a secure backup of it. Without a usable secret key or another recipient identity, you cannot decrypt files made for this public key.
Encrypt with your public key
The variable below stores the public key from your own identity file. This avoids a common example error: encryption to a published sample key that you cannot decrypt.
-
Store your public key in a shell variable:
AGE_DEMO_RECIPIENT=$(age-keygen -y key.txt) -
Make the sample text file:
printf '%s\n' 'Anyone can encrypt to my public key.' > note.txt -
Encrypt the note:
age -r "$AGE_DEMO_RECIPIENT" -o note.age note.txt -
Decrypt the note with your identity file:
age -d -i key.txt note.age
The -r option specifies the recipient. The -i option specifies the identity file for decryption. The output is:
Anyone can encrypt to my public key.
Encryption does not use a passphrase prompt in this example. A backup script can keep only the public key. The secret key can stay on the computer used to restore the backup.
A public key does not have to be secret. You must get the correct public key for the intended recipient. If you use a substituted public key, someone else can decrypt the file.
What changes in the header
The header post showed a scrypt stanza for a passphrase. An X25519 recipient uses a different stanza. The initial example recorded this header:
age-encryption.org/v1
-> X25519 FtU1s5d9k32gVivtjqvPX8rzlFO0Us90/nBclSGBnmk
UjnBxWgCapXFCE96yIVgtR2L9xhWnSixZsA8qREIBZg
--- CJaG+8hCydCZNsY5fLWDQtFPXBLoTxs7UdDtgjvNZgM
Your file will have different random values. The value after X25519 is an ephemeral public key. Here, ephemeral means that age generates a new key for this stanza and file.
age combines the ephemeral secret key with the recipient public key through X25519. This calculation makes a shared secret. age then derives a wrapping key from that secret with HKDF-SHA-256.
The recipient uses the stored ephemeral public key and their own secret key to calculate the same shared secret. Thus, the recipient can derive the same wrapping key. Neither party stores the shared secret in the header.
The pseudocode shows the encryption calculation. The symbol || means to join byte sequences:
shared secret = X25519(ephemeral secret key, recipient public key)
wrapping key = HKDF-SHA-256(
input key material = shared secret,
salt = ephemeral public key || recipient public key,
info = "age-encryption.org/v1/X25519"
)
stanza body = ChaCha20-Poly1305(wrapping key, file key)
The wrapping operation uses a nonce of twelve zero bytes and empty associated data. The age format specification defines the complete operation.
The file key and payload still have the jobs described in the cipher post. Only the method used to derive the wrapping key changes.
Encrypt one file for two recipients
-
Generate a second identity file:
age-keygen -o key2.txt -
Store its public key:
AGE_DEMO_RECIPIENT_TWO=$(age-keygen -y key2.txt) -
Encrypt the note for both recipients:
age -r "$AGE_DEMO_RECIPIENT" -r "$AGE_DEMO_RECIPIENT_TWO" -o two.age note.txt -
Decrypt with the first identity:
age -d -i key.txt two.age -
Decrypt with the second identity:
age -d -i key2.txt two.age
The two commands return the same note. Each identity works independently. The two people do not have to approve decryption together.
age encrypts the file contents once. It encrypts the same file key separately for each recipient. The resulting file has multiple stanzas and one payload.
Passphrase mode permits only one scrypt stanza. age rejects a command that combines -p with -r. It cannot combine these passphrase and public key methods in one encryption operation.
Choose the secret you can manage
| Question | Passphrase | X25519 key pair |
|---|---|---|
| What permits encryption? | The chosen passphrase | The recipient public key |
| What permits decryption? | The same passphrase | A matching secret key |
| What must stay secret? | The passphrase | The identity file |
| What does the user supply? | A passphrase at the prompt | A public key or an identity file |
| What is a useful application? | A file you decrypt with a stored passphrase | Automated backups or files from other people |
A key pair removes the human passphrase from this encryption path. Theft of the secret key can still let an attacker decrypt the file.
A passphrase can also be secure when it comes from random selection and you keep it secret. The final post shows why the selection method matters more than the character count alone.

Loading comments...