Back to the journalNOTES BY FAJAR
Cryptography5 min read

[Crypto: age] Reading the Header

Read an age file header one field at a time, with simple definitions for the salt, encrypted file key, and authentication code.

PART 2 OF 6Crypto: age
  1. 01[Crypto: age] From Password to Ciphertext
  2. 02[Crypto: age] Reading the HeaderYou are here
  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 Pair
  6. 06[Crypto: age] How Long Does a Passphrase Attack Take?
In this article 7 sections

The first post made an encrypted file called secret.txt.age. Its header is readable text. The header gives age the information necessary to start decryption.

The payload starts after the header. It contains a random value and the encrypted file contents. The header and the payload have different jobs.

Read the header

In the example directory, show the first four lines:

bash
head -n 4 secret.txt.age

The output from the initial example is:

text
age-encryption.org/v1
-> scrypt pzJgb0zs5vH+TDRw2LwY6w 18
uGTID9B5wTysoKAj16JdCCNB82QMOVTCS7e0OFjgN5s
--- q0qn6iAS9XKtkTt94HV6beIv5DIVMOqDCUYKuBtY7bA

Your random values will be different. The four line layout applies to this passphrase example. Other recipient types can make longer headers.

LineNameMeaning
1Version lineThe file uses age format version 1
2Recipient type and parametersage uses scrypt with the displayed salt and work factor
3Stanza bodyAn encrypted file key and its authentication tag
4Header authentication codeA value that age uses to detect changes to the header

A recipient is a destination for encryption. A recipient stanza is a group of header lines that shows one method for decryption of the file key. Lines 2 and 3 form the scrypt stanza in this example.

The salt and work factor

The first stanza line contains the name scrypt, a salt, and the number 18.

A salt is a random value that age uses with the passphrase to derive a key. It does not have to be secret. age stores the salt so that decryption can repeat the same calculation.

The salt contains 16 bytes. The header displays those bytes as base64 text. Base64 is a way to represent bytes with readable characters. Base64 does not encrypt those bytes.

The number 18 is the work factor stored in the header. It sets the scrypt cost parameter to 2 raised to the power 18, or 262,144. The scrypt post shows how this value changes time and memory use.

The keys have different jobs

The passphrase does not directly encrypt the file contents. age uses several keys in this process:

ValueSizeJob
PassphraseVariableThe secret that the user supplies
Wrapping key32 bytesEncrypts and decrypts the file key
File key16 bytesRandom secret from which age derives other keys
Payload key32 bytesEncrypts and decrypts the file contents

In passphrase mode, scrypt derives the wrapping key from the passphrase and salt. age also generates a new random file key for each file. It encrypts that file key with the wrapping key.

The stanza body contains 16 bytes of encrypted file key and a 16 byte authentication tag. Thus, the decoded stanza body has 32 bytes. It is not a separate random key of 32 bytes.

An authentication tag lets age detect an incorrect key or a change to the encrypted value. With an incorrect passphrase, the tag check fails when age tries to decrypt the file key.

After age gets the file key, it derives a separate payload key. The payload post shows that step.

Why age encrypts the file key separately

Separate keys let age encrypt the same file key for multiple public key recipients. Each recipient gets a stanza. Any recipient with a matching secret key can decrypt the file key.

The payload still contains only one encrypted copy of the initial data. The key pair post gives an example with two recipients.

Passphrase mode has a different restriction. An age file with a scrypt stanza must contain only that stanza. It cannot also contain public key recipients.

The header authentication code

The last header line starts with ---. The remaining text represents a message authentication code, or MAC. This MAC lets age detect a header change by someone who does not know the file key.

age derives a header authentication key from the file key. It uses that key with the HMAC-SHA-256 algorithm. The calculation covers the header through the --- marker, without the space after the marker.

During decryption, age calculates the MAC again and compares the result with the stored value. If the values differ, age rejects the file. Some changes, such as an invalid salt, can cause an earlier error.

A person who knows the file key can calculate a new MAC. Thus, the MAC does not prove who sent the file. The age format specification defines the header and its authentication calculation.

Text armor and random values

The -a option makes an armored file. Armor is a base64 text representation of the complete encrypted file. It helps when a system accepts text but cannot accept binary data.

To make an armored example, run:

bash
age -p -a -o secret.txt.age.txt secret.txt

Enter your example passphrase at the prompts. The first line of the output file is:

text
-----BEGIN AGE ENCRYPTED FILE-----

The armor adds no encryption. After base64 decoding, the file has the same age format as a binary age file.

This command performs a new encryption. age generates a new salt, file key, and payload nonce. A nonce is a value used once in an encryption context.

Even with the same input and passphrase, a new encryption makes different bytes with overwhelming probability. The salt prevents useful reuse of a precomputed passphrase table across files with different salts.

The complete layout

mermaid
graph TD
    A["Version line"] --> B["scrypt, salt, and work factor"]
    B --> C["Encrypted file key and its tag"]
    C --> D["Header MAC"]
    D --> E["Payload nonce: 16 bytes"]
    E --> F["Encrypted content and chunk tags"]

The first four boxes belong to the header. The last two belong to the payload. The next post shows how scrypt uses the header parameters.

FILED UNDER

NEXT IN THIS SERIES[Crypto: age] scrypt, From Password to Key

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.