age
(Actually Good Encryption)
Overview
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
age
age-keygen
The age-keygen
CLI creates an asymmetic identity key;
a public-private key of type Ed25519
(X25519) exclusively.
Yet age
also works with SSH (ssh-rsa
and ssh-ed25519
) keys,
and so natively integrates with Git projects.
Encryption and decryption of the subject message is by a symmetric key generated per message. That key, along with public (asymmetric) key(s) of the recipient(s), are added to the encrypted subject message to form the resulting AEAD package (encrypted and signed). Only the recipient(s) private key(s) can decrypt it, and only if the cleartext signature (AD) of the package verifies.
All these internals are transparent to the user.
The result includes a binary by default. The optional PEM encoded (armor) format, though somewhat larger, has more use cases; allows for embedding in JSON and such, and transmits by HTTP more reliably.
Install
Available methods:
# Pkg @ Ubuntu
sudo apt -y install age
# Pkg @ Fedora
sudo dnf -y install age
# Binary method
archive=https://dl.filippo.io/age/latest?for=linux/amd64
curl -sSfL $archive -o age.tar.gz &&
tar -xaf age.tar.gz &&
sudo cp age/age* /usr/local/bin/
# Build/Install from (internet) source
# 1. Install Golang
v=1.24.1
archive=go$v.linux-amd64.tar.gz
[[ $(type -t go >/dev/null 2>&1 && go version |grep $v) ]] ||
rm -rf /usr/local/go$v &&
curl -sSfLO https://go.dev/dl/$archive &&
sudo tar -C /usr/local -xzf $archive &&
sudo mv /usr/local/go /usr/local/go$v &&
export PATH="$PATH:/usr/local/go$v/bin"
# 2. Build/Install age and age-keygen
type -t go && go install filippo.io/age/cmd/...@latest
# Build from local source
git clone github:/FiloSottile/age.git
cd age
go build ./cmd/age
go build ./cmd/age-keygen
Usage
Encrypt/Decrypt a file using a new X25519 key pair
# Plaintext file
secret=secrets.yaml
# Create X25519 key-pair file
key=age-keypair.txt
age-keygen -o $key
# Encrypt
age -r $(age-keygen -y $key) -o $secret.age $secret
# Decrypt to STDOUT
age -d -i $key $secret.age
- Unlike
sops
, file format is preserved.
Encrypt/Decrypt using a passphrase, which is autogenerated and shown if not declared at prompt. That passphrase alone decrypts the message.
# Encrypt to PEM encoded (armor) format
age -a -p $secret > $secret.pem
# Decrypt to stdout; PROMPTS for passphrase.
age -d $secret.pem
Encrypt for recipient(s) having SSH key pair(s)
# @ Encrypt for SSH recipients
age -e -R ~/.ssh/recipient-1.pub -R ~/.ssh/recipient-2.pub -o $secret.age $secret
- To encrypt for multiple recipients, use multiple "
-R ...
"
Encrypt to PEM encoded (armor) format for a recipient having an SSH key pair with its public key at their GitHub account.
curl -s https://github.com/$account.keys \
|age -R - -a -o $secret.age $secret
Recipient decrypts it (to stdout) using the private key (identity) of that pair.
# @ Decrypt using recipient's private key
age -d -i ~/.ssh/identity-1 -o - $secret.age
Encrypt a folder archive
# Create key pair
key=key.txt
age-keygen -o $key
# Get public key AKA recipient
pub=$(age-keygen -y $key)
# Encrypt (the archive of a dir)
dir=~/data
tar -cvz $dir |age -r $pub > $dir.tar.gz.age
# Decrypt
age --decrypt -i $key $dir.tar.gz.age > $dir.tar.gz
- Multiple recipients allowed; one per flag
-r PUB
: Recipient-R PUB_FILE
: Recipient file
Create X25519 key pair using age-keygen
.
☩ age-keygen
# created: 2025-01-07T16:23:58-05:00
# public key: age1dtyyjt0afm8ecu8plwyzxhu22mz0t7j2zzu9ddkq7qsafk7c54qq8rzqe0
AGE-SECRET-KEY-1YCVWNEFFR7QQ5PJ37UMWDNE8JFZGYUXP5K9G29J3R0387ZLCUN2QZARH80
-o
,--output
FILE
: Write the resulting identity (X25529 key pair) toFILE
(path)-y FILE
: Convert the identity file (X25519 key pair) to recipient.- This extracts the public-key string from the X25519 key-pair file located at
FILE
.
- This extracts the public-key string from the X25519 key-pair file located at