AGE(1)
bestie, you're looking at age(1) โ the manual page for age, the simple, modern, and secure file encryption tool. It's giving cryptography, but make it cute. ๐
๐ธ NAME ๐ธ
age โ simple, modern, and secure file encryption. No cap. โจ
โจ SYNOPSIS โจ
okay so here's the shape of it, bestie:
age [--encrypt] (-r RECIPIENT | -R PATH)... [--armor] [-o OUTPUT]
[INPUT]
age [--encrypt] --passphrase [--armor] [-o OUTPUT] [INPUT]
age --decrypt [-i PATH | -j PLUGIN]... [-o OUTPUT] [INPUT]
๐ DESCRIPTION ๐
age encrypts or decrypts INPUT to OUTPUT, periodt. The INPUT argument is optional and defaults to standard input. Only a single INPUT file may be specified โ one file, bestie, that's the rule. If -o is not specified, OUTPUT defaults to standard output.
If -p/--passphrase is specified, the file is encrypted with a passphrase requested interactively. Otherwise, it's encrypted to one or more RECIPIENTS specified with -r/--recipient or -R/--recipients-file. Every recipient can decrypt the file. ๐
In -d/--decrypt mode, passphrase-encrypted files are detected automatically and the passphrase is requested interactively. Otherwise, one or more IDENTITIES specified with -i/--identity are used to decrypt the file.
age encrypted files are binary and not malleable, with around 200 bytes of overhead per recipient, plus 16 bytes every 64KiB of plaintext. The math is mathing. ๐งฎโจ
๐ OPTIONS ๐
-o,--output=OUTPUTโ Write the encrypted or decrypted file toOUTPUTinstead of standard output. IfOUTPUTalready exists, it will be overwritten. ๐ญ If you're encrypting without--armor,agewill refuse to output binary to a TTY. This can be forced by specifying-asOUTPUT.--versionโ Print the version and exit. That's it. ๐
๐ Encryption options ๐
-e,--encryptโ EncryptINPUTtoOUTPUT. This is the default, bestie. โจ-r,--recipient=RECIPIENTโ Encrypt to the explicitly specifiedRECIPIENT. See the RECIPIENTS AND IDENTITIES section for possible recipient formats. This option can be repeated and combined with other recipient flags, and the file can be decrypted by all provided recipients independently. The more the merrier. ๐ซถ-R,--recipients-file=PATHโ Encrypt to theRECIPIENTSlisted in the file atPATH, one per line. Empty lines and lines starting with#are ignored as comments. IfPATHis-, the recipients are read from standard input. In this case, theINPUTargument must be specified. This option can be repeated and combined with other recipient flags, and the file can be decrypted by all provided recipients independently. ๐-p,--passphraseโ Encrypt with a passphrase, requested interactively from the terminal.agewill offer to auto-generate a secure passphrase. This option can't be used with other recipient flags. ๐ซ-a,--armorโ Encrypt to an ASCII-only "armored" encoding.agearmor is a strict version of PEM with typeAGE ENCRYPTED FILE, canonical "strict" Base64, no headers, and no support for leading and trailing extra data. Decryption transparently detects and decodes ASCII armoring. It's giving armor but make it text. ๐ก๏ธโจ-i,--identity=PATHโ Encrypt to theRECIPIENTScorresponding to theIDENTITIESlisted in the file atPATH. This is equivalent to converting the file atPATHto a recipients file withage-keygen -yand then passing that to-R/--recipients-file. For the format ofPATH, see the definition of-i/--identityin the Decryption options section.-e/--encryptmust be explicitly specified when using-i/--identityin encryption mode to avoid confusion. Bestie, read the room and pass the flag. ๐-j PLUGINโ Encrypt using the data-less pluginPLUGIN. This is equivalent to using-i/--identitywith a file that contains a single pluginIDENTITYthat encodes no plugin-specific data.-e/--encryptmust be explicitly specified when using-jin encryption mode to avoid confusion. ๐งฉ
๐ Decryption options ๐
-d,--decryptโ DecryptINPUTtoOUTPUT. IfINPUTis passphrase encrypted, it will be automatically detected and the passphrase will be requested interactively. Otherwise, theIDENTITIESspecified with-i/--identityare used. ASCII armoring is transparently detected and decoded. โจ-i,--identity=PATHโ Decrypt using theIDENTITIESatPATH.PATHmay be one of the following:- a. A file listing
IDENTITIESone per line. Empty lines and lines starting with#are ignored as comments. - b. A passphrase encrypted
agefile, containingIDENTITIESone per line like above. The passphrase is requested interactively. Note that passphrase-protected identity files are not necessary for most use cases, where access to the encrypted identity file implies access to the whole system. - c. An SSH private key file, in PKCS#1, PKCS#8, or OpenSSH format. If the private key is password-protected, the password is requested interactively only if the SSH identity matches the file. See the SSH keys section for more information, including supported key types.
- d.
-, causing one of the options above to be read from standard input. In this case, theINPUTargument must be specified.
- a. A file listing
This option can be repeated. Identities are tried in the order in which are provided, and the first one matching one of the file's recipients is used. Unused identities are ignored, but it is an error if the INPUT file is passphrase-encrypted and -i/--identity is specified. Bestie, that's the rule. ๐
-j PLUGINโ Decrypt using the data-less pluginPLUGIN. This is equivalent to using-i/--identitywith a file that contains a single pluginIDENTITYthat encodes no plugin-specific data. ๐งฉ
๐ซถ RECIPIENTS AND IDENTITIES ๐ซถ
RECIPIENTS are public values, like a public key, that a file can be encrypted to. IDENTITIES are private values, like a private key, that allow decrypting a file encrypted to the corresponding RECIPIENT. Public = shareable, private = keep it close. iykyk. ๐
๐ง Native keys ๐ง
Native age key pairs are generated with age-keygen(1), and provide small encodings and strong encryption based on X25519 for classic keys, and X25519 + ML-KEM-768 for post-quantum hybrid keys. The post-quantum hybrid keys are secure against future quantum computers and are the recommended recipient type for most applications. Future-proofing is main character energy. ๐โจ
A hybrid RECIPIENT encoding begins with age1pq1 and looks like the following:
age1pq167[... 1950 more characters ...]
A hybrid IDENTITY encoding begins with AGE-SECRET-KEY-PQ-1 and looks like the following:
AGE-SECRET-KEY-PQ-1K30MYPZAHAXHR22YHH27EGDVLU0QNSUH3DSV7J7NR3X6D9LHXNWSDLTV4T
A classic RECIPIENT encoding begins with age1 and looks like the following:
age1gde3ncmahlqd9gg50tanl99r960llztrhfapnmx853s4tjum03uqfssgdh
A classic IDENTITY encoding begins with AGE-SECRET-KEY-1 and looks like the following:
AGE-SECRET-KEY-1KTYK6RVLN5TAPE7VF6FQQSKZ9HWWCDSKUGXXNUQDWZ7XXT5YK5LSF3UTKQ
โ ๏ธ A file can't be encrypted to both post-quantum and classic keys, as that would defeat the post-quantum security of the encryption. So don't mix those vibes, bestie. ๐
An encrypted file can't be linked to the native recipient it's encrypted to without access to the corresponding identity. Privacy stays winning. ๐ธ
๐ SSH keys ๐
As a convenience feature, age also supports encrypting to RSA or Ed25519 ssh(1) keys. RSA keys must be at least 2048 bits. This feature employs more complex cryptography, and should only be used when a native key is not available for the recipient. Note that SSH keys might not be protected long-term by the recipient, since they are revokable when used only for authentication. Lowkey a use-when-needed situation. ๐ซถ
A RECIPIENT encoding is an SSH public key in authorized_keys format (see the AUTHORIZED_KEYS FILE FORMAT section of sshd(8)), starting with ssh-rsa or ssh-ed25519, like the following:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDULTit0KUehbi[...]GU4BtElAbzh8=
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH9pO5pz22JZEas[...]l1uZc31FGYMXa
The comment at the end of the line, if present, is ignored. โจ
In recipient files passed to -R/--recipients-file, unsupported but valid SSH public keys are ignored with a warning, to facilitate using authorized_keys or GitHub .keys files. (See EXAMPLES.) Very "drop it in and go" of them. ๐
An IDENTITY is an SSH private key file passed individually to -i/--identity. Note that keys held on hardware tokens such as YubiKeys or accessed via ssh-agent(1) are not supported. Not me finding out the hard way. ๐ญ
An encrypted file can be linked to the SSH public key it was encrypted to. This is so that age can identify the correct SSH private key before requesting its password, if any. It's giving thoughtful. ๐ธ
๐งฉ Plugins ๐งฉ
age can be extended through plugins. A plugin is only loaded if a corresponding RECIPIENT or IDENTITY is specified. (Simply decrypting a file encrypted with a plugin will not cause it to load, for security reasons among others.) Safety first, bestie. ๐ก๏ธ
A RECIPIENT for a plugin named example starts with age1example1, while an IDENTITY starts with AGE-PLUGIN-EXAMPLE-1. They both encode arbitrary plugin-specific data, and are generated by the plugin. Cute little namespace moment. ๐
When either is specified, age searches for age-plugin-example in the PATH and executes it to perform the file header encryption or decryption. The plugin may request input from the user through age to complete the operation. Teamwork makes the dream work. ๐ซถ
Plugins can be freely mixed with other plugins or natively supported keys. No gatekeeping. โจ
A plugin is not bound to only encrypt or decrypt files meant for or generated by the plugin. For example, a plugin can be used to decrypt files encrypted to a native X25519 RECIPIENT or even with a passphrase. Similarly, a plugin can encrypt a file such that it can be decrypted without the use of any plugin. Flexible icon behavior. ๐
Plugins for which the IDENTITY/RECIPIENT distinction doesn't make sense (such as a symmetric encryption plugin) may generate only an IDENTITY and instruct the user to perform encryption with the -e/--encrypt and -i/--identity flags. Plugins for which the concept of separate identities doesn't make sense (such as a password-encryption plugin) may instruct the user to use the -j flag. Bestie, just follow the plugin's instructions, fr fr. ๐งฉ
age can natively encrypt to recipients starting with age1tag1 (using P-256 ECDH) or age1tagpq1 (using the ML-KEM-768 + P-256 post-quantum hybrid). These are intended to be the public side of private keys held in hardware. Hardware girlies, rise. ๐โจ
They are directly supported to avoid the need to install the plugin, which may be platform-specific, on the encrypting side. Convenience ate. ๐
The tag reduces privacy, by allowing an observer to correlate files with a recipient (but not files amongst them without knowledge of the recipient), but this is also a desirable property for hardware keys that require user interaction for each decryption operation. A little tradeoff, but make it make sense. ๐
๐ EXIT STATUS ๐
okay so here's the vibe check on how age leaves the chat:
0โ it exits0if and only if encryption or decryption is successful for the full length of the input. like, the whole thing. no half-sending. ๐
no cap, this is the dramatic part: if an error happens during decryption, partial output might still get written out โ but only if it was possible to securely authenticate it. No unauthenticated output is ever released. ever. not even a crumb. ๐ซถ
๐ BACKWARDS COMPATIBILITY ๐
Files encrypted with a stable version (not alpha, beta, or release candidate) of age, or with any v1.0.0 beta or release candidate, will decrypt with any later version of the tool. so your old locked-up stuff stays unlocked, iykyk. ๐
If decrypting older files poses a security risk, doing so might cause an error by default. In this case, a flag will be provided to force the operation. so like โ the tool might be โจprotectiveโจ of you by default, and there'll be an escape hatch flag if you really need it. ๐ช
๐ EXAMPLES ๐
โจ the full pipeline: generate a post-quantum identity, encrypt, decrypt โจ
$ age-keygen -pq -o key.txt
Public key: age1pq167[... 1950 more characters ...]
$ tar cvz ~/data | age -r age1pq167[...] > data.tar.gz.age
$ age -d -o data.tar.gz -i key.txt data.tar.gz.age
like, tar it up, pipe it straight into age, and reverse it later with your key file. obsessed with the pipeline energy ๐ธ
๐ฆ encrypt example.jpg to multiple recipients ๐ฆ
and output to example.jpg.age, obviously:
$ age -o example.jpg.age -r age1pq167[...] -r age1pq1e3[...] example.jpg
two -r flags, two besties getting the file. ๐
๐ encrypt to a list of recipients ๐
$ cat > recipients.txt
# Alice
age1pq167[... 1950 more characters ...]
# Bob
age1pq1e3[... 1950 more characters ...]
$ age -R recipients.txt example.jpg > example.jpg.age
the # lines are just lil comments for your own sanity, and the capital -R is the "read this whole list" flag. ๐ซถ
๐ฅ encrypt and decrypt a file using a passphrase ๐ฅ
$ age -p secrets.txt > secrets.txt.age
Enter passphrase (leave empty to autogenerate a secure one):
Using the autogenerated passphrase "release-response-step-brand-wrap-ankle-pair-unusual-sword-train".
$ age -d secrets.txt.age > secrets.txt
Enter passphrase:
lowkey the best part: leave it empty and it literally invents a whole secure passphrase for you. and that passphrase? "release-response-step-brand-wrap-ankle-pair-unusual-sword-train". iconic. ๐ญ
๐ง passphrase-protected identity file: the combo move ๐ง
$ age-keygen | age -p > key.age
Public key: age1yhm4gctwfmrpz87tdslm550wrx6m79y9f2hdzt0lndjnehwj0ukqrjpyx5
Enter passphrase (leave empty to autogenerate a secure one):
Using the autogenerated passphrase "hip-roast-boring-snake-mention-east-wasp-honey-input-actress".
$ age -r age1yhm4gctwfmrpz87tdslm550wrx6m79y9f2hdzt0lndjnehwj0ukqrjpyx5 secrets.txt > secrets.txt.age
$ age -d -i key.age secrets.txt.age > secrets.txt
Enter passphrase for identity file "key.age":
so you pipe the freshly generated key straight into age -p and boom, your identity file is itself encrypted. main character energy. ๐
โญ encrypt and decrypt with an SSH public key โญ
$ age -R ~/.ssh/id_ed25519.pub example.jpg > example.jpg.age
$ age -d -i ~/.ssh/id_ed25519 example.jpg.age > example.jpg
you already have SSH keys, bestie. age said "say less." ๐
๐ encrypt and decrypt with age-plugin-yubikey ๐
$ age-plugin-yubikey # run interactive setup, generate identity file and obtain recipient
$ age -r age1yubikey1qwt50d05nh5vutpdzmlg5wn80xq5negm4uj9ghv0snvdd3yysf5yw3rhl3t secrets.txt > secrets.txt.age
$ age -d -i age-yubikey-identity-388178f3.txt secrets.txt.age
first line is the interactive setup (it makes your identity file and hands you the recipient), then it's just normal age business with a hardware key. hardware-backed decryption?? slay. ๐
๐ encrypt to the SSH keys of a GitHub user ๐
$ curl https://github.com/benjojo.keys | age -R - example.jpg > example.jpg.age
fetch their public keys over curl, pipe into age -R - (the - means "read the recipient list from stdin", fr fr), done. โจ
๐ SEE ALSO ๐
go read those next, they're the supporting cast and they ate. ๐
๐ AUTHORS ๐
Filippo Valsorda age@filippo.io
and that's the whole page, bestie!! ๐ฆ this was the AGE(1) manual page from August 2026 โ shipped with the tool itself, no separate version number, periodt. now go encrypt something and feel like the main character. ๐โจ๐
๐ฆ where this page comes from
- alpine 3.24: age-doc 1.3.2-r1 ยท BSD-3-Clause
- arch rolling: age 1.3.2-1 ยท BSD-3-Clause
- nixos 26.05: age 1.3.2
- nixpkgs unstable: age 1.3.2
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms