rage is a simple, modern, and secure file encryption tool, using the age format

Overview

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. To discuss the spec or other age related topics, please email the mailing list at [email protected]. age was designed by @Benjojo12 and @FiloSottile.

The reference interoperable Go implementation is available at filippo.io/age.

Usage

Usage:
  rage [--encrypt] -r RECIPIENT [-i IDENTITY] [-a] [-o OUTPUT] [INPUT]
  rage --decrypt [-i IDENTITY] [-o OUTPUT] [INPUT]

Positional arguments:
  INPUT                       Path to a file to read from.

Optional arguments:
  -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.
  -o, --output OUTPUT         Write the result to the file at path OUTPUT.

INPUT defaults to standard input, and OUTPUT defaults to standard output.

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

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.

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

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]

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.

Installation

On macOS or Linux, you can use Homebrew:

brew tap str4d.xyz/rage https://str4d.xyz/rage
brew install rage

On Windows, Linux, and macOS, you can use the pre-built binaries.

If your system has Rust 1.51+ installed (either via rustup or a system package), you can build directly from source:

cargo install rage

Note: previously the rage suite of tools was provided in the age Rust crate. This is no longer the case; age now only contains the Rust library.

Help from new packagers is very welcome.

Feature flags

  • mount enables the rage-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 on libfuse.

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

License

Licensed under either of

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.

