rage
A simple, secure and modern file encryption tool (and Rust library) with small explicit keys, no config options, and UNIX-style composability.
Top Related Projects
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
A dead simple tool to sign files and verify digital signatures.
a modern crypto messaging format
Simple and flexible tool for managing secrets
Tink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.
A high-level OpenPGP library
Quick Overview
The str4d/rage
repository is a Rust library that provides a high-performance, memory-safe, and cryptographically secure implementation of the Ristretto group, which is a prime-order group suitable for use in cryptographic protocols. It is designed to be a building block for higher-level cryptographic primitives and applications.
Pros
- High Performance: The library is optimized for speed and efficiency, making it suitable for use in performance-critical applications.
- Memory Safety: The Rust programming language's strong type system and ownership model help ensure that the library is memory-safe, reducing the risk of common security vulnerabilities.
- Cryptographic Security: The Ristretto group is a well-studied and secure elliptic curve group, providing a strong foundation for cryptographic applications.
- Modular Design: The library is designed to be a building block for higher-level cryptographic primitives and applications, making it easy to integrate into larger projects.
Cons
- Limited Documentation: The project's documentation, while generally good, could be more comprehensive, especially for users new to Rust or cryptography.
- Niche Use Case: The Ristretto group is a relatively specialized cryptographic primitive, so the library may not be relevant for all projects.
- Dependency on Rust: The library is written in Rust, which may be a barrier for developers who are more familiar with other programming languages.
- Ongoing Maintenance: As with any open-source project, the long-term maintenance and support of the library may be a concern for some users.
Code Examples
Here are a few examples of how to use the str4d/rage
library:
- Generating a Ristretto Point:
use rage::ristretto::RistrettoPoint;
let point = RistrettoPoint::random(&mut rand::thread_rng());
println!("Random Ristretto point: {}", point);
- Performing Scalar Multiplication:
use rage::ristretto::RistrettoPoint;
use rand::Rng;
let mut rng = rand::thread_rng();
let scalar: [u8; 32] = rng.gen();
let point = RistrettoPoint::random(&mut rng);
let result = point * scalar;
println!("Scalar multiplication result: {}", result);
- Verifying a Ristretto Point:
use rage::ristretto::RistrettoPoint;
let point = RistrettoPoint::from_bytes(&[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
]);
if point.is_valid() {
println!("The point is valid!");
} else {
println!("The point is not valid.");
}
Getting Started
To get started with the str4d/rage
library, you'll need to have Rust installed on your system. You can then add the library as a dependency in your Cargo.toml file:
[dependencies]
rage = "0.6.1"
Once you've added the dependency, you can start using the library in your Rust code. Here's a simple example that demonstrates how to generate a random Ristretto point and perform scalar multiplication:
use rage::ristretto::RistrettoPoint;
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
// Generate a random Ristretto point
let point = RistrettoPoint::random(&mut rng);
Competitor Comparisons
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
Pros of age
- Written in Go, which offers better performance and easier deployment
- More mature project with a larger community and ecosystem
- Supports additional features like SSH key encryption
Cons of age
- Less flexible API for integration into other projects
- Slower development cycle and fewer recent updates
- Limited support for non-UNIX platforms
Code Comparison
age:
recipient, err := age.ParseX25519Recipient(pubKey)
if err != nil {
log.Fatalf("Failed to parse public key: %v", err)
}
rage:
let recipient = age::x25519::Recipient::from_str(pub_key)?;
Both projects implement the age encryption protocol, but rage is written in Rust while age is written in Go. The code snippets show how to create a recipient from a public key in each library.
rage offers a more idiomatic Rust API with better error handling through the Result
type, while age uses Go's traditional error handling approach. The rage implementation is more concise and leverages Rust's type system for improved safety.
Overall, age is more established and widely used, while rage provides a Rust-native implementation with a more ergonomic API for Rust developers. The choice between them often depends on the programming language preference and specific project requirements.
A dead simple tool to sign files and verify digital signatures.
Pros of minisign
- Simpler and more focused on file signing
- Lightweight and easy to use
- Cross-platform compatibility
Cons of minisign
- Limited to file signing, lacks encryption capabilities
- Fewer features compared to rage's comprehensive toolset
Code comparison
minisign:
minisign -Sm myfile.txt
minisign -Vm myfile.txt -P RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3
rage:
rage -e -o myfile.txt.age myfile.txt
rage -d -i key.txt myfile.txt.age
Key differences
- minisign focuses on file signing and verification
- rage offers both encryption and signing capabilities
- minisign uses Ed25519 signatures, while rage supports multiple encryption algorithms
- rage provides a more comprehensive set of features for secure communication and file handling
Use cases
minisign is ideal for:
- Simple file signing and verification
- Scenarios where lightweight, focused tools are preferred
rage is better suited for:
- Comprehensive secure communication needs
- Projects requiring both encryption and signing capabilities
- Situations where flexibility in encryption algorithms is necessary
Both tools prioritize security and ease of use, but cater to different needs in the cryptographic toolset landscape.
a modern crypto messaging format
Pros of Saltpack
- More established project with longer history and wider adoption
- Supports multiple message formats (encryption, signing, detached signing)
- Designed for both human-readable and binary output
Cons of Saltpack
- More complex implementation with additional dependencies
- Slower performance for large file encryption
- Less active development in recent years
Code Comparison
Saltpack encryption example:
encrypted, err := saltpack.Encrypt(
message,
saltpack.NewKeyring(senderSecretKey),
[]saltpack.BoxPublicKey{recipientPublicKey},
)
Rage encryption example:
let encrypted = age::Encryptor::with_recipients(vec![recipient])
.encrypt_bytes(&message)?;
Key Differences
- Rage focuses on simplicity and performance, while Saltpack offers more features
- Rage uses the Age encryption format, Saltpack uses its own custom format
- Rage is implemented in Rust, Saltpack in Go (with bindings for other languages)
- Rage has a more active development community currently
Both projects aim to provide secure, modern encryption tools for developers and end-users, but with different approaches to design and implementation. Rage prioritizes simplicity and performance, while Saltpack offers a broader range of features and message formats.
Simple and flexible tool for managing secrets
Pros of sops
- Supports multiple key management systems (AWS KMS, GCP KMS, Azure Key Vault, etc.)
- Allows partial encryption of files, maintaining structure for easy editing
- Integrates well with version control systems and CI/CD pipelines
Cons of sops
- More complex setup and configuration compared to rage
- Requires external key management services for full functionality
- May have a steeper learning curve for new users
Code comparison
sops:
myapp:
db:
user: ENC[AES256_GCM,data:...] # Encrypted value
password: ENC[AES256_GCM,data:...] # Encrypted value
rage:
age-encryption.org/v1
-> X25519 yXNuRQyPo7W1oT9sHpMvfg1WTHNWcdLCgyx9QLzPukU
... (encrypted content)
Summary
sops offers more flexibility and integration options, making it suitable for complex enterprise environments. It excels in scenarios requiring partial file encryption and integration with cloud key management services. rage, on the other hand, provides a simpler, file-based encryption approach that may be more appropriate for individual users or smaller projects with straightforward encryption needs.
Tink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.
Pros of Tink
- Broader cryptographic functionality, including digital signatures, MACs, and hybrid encryption
- Extensive language support (C++, Java, Go, Python, JavaScript)
- Backed by Google, potentially offering more resources and long-term support
Cons of Tink
- More complex API and setup process
- Larger codebase and dependencies, potentially increasing attack surface
- Less focused on age encryption format compatibility
Code Comparison
Tink (encryption example):
keysetHandle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate())
a, err := aead.New(keysetHandle)
ciphertext, err := a.Encrypt(plaintext, associatedData)
Rage (encryption example):
let encryptor = age::Encryptor::with_recipients(vec![recipient])
.expect("failed to create encryptor");
let mut encrypted = vec![];
let mut writer = encryptor.wrap_output(&mut encrypted)?;
writer.write_all(message.as_bytes())?;
writer.finish()?;
Both libraries offer encryption functionality, but Tink provides a more generalized approach with its keysetHandle and AEAD interface, while Rage focuses specifically on the age encryption format with a more streamlined API.
A high-level OpenPGP library
Pros of gopenpgp
- Developed by ProtonMail, a well-known privacy-focused company
- Extensive support for OpenPGP standard, including key management and encryption
- Well-documented API with examples for various use cases
Cons of gopenpgp
- Larger codebase and potentially more complex to integrate
- Focused primarily on OpenPGP, which may be overkill for simpler encryption needs
- Slower development pace compared to rage
Code Comparison
gopenpgp:
publicKey, err := crypto.NewKeyFromArmored(publicKeyString)
message := crypto.NewPlainMessage([]byte("Hello, World!"))
encrypted, err := publicKey.Encrypt(message, nil)
rage:
let public_key = age::x25519::Recipient::from_str(public_key_string)?;
let encrypted = age::Encryptor::with_recipients(vec![Box::new(public_key)])
.encrypt_bytes(b"Hello, World!")?;
Both libraries provide encryption functionality, but rage offers a more streamlined API for simple encryption tasks, while gopenpgp provides more comprehensive OpenPGP features.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
rage: Rust implementation of age
rage is a simple, modern, and secure file encryption tool, using the age format. It features small explicit keys, no config options, and UNIX-style composability.
The format specification is at age-encryption.org/v1. age was designed by @Benjojo and @FiloSottile.
The reference interoperable Go implementation is available at filippo.io/age.
Hardware PIV tokens such as YubiKeys are supported through the age-plugin-yubikey plugin.
For more plugins, implementations, tools, and integrations, check out the awesome age list.
Installation
Environment | CLI command |
---|---|
Cargo (Rust 1.65+) | cargo install rage |
Homebrew (macOS or Linux) | brew install rage |
MacPorts | port install rage |
Alpine Linux (edge) | apk add rage |
Arch Linux | pacman -S rage-encryption |
Debian | Debian packages |
NixOS | Add to config: environment.systemPackages = [ pkgs.rage ]; Or run nix-env -i rage |
openSUSE Tumbleweed | zypper install rage-encryption |
Ubuntu 20.04+ | Debian packages |
FreeBSD | pkg install rage-encryption |
Scoop (Windows) | scoop bucket add main scoop install main/rage |
On Windows, Linux, and macOS, you can use the pre-built binaries.
Help from new packagers is very welcome. Please use the package name
rage
; the fallback package namerage-encryption
should be used only when there are unavoidable name conflicts in package systems that use global namespaces. Do not rename any binaries; instead use your package system's conflicting package mechanism to prevent installation of both packages at once.
Usage
Usage: rage [--encrypt] (-r RECIPIENT | -R PATH)... [-i IDENTITY] [-a] [-o OUTPUT] [INPUT]
rage [--encrypt] --passphrase [-a] [-o OUTPUT] [INPUT]
rage --decrypt [-i IDENTITY] [-o OUTPUT] [INPUT]
Arguments:
[INPUT] Path to a file to read from.
Options:
-h, --help Print this help message and exit.
-V, --version Print version info and exit.
-e, --encrypt Encrypt the input (the default).
-d, --decrypt Decrypt the input.
-p, --passphrase Encrypt with a passphrase instead of recipients.
--max-work-factor <WF> Maximum work factor to allow for passphrase decryption.
-a, --armor Encrypt to a PEM encoded format.
-r, --recipient <RECIPIENT> Encrypt to the specified RECIPIENT. May be repeated.
-R, --recipients-file <PATH> Encrypt to the recipients listed at PATH. May be repeated.
-i, --identity <IDENTITY> Use the identity file at IDENTITY. May be repeated.
-j <PLUGIN-NAME> Use age-plugin-PLUGIN-NAME in its default mode as an identity.
-o, --output <OUTPUT> Write the result to the file at path OUTPUT.
INPUT defaults to standard input, and OUTPUT defaults to standard output.
If OUTPUT exists, it will be overwritten.
RECIPIENT can be:
- An age public key, as generated by rage-keygen ("age1...").
- An SSH public key ("ssh-ed25519 AAAA...", "ssh-rsa AAAA...").
PATH is a path to a file containing age recipients, one per line
(ignoring "#" prefixed comments and empty lines). "-" may be used to
read recipients from standard input.
IDENTITY is a path to a file with age identities, one per line
(ignoring "#" prefixed comments and empty lines), or to an SSH key file.
Passphrase-encrypted age identity files can be used as identity files.
Multiple identities may be provided, and any unused ones will be ignored.
"-" may be used to read identities from standard input.
Multiple recipients
Files can be encrypted to multiple recipients by repeating -r/--recipient
.
Every recipient will be able to decrypt the file.
$ rage -o example.png.age -r age1uvscypafkkxt6u2gkguxet62cenfmnpc0smzzlyun0lzszfatawq4kvf2u \
-r age1ex4ty8ppg02555at009uwu5vlk5686k3f23e7mac9z093uvzfp8sxr5jum example.png
Recipient files
Multiple recipients can also be listed one per line in one or more files passed
with the -R/--recipients-file
flag.
$ cat recipients.txt
# Alice
age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
# Bob
age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg
$ rage -R recipients.txt example.jpg > example.jpg.age
If the argument to -R
(or -i
) is -
, the file is read from standard input.
Passphrases
Files can be encrypted with a passphrase by using -p/--passphrase
. By default
rage will automatically generate a secure passphrase.
$ rage -p -o example.png.age example.png
Type passphrase (leave empty to autogenerate a secure one): [hidden]
Using an autogenerated passphrase:
kiwi-general-undo-bubble-dwarf-dizzy-fame-side-sunset-sibling
$ rage -d example.png.age >example.png
Type passphrase: [hidden]
If a binary named pinentry
is available in $PATH
, it will be used to ask the
user for a passphrase. The PINENTRY_PROGRAM
environment variable can be used
to set the binary name or path to use. If a pinentry
binary is not available,
or PINENTRY_PROGRAM
is set to the empty string, rage
will fall back to the
CLI instead.
Passphrase-protected identity files
If an identity file passed to -i/--identity
is a passphrase-encrypted age
file, it will be automatically decrypted.
$ rage -p -o key.age <(rage-keygen)
Public key: age1pymw5hyr39qyuc950tget63aq8vfd52dclj8x7xhm08g6ad86dkserumnz
Type passphrase (leave empty to autogenerate a secure one): [hidden]
Using an autogenerated passphrase:
flash-bean-celery-network-curious-flower-salt-amateur-fence-giant
$ rage -r age1pymw5hyr39qyuc950tget63aq8vfd52dclj8x7xhm08g6ad86dkserumnz secrets.txt > secrets.txt.age
$ rage -d -i key.age secrets.txt.age > secrets.txt
Type passphrase: [hidden]
Passphrase-protected identity files are not necessary for most use cases, where access to the encrypted identity file implies access to the whole system. However, they can be useful if the identity file is stored remotely.
SSH keys
As a convenience feature, rage also supports encrypting to ssh-rsa
and
ssh-ed25519
SSH public keys, and decrypting with the respective private key
file. (ssh-agent
is not supported.)
$ rage -R ~/.ssh/id_ed25519.pub example.png > example.png.age
$ rage -d -i ~/.ssh/id_ed25519 example.png.age > example.png
Note that SSH key support employs more complex cryptography, and embeds a public key tag in the encrypted file, making it possible to track files that are encrypted to a specific public key.
Feature flags
When building with Cargo, you can configure rage using --no-default-features
and --features comma,separated,flags
to enable or disable the following
feature flags:
-
mount
enables therage-mount
tool, which can mount age-encrypted TAR or ZIP archives as read-only. It is currently only usable on Unix systems, as it relies onlibfuse
. -
ssh
(enabled by default) enables support for reusing existing SSH key files for age encryption. -
unstable
enables in-development functionality. Anything behind this feature flag has no stability or interoperability guarantees.
Rust Library
Applications wishing to use rage as a library should use the age
crate, which rage is built on top of.
License
Licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Top Related Projects
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
A dead simple tool to sign files and verify digital signatures.
a modern crypto messaging format
Simple and flexible tool for managing secrets
Tink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.
A high-level OpenPGP library
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot