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

Generating 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.age

Encrypt with a passphrase

# Prompts for a passphrase interactively
rage -p secret.txt -o secret.txt.age

Encrypt 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.age

Decrypt

# 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.txt

Pipes 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.asc

Why 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