Issues
  • Unicode feast in time of COVID19 plague

    Unicode feast in time of COVID19 plague

    Windows 7, rage 0.5.1

    [?] marks are related neither to the chosen console font, nor to the code page (866, 1251, 65001). 0.4.0 was the last one w/o them. Consider figuring out who’s responsible for this freaking decoration.

    opened by sergeevabc 12
  • Compile to WASM

    Compile to WASM

    Let's make the age crate usable in WASM!

    opened by str4d 11
  • YubiKey plugin

    YubiKey plugin

    Discuss this draft on the age-dev mailing list thread!

    Current draft specification:

    age PIV identities use ECC P-256 keys, generated on the hardware token, with certificates that never expire.

    For hardware tokens that support PIN and/or touch policies (such as YubiKeys), the default PIN policy is "once per session", and the default touch policy is "every decryption".

    A PIV recipient has the following form:

    Bech32("age1piv", SEC-1-C(public key))
    

    where SEC-1-C is the 33-byte compressed SEC-1 encoding.

    A PIV recipient line is of the form:

    -> piv encode(SHA-256(recipient)[:4]) encode(SEC-1-C(ECDH(ephemeral secret, p256-basepoint)))\n
    encode(encrypt[HKDF[salt, label](ECDH(ephemeral secret, public key))](file key))\n
    

    where ephemeral secret is a random scalar within the scalar field of P-256 and MUST be new for every file key, salt is SEC-1-C(ECDH(ephemeral secret, basepoint)) || SEC-1-C(public key), and label is age-encryption.org/v1/piv.

    A YubiKey "identity" is managed locally as a key stub with the following form:

    Uppercase(Bech32("age-yubikey-stub-", serial || slot || SHA-256(recipient)[:4]))
    

    The stub may exist in files alongside age X25519 secret keys, and is similarly passed to the age / rage binary with the -i flag.

    Note that the common tag in the recipient line and key stub means that recipients can trivially identify whether they can decrypt a particular recipient line, at the cost of making recipients linkable across different encrypted files.


    Usage example (responses out-of-date):

    $ cargo install --path . --features yubikey
    $ rage-keygen --yubikey -o keystub.txt
    Enter PIN for YubiKey with serial 12345678: [hidden]
    Use the up/down arrow keys to select a PIV slot (q to quit): Retired(R1) (Empty)
    Select a PIN policy: Once   (A PIN is required once per session, if set)
    Select a touch policy: Always (A physical touch is required for every decryption),
    Generate new key in Retired(R1) slot? yes
    $ cat keystub.txt 
    # created: 2019-12-07T23:13:09Z
    # yubikey:A_y2TWFFIZ8AhuFCjpxGzt_qiZrwMfEyDG6M8fqgG3ET
    AGE_YUBIKEY_STUB_00bc614e_9d_6ecc74ff
    $ echo "YubiKey FTW!" | rage -o test.age -r yubikey:A_y2TWFFIZ8AhuFCjpxGzt_qiZrwMfEyDG6M8fqgG3ET
    $ rage -d -i keystub.txt test.age
    Enter PIN for YubiKey with serial 12345678: [hidden]
    YubiKey FTW!
    
    opened by str4d 11
  • `cargo install rage` fails

    `cargo install rage` fails

    Environment

    • OS: Linux
    • rage version: v0.5.0

    What were you trying to do

    What happened

    Using:
       stable-x86_64-unknown-linux-gnu unchanged - rustc 1.49.0 (e1884a8e3 2020-12-29)
       
     $ cargo install rage
         Updating crates.io index
      Installing rage v0.5.0
     (...)
     error[E0599]: no method named `insert_and_get` found for struct `DOMAINS` in the current scope
       --> /home/gw/.cargo/registry/src/github.com-1ecc6299db9ec823/i18n-embed-fl-0.2.0/src/lib.rs:360:17
        |
    136 | / lazy_static::lazy_static! {
    137 | |     /// Cached data specific to each localization domain, to improve
    138 | |     /// performance of subsequent macro invokations.
    139 | |     static ref DOMAINS: dashmap::DashMap<String, DomainSpecificData> =
    140 | |         dashmap::DashMap::new();
    141 | | }
        | |_- method `insert_and_get` not found for this
    ...
    360 |           DOMAINS.insert_and_get(domain.clone(), data)
        |                   ^^^^^^^^^^^^^^ method not found in `DOMAINS`
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0599`.
    error: could not compile `i18n-embed-fl`
    
    To learn more, run the command again with --verbose.
    warning: build failed, waiting for other jobs to finish...
    error: failed to compile `rage v0.5.0`, intermediate artifacts can be found at `/tmp/cargo-installJwMnWy`
    
    Caused by:
      build failed
    
    
    opened by gwpl 10
  • Performance improvements

    Performance improvements

    The performance improvement comes from the upgraded chacha20 dependency. Performance is slightly improved by default, and compiling with RUSTFLAGS="-Ctarget-feature=+avx2" will boost performance significantly.

    Part of #57.

    opened by str4d 10
  • Rage refuses to write to stdout even when armor is enabled

    Rage refuses to write to stdout even when armor is enabled

    PS C:\Users\Alice> rage -r age1wssqv0rf9ctp5w7j3dfmngurhe2xrj5869rv9x8a0gex5r0f6ejqy0prkw -a .\Desktop\age.txt
    Error: not printing to stdout
    
    [ Did rage not do what you expected? Could an error be more useful? ]
    [ Tell us: https://github.com/str4d/rage/issues/new/choose          ]
    
    opened by alajpie 7
  • i18n-embed-fl 0.3

    i18n-embed-fl 0.3

    Fixes an issue where cargo update breaks builds (due to how i18n-embed-fl 0.2 was not pinning its pre-release dashmap dependency).

    opened by str4d 7
  • add Identity support for RSA PKCS#8 nocrypt

    add Identity support for RSA PKCS#8 nocrypt

    Hi @str4d,

    I realize that this feature is unlikely to see much use in practice, but I picked an old issue that seemed simple enough for a very new rustacean to be able to tackle (first real attempt at Rust).


    fully parse unencrypted PKCS#8 RSA private key

    parse encrypted PKCS#8 enough to recognize it as an unsupported key format

    add test coverage for key format support

    • PEM (PKCS#1) unencrypted RSA (supported)
    • PEM (PKCS#1) encrypted RSA (never support)
    • PKCS#8 unencrypted RSA (supported)
    • PKCS#8 encrypted (not supported, yet?)

    fixes #14

    opened by dwhjames 6
  • Add -j flag for invoking data-less plugins

    Add -j flag for invoking data-less plugins

    Some plugins (like yubikey-agent, or an sshpass equivalent) just need the user to inform rage that they exist and should be used, but not to actually pass any data across. A user can currently achieve this with an "empty plugin identity", which looks like:

    AGE-PLUGIN-NAME-1SIXCHR

    where name is the plugin name, and SIXCHR is the Bech32 checksum. This has two UX flaws:

    • The empty identity is a "magic string", that users need to know about in order to use these plugins.
    • It needs to go into a file (since -i only accepts files). For a user that only uses yubikey-agent this would mean having a loose file around with a single magic string, the location of which they need to remember.

    In a long UX discussion with @FiloSottile and @benjojo, we decided to add a new -j flag, which does this all for the user. When rage sees -j name, it internally behaves as if it had seen a -i file where the file contained AGE-PLUGIN-NAME-1SIXCHR (with valid checksum).

    This has a downstream effect on plugins: they can now distinguish a "default" behaviour. If a plugin only normally gives out plugin identities containing data, they can behave differently if they are sent (via the plugin protocol) an add-identity command with a known plugin name but empty data. This could be used to e.g. decrypt with a default set of identities, instead of a specific one.

    -j is intended to be handled in-line with -i for deterministic decryption (#236). For simplicity, rage will only support a single -j flag, and make it incompatible with -i flags.

    opened by str4d 6
  • [FEATURE] Please create homebrew package for OSX

    [FEATURE] Please create homebrew package for OSX

    While I'm personally fine compiling this with cargo I've noticed adoption tends to be much easier for folks on osx if you provide a homebrew package to give you something like brew install rage (which is both useful and hilarious as a command... 😜 )

    Could we have one? (or I could take a shot at a formula for it though never done it myself.).

    thanks! Daryl.

    opened by wakatara 6
  • build(deps): bump codecov/codecov-action from 2.0.3 to 2.1.0

    build(deps): bump codecov/codecov-action from 2.0.3 to 2.1.0

    Bumps codecov/codecov-action from 2.0.3 to 2.1.0.

    Release notes

    Sourced from codecov/codecov-action's releases.

    v2.1.0

    2.1.0

    Features

    • #515 Allow specifying version of Codecov uploader

    Dependencies

    • #499 build(deps-dev): bump @​vercel/ncc from 0.29.0 to 0.30.0
    • #508 build(deps): bump openpgp from 5.0.0-5 to 5.0.0
    • #514 build(deps-dev): bump @​types/node from 16.6.0 to 16.9.0
    Changelog

    Sourced from codecov/codecov-action's changelog.

    2.1.0

    Features

    • #515 Allow specifying version of Codecov uploader

    Dependencies

    • #499 build(deps-dev): bump @​vercel/ncc from 0.29.0 to 0.30.0
    • #508 build(deps): bump openpgp from 5.0.0-5 to 5.0.0
    • #514 build(deps-dev): bump @​types/node from 16.6.0 to 16.9.0
    Commits
    • f32b3a3 Merge pull request #515 from codecov/specify-version
    • 72dfd47 Allow specifying version of Codecov uploader
    • 46edaed Merge pull request #499 from codecov/dependabot/npm_and_yarn/vercel/ncc-0.30.0
    • b6fd8cc Merge pull request #508 from codecov/dependabot/npm_and_yarn/openpgp-5.0.0
    • 07a4e97 build(deps-dev): bump @​vercel/ncc from 0.29.0 to 0.30.0
    • c071c70 build(deps): bump openpgp from 5.0.0-5 to 5.0.0
    • f6d4366 Merge pull request #514 from codecov/dependabot/npm_and_yarn/types/node-16.9.0
    • 2bbefc9 build(deps-dev): bump @​types/node from 16.6.0 to 16.9.0
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 1
  • Crate cleanups

    Crate cleanups

    null

    opened by str4d 0
  • use pkcs1 crate to parse RSAPrivateKey ASN.1 object

    use pkcs1 crate to parse RSAPrivateKey ASN.1 object

    following from review conversation: https://github.com/str4d/rage/pull/260#issuecomment-917665743

    references:

    opened by dwhjames 0
  • build(deps): bump actions/download-artifact from 1 to 2.0.10

    build(deps): bump actions/download-artifact from 1 to 2.0.10

    Bumps actions/download-artifact from 1 to 2.0.10.

    Release notes

    Sourced from actions/download-artifact's releases.

    v2.0.10

    • Retry on HTTP 500 responses from the service

    v2.0.9

    • Fixes to proxy related issues

    v2.0.8

    • Improvements to retryability if an error is encountered during artifact download

    v2.0.7 download-artifact

    • Improved download retry-ability if a partial download is encountered

    v2.0.6

    Update actions/core NPM package that is used internally

    v2.0.5

    • Add Third Party License Information

    v2.0.4

    • Use the latest version of the @actions/artifact NPM package

    v2.0.3

    • Misc improvements

    v2.0.2

    • Support for tilde expansion

    v2.0.1

    • Download path output
    • Improved logging
    Commits
    • 3be87be Ingest v0.5.2 of @​actions/artifact (#100)
    • 8bef1ad Merge pull request #97 from actions/dependabot/npm_and_yarn/glob-parent-5.1.2
    • 2940e0d Merge pull request #92 from actions/dependabot/npm_and_yarn/hosted-git-info-2...
    • bd90b34 Merge pull request #91 from actions/dependabot/npm_and_yarn/lodash-4.17.21
    • 3b6d0ab Merge pull request #99 from actions/brcrista/dependabot-push
    • 46a6d6f Don't trigger CodeQL on Dependabot push
    • 246a0f4 Bump glob-parent from 5.1.1 to 5.1.2
    • df388c9 Clarified the v1 and v2 differences (#96)
    • 87f717a Bump hosted-git-info from 2.8.5 to 2.8.9
    • ae44515 Bump lodash from 4.17.19 to 4.17.21
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 2
  • Have debs link against musl libc instead of glibc

    Have debs link against musl libc instead of glibc

    Fixes https://github.com/str4d/rage/issues/252

    Hopefully this is correct. I probably should add the incantation to statically link to the C runtime.

    opened by ethanhs 0
  • Link to musl instead of glibc for .deb files

    Link to musl instead of glibc for .deb files

    Environment

    • OS: Debian stretch/buster
    • rage version: 0.6.0

    I recently set up an apt repo for Rust command line tools at https://apt.0xe.me, and I was hoping to add rage. However, to support the widest set of OS versions, linking to musl libc seems to give the best portability.

    Would you consider linking your .deb files to musl instead of glibc?

    Edit: See e.g. this ripgrep issue where linking to glibc was an issue: https://github.com/BurntSushi/ripgrep/issues/1890

    opened by ethanhs 8
  • RUSTSEC-2020-0077: memmap is unmaintained

    RUSTSEC-2020-0077: memmap is unmaintained

    memmap is unmaintained

    | Details | | | ------------------- | ---------------------------------------------- | | Status | unmaintained | | Package | memmap | | Version | 0.7.0 | | URL | https://github.com/danburkert/memmap-rs/issues/90 | | Date | 2020-12-02 |

    The author of the memmap crate is unresponsive.

    Maintained alternatives:

    See advisory page for additional details.

    opened by github-actions[bot] 1
  • rage-mount-dir: OverlayFS that transparently decrypts age-encrypted files

    rage-mount-dir: OverlayFS that transparently decrypts age-encrypted files

    Usage: rage-mount-dir -i IDENTITY [-i IDENTITY ..] DIRECTORY MOUNT_POINT

    • The caller provides a directory to be mounted, and some age identities.
    • The directory is transparently mounted at a provided destination.
    • Any *.age files inside the directory's subtree are checked for decryptability (by the given identities) on first interaction (when the directory containing the file is read).
      • If an age file can be decrypted, it is shown inside the mount point without its .age suffix, and with a filesize equivalent to the decrypted file.
      • If an age file cannot be decrypted, it is show unmodified inside the mount point.
    • On read, normal files and undecryptable age files are read as-normal, while decryptable age files are transparently decrypted.

    Part of #188.

    opened by str4d 1
  • Figure out which targets have terminals that support Unicode Directionality Isolation Marks

    Figure out which targets have terminals that support Unicode Directionality Isolation Marks

    We turned them off in #220 but we can probably do better, by only disabling them on platforms that don't support them by default.

    opened by str4d 0
  • rage package naming

    rage package naming

    While wanting to package your rage program I realized package and binary name will probably conflict with Rage [0] that is already available in the target linux distribution as "rage".

    Do you know if others ran into this situation as well and how they solved it?

    Does this upstream project has preferences if and what alternative name I can use instead (rustage, ager, ...) ?

    Do you have experience/ideas what parts of the code have to be touched/changed downstream to use a different name than "rage"?

    Is it maintainable by replacing some strings programatically or are issues and new bugs likely if I have to change name, man pages, bash completetion, ... and propably more in order to make it work with a different name?

    Thank you for this software!

    [0] https://www.enlightenment.org/about-rage

    opened by cunyx 5
Releases(v0.6.0)
  • v0.6.0(May 1, 2021)

    rage

    Added

    • Plugin support!
      • The new age-plugin crate provides a Rust API for building age plugins.
      • See https://hackmd.io/@str4d/age-plugin-spec for the beta specification.
    • The -R/--recipients-file flag, which accepts a path to a file containing age recipients, one per line (ignoring "#" prefixed comments and empty lines).
    • The -e/--encrypt flag, to allow encryption to be an explicit choice (instead of relying on -d/--decrypt not being present).

    Changed

    • MSRV is now 1.47.0.
    • -o/--output will now overwrite existing files instead of returning an error. This makes the behaviour consistent with most UNIX tools, as well as when using pipes.
    • Files encrypted with this version of rage might not decrypt with previous beta versions, due to changes in how stanza bodies are canonically encoded. This should only affect a small fraction of files (if grease that triggers the change is added, which has a 3% chance per file).
    • -r/--recipient now has the specific type "recipient" which better reflects its name, rather than the ambiguous "source of recipients" it was previously.
    • -i/--identity can now be used when encrypting files. This requires the -e/--encrypt flag (to prevent ambiguity, e.g. if the user wants to decrypt but forgets the -d/--decrypt flag).

    Removed

    • Recipients file support from -r/--recipient (use -R/--recipients-file instead).
    • HTTPS support. This added otherwise-unnecessary networking dependencies to rage, and there are many decisions that need to be made when downloading a file (e.g. what roots to trust?) that go beyond the APIs we want to focus on here. Users should use a tool like curl or wget to download a recipients file, and then pass it to rage.
    • The unstable GitHub feature (which relied on HTTPS support).
    • The unstable aliases feature.

    Fixed

    • Log output is now disabled by default, to prevent non-fatal error messages (such as an unset or invalid LANG variable) being printed to stderr while the program succeeds (which is confusing for users). The previous behaviour can be configured by setting the environment variable RUST_LOG=error.
    • Output files are now opened lazily, which avoids leaving behind an empty file when an error occurs before we write the header.

    age

    Security

    • StreamReader::seek(SeekFrom::End(offset)) did not previously authenticate the ciphertext length; if the ciphertext had been truncated or extended by adversary_offset, it would instead seek to offset + adversary_offset. This allowed an adversary with temporary control of an encrypted age file to control the location of a plaintext read following a seek-from-end. age now returns an error if the last chunk is invalid.
      • rage was not affected by this security issue, as it does not use Seek.
      • rage-mount may have been affected; it does not use SeekFrom::End directly, but the tar or zip crates might do so.

    Added

    • Plugin support, enabled by the plugin feature flag:
      • age::plugin::{Identity, Recipient} structs for parsing plugin recipients and identities from strings.
      • age::plugin::RecipientPluginV1, which implements age::Recipient and runs the V1 recipient plugin protocol.
      • age::plugin::IdentityPluginV1, which implements age::Identity and runs the V1 identity plugin protocol.
    • The web-sys feature flag, which enables calculating the work factor for passphrase encryption with the Performance timer via the web-sys crate, when compiling for a WebAssembly target such as wasm32-unknown-unknown. This feature is ignored for the wasm32-wasi target, which supports std::time::SystemTime.
    • age::Callbacks::request_public_string to request non-private input from the user (which will not trigger any OS-level passphrase-style prompt, unlike Callbacks::request_passphrase).

    Changed

    • MSRV is now 1.47.0.
    • age::cli_common::file_io::OutputWriter::File will now overwrite the file if it exists, instead of returning an error. This makes it consistent with age::cli_common::file_io::OutputWriter::Stdout, as well as most UNIX tools.
    • Files encrypted with this version of age might not decrypt with previous beta versions, due to changes in how stanza bodies are canonically encoded. This should only affect a small fraction of files (if grease that triggers the change is added, which has a 3% chance per file).
    • age::decryptor::RecipientsDecryptor now takes impl Iterator<Item = &'a dyn Identity> in its decryption methods, to make decrypting multiple files with the same identities easier.
    • age::cli_common::file_io::OutputWriter::File now wraps a LazyFile struct (instead of wrapping std::io::File directly), which does not open the file until it is first written to.
    • age::decryptor::Callbacks has been moved to age::Callbacks, as it is no longer decryption-specific.

    Fixed

    • age::cli_common::read_identities now allows either kind of line ending in SSH identity files.
    • Default en-US language strings are now always loaded, even if translations are not loaded by calling age::localizer().select(&requested_languages).
    • StreamReader::seek(SeekFrom::End(0)) now seeks to the correct position when the plaintext is an exact multiple of the chunk size.

    age-plugin 0.1.0

    Initial beta release!

    age-core

    Security

    • age_core::primitives::aead_decrypt now takes a size argument, checked against the plaintext length. This is to mitigate multi-key attacks, where a ciphertext can be crafted that decrypts successfully under multiple keys. Short ciphertexts can only target two keys, which has limited impact. See this commit message for more details.

    Added

    • age_core::format::FILE_KEY_BYTES constant.
    • age_core::plugin module, which contains common backend logic used by both the age library (to implement client support for plugins) and the age-plugin library.

    Changed

    • The stanza prefix -> and trailing newline are now formal parts of the age stanza; age_core::format::write::age_stanza now includes them in its output, and age_core::format::read::age_stanza expects them to be present.
    • Stanza bodies are now canonically serialized with a short (empty if necessary) last line. age_core::format::write::age_stanza outputs the new encoding, and age_core::format::read::age_stanza accepts only the new encoding. The new API age_core::format::read::legacy_age_stanza accepts either kind of stanza body encoding (the legacy minimal encoding, and the new explicit encoding).
    Source code(tar.gz)
    Source code(zip)
    rage-v0.6.0-arm64-linux.tar.gz(3.43 MB)
    rage-v0.6.0-armv7-linux.tar.gz(3.55 MB)
    rage-v0.6.0-x86_64-darwin.tar.gz(2.11 MB)
    rage-v0.6.0-x86_64-linux.tar.gz(5.86 MB)
    rage-v0.6.0-x86_64-windows.zip(1.68 MB)
    rage_0.6.0_amd64.deb(1.26 MB)
    rage_0.6.0_arm64.deb(825.24 KB)
    rage_0.6.0_armhf.deb(801.80 KB)
  • v0.5.0(Nov 22, 2020)

    rage

    Added

    • Italian, Spanish, and Chinese translations!
    • ssh feature flag, enabled by default. It can be disabled to remove support for ssh-rsa and ssh-ed25519 recipients and identities. ssh-rsa keys are now supported without the unstable feature flag.

    Changed

    • MSRV is now 1.45.0.

    Removed

    • Default identity path (identities should instead be set per-use).
    • Default alias path (for unstable aliases feature).

    age

    Added

    • Italian, Spanish, and Chinese translations!
    • New core traits, implemented by all relevant age types:
      • age::Identity, representing an identity that can decrypt an age file.
      • age::Recipient, representing a potential recipient of an age file.
    • Separate modules and structs for different recipient types:
      • age::x25519
      • age::ssh (behind the ssh feature flag).
    • age::EncryptError, representing errors that can occur during encryption.
    • age::IdentityFile struct, for parsing a list of native age identities (currently only age::x25519::Identity) from a file.
    • Asynchronous APIs for encryption and decryption, enabled by the async feature flag:
      • age::Encryptor::wrap_async_output()
      • age::Decryptor::new_async()
      • age::decryptor::RecipientsDecryptor::decrypt_async()
      • age::decryptor::PassphraseDecryptor::decrypt_async()
    • Explicit armoring support, enabled by the armor feature flag:
      • age::armor::ArmoredReader, which can be wrapped around an input to handle a potentially-armored age file.
      • age::armor::ArmoredWriter, which can be wrapped around an output to optionally apply the armored age format.

    Changed

    • MSRV is now 1.45.0.
    • Changes due to the new core traits:
      • age::Encryptor::with_recipients now takes Vec<Box<dyn Recipient>>.
      • age::decryptor::RecipientsDecryptor now takes impl Iterator<Item = Box<dyn Identity>> in its decryption methods.
      • age::cli_common::read_identities now returns Vec<Box<dyn Identity>>, as it abstracts over age::IdentityFile and age::ssh::Identity. When the ssh feature flag is enabled, it also takes an unsupported_ssh argument for handling unsupported SSH identities.
      • age::Error has been renamed to age::DecryptError.
    • Changes due to explicit armoring support:
      • age::Encryptor::wrap_output now only generates the non-malleable binary age format. To optionally generate armored age files, use encryptor.wrap_output(ArmoredWriter::wrap_output(output, format)).
      • age::Decryptor now only decrypts the non-malleable binary age format. To handle age files that are potentially armored, use Decryptor::new(ArmoredReader::new(input)).
      • age::Format has been moved to age::armor::Format.
    • SSH support is now disabled by default, behind the ssh feature flag. ssh-rsa keys are now supported without the unstable feature flag.
    • age::Callbacks has been moved to age::decryptor::Callbacks.

    Removed

    • age::SecretKey (replaced by age::x25519::Identity and age::ssh::Identity).
    • age::keys::RecipientKey (replaced by age::x25519::Recipient and age::ssh::Recipient).
    • age::keys::{Identity, IdentityKey} (replaced by age::Identity trait on individual identities, and age::IdentityFile for parsing identities).
    • age::decryptor::RecipientsDecryptor::decrypt_with_callbacks() (identities are now expected to handle their own callbacks, and age::cli_common::read_identities now adds callbacks to SSH identities).
    • Default identity path:
      • age::cli_common::get_config_dir.
      • The no_default parameter for age::cli_common::read_identities.

    age-core

    Added

    • Several structs used when implementing the age::Identity and age::Recipient traits:
      • age_core::format::FileKey
      • age_core::format::Stanza
    • age_core::format::grease_the_joint, for generating a random valid recipient stanza. No other guarantees are made about the stanza's fields.
    • age_core::primitives::{aead_decrypt, aead_encrypt, hkdf}, to enable these common primitives to be reused in plugins.

    Changed

    • MSRV is now 1.41.0.
    • age_core::format::write::age_stanza now takes args: &[impl AsRef<str>].
    Source code(tar.gz)
    Source code(zip)
    rage-v0.5.0-arm64-linux.tar.gz(4.04 MB)
    rage-v0.5.0-armv7-linux.tar.gz(4.03 MB)
    rage-v0.5.0-x86_64-darwin.tar.gz(2.59 MB)
    rage-v0.5.0-x86_64-linux.tar.gz(6.30 MB)
    rage-v0.5.0-x86_64-windows.zip(2.16 MB)
    rage_0.5.0_amd64.deb(1.63 MB)
    rage_0.5.0_arm64.deb(1.15 MB)
    rage_0.5.0_armhf.deb(1.01 MB)
  • v0.4.0(Mar 24, 2020)

    rage

    Added

    • rage-mount can now mount ASCII-armored age files.

    Changed

    • [rage] -p/--passphrase flag can no longer be used with -d/--decrypt (passphrase-encrypted files are now detected automatically).

    Removed

    • -p/--passphrase flag from rage-mount (passphrase-encrypted files are now detected automatically).

    Fixed

    • [Unix] Files encrypted with a passphrase can now be decrypted with rage when piped over stdin.

    age

    Added

    • age::Decryptor::new(R: Read), which parses an age file header and returns a context-specific decryptor.
    • age::decryptor module containing the context-specific decryptors.
      • Their decryption methods return the concrete type StreamReader<R>, enabling them to handle seekable readers.
    • age::Encryptor::with_recipients(Vec<RecipientKey>)
    • age::Encryptor::with_user_passphrase(SecretString)
    • Support for encrypted OpenSSH keys created with ssh-keygen prior to OpenSSH 7.6.
    • age::cli_common::file_io::OutputWriter::is_terminal

    Changed

    • age::Decryptor has been refactored to auto-detect the decryption type. As a result, both identity-based and passphrase-based decryption need to be handled.
    • age::StreamReader has been moved into the age::stream module, along with StreamWriter which was previously public but has now been formally exposed in the API for documentation purposes.
    • age::Encryptor is now an opaque struct, and must be created via its new constructors.
    • age::Encryptor::wrap_output now consumes self, making it harder to accidentally reuse a passphrase for multiple encrypted files.
    • age::cli_common::read_identities now takes an additional file_not_found parameter for customising the error when an identity filename is not found.

    Removed

    • age::Decryptor::trial_decrypt (replaced by context-specific decryptors).
    • age::Decryptor::trial_decrypt_seekable (merged into the context-specific decryptors).
    • age::Error::ArmoredWhenSeeking
    • age::Error::MessageRequiresKeys
    • age::Error::MessageRequiresPassphrase

    Fixed

    • Key files with Windows line endings are now correctly parsed.

    age-core

    No changes; version bumped to keep it in sync with age.

    Source code(tar.gz)
    Source code(zip)
    rage-v0.4.0-arm64-linux.tar.gz(3.14 MB)
    rage-v0.4.0-armv7-linux.tar.gz(3.19 MB)
    rage-v0.4.0-x86_64-darwin.tar.gz(1.99 MB)
    rage-v0.4.0-x86_64-linux.tar.gz(3.27 MB)
    rage-v0.4.0-x86_64-windows.zip(1.72 MB)
    rage_0.4.0_amd64.deb(1.35 MB)
    rage_0.4.0_arm64.deb(983.72 KB)
    rage_0.4.0_armhf.deb(979.53 KB)
  • v0.3.0(Feb 9, 2020)

    Crates galore! The changes in the age library crate are reflected in the CLI tools in the rage crate.

    rage

    (relative to the CLI tools in age 0.2.0)

    Added

    • -V / --version flags to all binaries.
    • Completion files for Bash, Elvish, Fish, PowerShell, and Zsh can be generated with cargo run --example generate-completions.
    • The Debian package will install completion files for Bash, Fish, and Zsh.

    Changed

    • If a pinentry binary is available, it will be used preferentially to request secrets such as passphrases. The previous CLI input will be used if pinentry is not available.

    age

    Added

    • age::Callbacks, which encapsulates any requests that might be necessary during the decryption process.
    • age::cli_common::UiCallbacks, which implements Callbacks with requests to the user via age::cli_common::read_secret.
    • age::Decryptor::with_identities(Vec<Identity>)
    • age::Decryptor::with_identities_and_callbacks(Vec<Identity>, Box<dyn Callbacks>)
    • age::Encryptor will insert a random recipient stanza into the header, to keep age's joint well oiled.

    Changed

    • The CLI tools have been moved into the rage crate.
    • The age::Decryptor::Keys enum case has been renamed to Identities and altered to store a Box<dyn Callbacks> internally.
    • age::Decryptor::trial_decrypt and age::Decryptor::trial_decrypt_seekable both no longer take a request_passphrase argument.
    • age::cli_common::read_secret:
      • Takes an additional prompt parameter.
      • Uses the system pinentry binary for requesting secrets if available.
      • Returns pinentry::Error instead of io::Error.
    • age::cli_common::read_or_generate_passphrase now returns pinentry::Error instead of io::Error.
    • Core age parsers and serializers have been moved into the age-core crate.

    Fixed

    • Fixed several crashes in the armored format reader, found by fuzzing. The reader also now correctly enforces a canonical armor marker and line lengths.
    • Recipient stanzas with empty bodies are correctly parsed.

    age-core

    (relative to age 0.2.0)

    Fixed

    • Base64 padding is now correctly rejected by the age stanza parser.
    Source code(tar.gz)
    Source code(zip)
    rage-v0.3.0-arm64-linux.tar.gz(3.12 MB)
    rage-v0.3.0-armv7-linux.tar.gz(3.17 MB)
    rage-v0.3.0-x86_64-darwin.tar.gz(1.97 MB)
    rage-v0.3.0-x86_64-linux.tar.gz(3.25 MB)
    rage-v0.3.0-x86_64-windows.zip(1.71 MB)
    rage_0.3.0_amd64.deb(1.34 MB)
    rage_0.3.0_arm64.deb(970.74 KB)
    rage_0.3.0_armhf.deb(966.50 KB)
  • v0.2.0(Jan 10, 2020)

    Added

    • The library crate can be compiled to WASM.
    • When encrypting to a passphrase, rage will generate a secure passphrase if the user does not provide one.
    • SecretKey::to_string -> secrecy::SecretString, which zeroizes most internal state. (Zeroizing all internal state requires changes to the bech32 crate.)
    • RecipientKey implements Display, and can be converted to a string using recipient.to_string().
    • Decryptor::with_passphrase constructor.
    • --max-work-factor WF argument for rage and rage-mount, to enable overriding the default maximum (which is around 16 seconds of work).

    Changed

    • age::Encryptor::wrap_output now takes an age::Format enum argument instead of a boolean flag.
    • Recipients are now parsed as filenames last instead of first. If a filename happens to also be a valid recipient format, the file will be ignored. This can be overridden by using an absolute file path.
    • The filename - (hyphen) is now treated as an explicit request to read from standard input or write to standard output when used as an input or output filename.
    • -o - will override protections for terminals when standard output is not being piped elsewhere: output will not be truncated, and binary data will be printed directly to the terminal.
    • Armored encrypted output can now be printed to the terminal. Large files will be truncated (to protect the terminal), corrupting the encryption. This can be overriden with -o -.
    • The Decryptor::Passphrase enum case has been altered to store an optional maximum work factor.

    Removed

    • SecretKey::to_str (replaced by SecretKey::to_string).
    • RecipientKey::to_str (replaced by Display implementation and recipient.to_string()).

    Fixed

    • Corrected encoding of example recipients in manpages.
    • Re-enabled the default identities file (#41).
    • Fixed parser to reject encrypted OpenSSH keys if they contain invalid bcrypt_pbkdf parameters.
    • [Unix] rage-keygen -o filename now creates files with mode 600 (i.e. the output file is no longer world-readable).
    • Unknown recipient lines are now parsed and ignored during decryption, instead of causing a hard failure.
    Source code(tar.gz)
    Source code(zip)
    rage-v0.2.0-arm64-linux.tar.gz(3.05 MB)
    rage-v0.2.0-armv7-linux.tar.gz(3.11 MB)
    rage-v0.2.0-x86_64-darwin.tar.gz(1.91 MB)
    rage-v0.2.0-x86_64-linux.tar.gz(4.69 MB)
    rage-v0.2.0-x86_64-windows.zip(1.65 MB)
    rage_0.2.0_amd64.deb(1.29 MB)
    rage_0.2.0_arm64.deb(941.64 KB)
    rage_0.2.0_armhf.deb(944.64 KB)
  • v0.1.1(Dec 29, 2019)

    This time with binaries!

    Added

    • Debian packaging support via cargo deb. See docs/debian.md for details.

    Changed

    • Moved the num_traits dependency behind the unstable feature flag.
    • The generate-docs example now generates (the equivalent of ) gzip -9 manpages, for ease of use in Debian packaging.

    Fixed

    • Decrypted chunks inside the STREAM implementation are now zeroized after use.
    Source code(tar.gz)
    Source code(zip)
    rage-v0.1.1-x86_64-darwin.tar.gz(1.88 MB)
    rage-v0.1.1-x86_64-linux.tar.gz(4.65 MB)
    rage-v0.1.1-x86_64-windows.zip(1.63 MB)
    rage_0.1.1_amd64.deb(1.27 MB)
  • v0.1.0(Dec 28, 2019)

    This is the first beta release of the age crate and rage tool suite.

    Note: The 0.X version series is being used for beta releases. The first non-beta release will be version 1.0.0.

    Source code(tar.gz)
    Source code(zip)
The fast, light, and robust client for the Ethereum mainnet.

OpenEthereum Fast and feature-rich multi-network Ethereum client. » Download the latest release « Table of Contents Description Technical Overview Bui

OpenEthereum 1.1k Sep 19, 2021
Official implementation of the YeeCo Root Chain (Layer 1)

yeeroot Official implementation of the YeeCo Root Chain (Layer 1) YeeCo is a permissionless, secure, high performance and scalable public blockchain p

YeeCo 25 Jan 7, 2021
The new, performant, and simplified version of Holochain on Rust (sometimes called Holochain RSM for Refactored State Model)

Holochain License: This repository contains the core Holochain libraries and binaries. This is the most recent and well maintained version of Holochai

Holochain 437 Sep 14, 2021
DEPRECATED. The Holochain framework implemented in rust with a redux style internal state-model.

Holochain-rust Travis: Circle CI: Codecov: License: This code is loosely based on the previous Golang prototype. Code Status: This Rust version is alp

Holochain 1k Sep 6, 2021
Reference client for NEAR Protocol

Reference implementation of NEAR Protocol About NEAR NEAR's purpose is to enable community-driven innovation to benefit people around the world. To ac

NEAR 1k Sep 14, 2021
Rust Ethereum 2.0 Client

Lighthouse: Ethereum 2.0 An open-source Ethereum 2.0 client, written in Rust and maintained by Sigma Prime. Documentation Overview Lighthouse is: Read

Sigma Prime 1.3k Sep 14, 2021
Rust port of the Terry Davis' (RIP) "god says" program

RIP Terry A. Davis 1969-2018 god says Rust port of the programmer Terry Davis' "god says" (AKA GodSpeaks) program. Terrence Andrew Davis (December 15,

Orhun Parmaksız 31 Sep 7, 2021
Implementation of the Kademlia DHT protocol in Rust

kademlia-dht Simple implementation of the Kademlia DHT protocol in Rust with state dumping features for educational purposes (not production-ready). T

Leonardo Folgoni 11 Jul 30, 2021
Custom Ethereum vanity address generator made in Rust

ethaddrgen Custom Ethereum address generator Get a shiny ethereum address and stand out from the crowd! Disclaimer: Do not use the private key shown i

Jakub Hlusička 99 Sep 17, 2021
The Phala Network Blockchain, pRuntime and the bridge.

Phala Blockchain Phala Network is a TEE-Blockchain hybrid architecture implementing Confidential Contract. This repo includes: node/: the main blockch

Phala Network 198 Sep 18, 2021
The Parity Bitcoin client

The Parity Bitcoin client. Gitter Installing from source Installing the snap Running tests Going online Importing bitcoind database Command line inter

Parity Technologies 682 Sep 6, 2021
Polkadot Node Implementation

Polkadot Implementation of a https://polkadot.network node in Rust based on the Substrate framework. NOTE: In 2018, we split our implementation of "Po

Parity Technologies 4.2k Sep 20, 2021
Rust implementation of Zcash protocol

The Parity Zcash client. Gitter Blog: Parity teams up with Zcash Foundation for Parity Zcash client Installing from source Installing the snap Running

Parity Technologies 158 Sep 11, 2021
Official Rust implementation of the Nimiq protocol

Nimiq Core implementation in Rust (core-rs) Rust implementation of the Nimiq Blockchain Core Nimiq is a frictionless payment protocol for the web. Thi

Nimiq 69 Aug 18, 2021
A Rust implementation of BIP-0039

bip39-rs A Rust implementation of BIP0039 Changes See the changelog file, or the Github releases for specific tags. Documentation Add bip39 to your Ca

Infincia LLC 42 Jun 24, 2021
A high performance blockchain kernel for enterprise users.

English | 简体中文 What is CITA CITA is a fast and scalable blockchain kernel for enterprises. CITA supports both native contract and EVM contract, by whi

CITAHub 1.2k Sep 10, 2021
The CLI to control StewardX

StewardX CLI Logo converted to ASCII via https://asciiart.club/ The CLI to control StewardX This is the official CLI to control StewardX. Made with #c

Gökay Okyay 5 May 25, 2021
Joystream Monorepo

Joystream This is the main code repository for all Joystream software. In this mono-repo you will find all the software required to run a Joystream ne

Joystream 92 Sep 8, 2021
The Nervos CKB is a public permissionless blockchain, and the layer 1 of Nervos network.

Nervos CKB - The Common Knowledge Base master develop About CKB CKB is the layer 1 of Nervos Network, a public/permissionless blockchain. CKB uses Pro

Nervos Network 871 Sep 11, 2021