rage
A simple, modern, and secure file encryption tool implementing the age format, written in Rust.
rage is a Rust implementation of the age file
encryption format. age (Actually Good Encryption) was designed by Filippo
Valsorda as a simple, modern replacement for GPG — no key servers, no web of
trust, no configuration files, no footguns. Just encrypt to a public key or
passphrase, and decrypt with the corresponding private key or passphrase.
rage is the reference Rust implementation of the spec, and the most
feature-complete CLI for working with age-encrypted files.
Features
- Simple by design — a tiny, well-defined format with no configuration and very few options
- Multiple recipient types — encrypt to X25519 public keys, SSH public keys
(
~/.ssh/id_ed25519.pub,~/.ssh/id_rsa.pub), or a passphrase - Multiple recipients — encrypt a single file to multiple recipients at once; any one of them can decrypt it
- Streaming — encrypts and decrypts as a stream, so arbitrarily large files are handled efficiently without loading them fully into memory
- Armored output — optionally produce a PEM-like ASCII-armored text output for pasting into emails or config files
- Plugin support — extensible via plugins for hardware keys (YubiKey, etc.) and other backends
- No metadata leakage — the ciphertext reveals nothing about the recipients or the plaintext length beyond broad size
Installation
cargo install rage
Or via your system package manager:
# Debian / Ubuntu (Debian 12+)
apt install rage
# Fedora
dnf install rage
# macOS
brew install rage
# Arch Linux
pacman -S rage
# Nix
nix-env -iA nixpkgs.rageGenerating a key pair
# Generate a new X25519 key pair
rage-keygen -o key.txt
# Output looks like:
# Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
# (the private key is stored in key.txt)
Keep key.txt safe — it contains your private key. Share only the public key
line (starting with age1...).
Usage
Encrypt to a public key
# Encrypt a file to a recipient's public key
rage -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
secret.txt -o secret.txt.age
# Encrypt to multiple recipients (any one can decrypt)
rage \
-r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
-r age1lggyhqrw2nlhcxprm67z43rj4c3u4sezd55svlnukd4gyzdnrfjqd7z2zj \
secret.txt -o secret.txt.ageEncrypt with a passphrase
# Prompts for a passphrase interactively
rage -p secret.txt -o secret.txt.ageEncrypt to an SSH public key
# Use an existing SSH public key as the recipient
rage -r "$(cat ~/.ssh/id_ed25519.pub)" secret.txt -o secret.txt.age
# Or reference it directly
rage -R ~/.ssh/id_ed25519.pub secret.txt -o secret.txt.ageDecrypt
# Decrypt using a private key file
rage -d -i key.txt secret.txt.age -o secret.txt
# Decrypt using an SSH private key
rage -d -i ~/.ssh/id_ed25519 secret.txt.age -o secret.txt
# Decrypt a passphrase-encrypted file (prompts interactively)
rage -d secret.txt.age -o secret.txtPipes and streams
# Encrypt stdin to stdout
tar czf - ./mydir | rage -r age1... -o archive.tar.gz.age
# Decrypt to stdout and pipe onward
rage -d -i key.txt archive.tar.gz.age | tar xzf -ASCII armoring
# Produce ASCII-armored output (safe to paste in text)
rage -r age1... -a secret.txt -o secret.txt.age.ascWhy not GPG?
GPG is notoriously difficult to use correctly — keys expire, keyrings get
corrupted, the trust model is complex, and the output format leaks metadata. age
(and rage) strips all of that away:
- No key servers, no expiry, no revocation complexity
- No configuration files to get wrong
- A key is just a short string you can copy-paste or save in a password manager
- The format is simple enough to be audited and re-implemented easily