Back to the journalNOTES BY FAJAR
Cryptography4 min read

[Crypto: age] Passphrase or Key Pair

Compare a passphrase with an age key pair, make your own keys, and encrypt one file for two recipients.

PART 5 OF 6Crypto: age
  1. 01[Crypto: age] From Password to Ciphertext
  2. 02[Crypto: age] Reading the Header
  3. 03[Crypto: age] scrypt, From Password to Key
  4. 04[Crypto: age] ChaCha20-Poly1305, Sealing the Body
  5. 05[Crypto: age] Passphrase or Key PairYou are here
  6. 06[Crypto: age] How Long Does a Passphrase Attack Take?
In this article 5 sections

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.

  1. Make a new directory for this example:

    bash
    mkdir age-key-demo
    
  2. Change to that directory:

    bash
    cd age-key-demo
    
  3. Generate the key pair:

    bash
    age-keygen -o key.txt
    
  4. Show only the public key:

    bash
    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.

  1. Store your public key in a shell variable:

    bash
    AGE_DEMO_RECIPIENT=$(age-keygen -y key.txt)
    
  2. Make the sample text file:

    bash
    printf '%s\n' 'Anyone can encrypt to my public key.' > note.txt
    
  3. Encrypt the note:

    bash
    age -r "$AGE_DEMO_RECIPIENT" -o note.age note.txt
    
  4. Decrypt the note with your identity file:

    bash
    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:

text
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:

text
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:

text
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

  1. Generate a second identity file:

    bash
    age-keygen -o key2.txt
    
  2. Store its public key:

    bash
    AGE_DEMO_RECIPIENT_TWO=$(age-keygen -y key2.txt)
    
  3. Encrypt the note for both recipients:

    bash
    age -r "$AGE_DEMO_RECIPIENT" -r "$AGE_DEMO_RECIPIENT_TWO" -o two.age note.txt
    
  4. Decrypt with the first identity:

    bash
    age -d -i key.txt two.age
    
  5. Decrypt with the second identity:

    bash
    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

QuestionPassphraseX25519 key pair
What permits encryption?The chosen passphraseThe recipient public key
What permits decryption?The same passphraseA matching secret key
What must stay secret?The passphraseThe identity file
What does the user supply?A passphrase at the promptA public key or an identity file
What is a useful application?A file you decrypt with a stored passphraseAutomated 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.

FILED UNDER

NEXT IN THIS SERIES[Crypto: age] How Long Does a Passphrase Attack Take?

THANKS FOR READING

Did this resonate?

A reaction or a conversation is always welcome.

Loading reactions…

Pass it along

Loading comments...

KEEP EXPLORING

One thought leads to another.

All writing
Back to all writingOne note at a time.