Skip to content

Releases: str4d/rage

rage v0.7.1

27 Dec 01:03
c950780
Compare
Choose a tag to compare

rage

Fixed

  • Fixed a bug in 0.7.0 where non-canonical recipient stanza bodies in an age
    file header would cause rage to crash instead of being rejected.

age

Fixed

  • Bumped age-core to 0.7.1 to fix a bug where non-canonical recipient stanza
    bodies in an age file header would cause a panic instead of being rejected.

age-plugin 0.2.1

Fixed

  • Bumped age-core to 0.7.1 to fix a bug where non-canonical recipient stanza
    bodies in an age file header would cause a panic instead of being rejected.

age-core

Fixed

  • In 0.7.0, Base64 decoding was moved to the AgeStanza::body method, with the
    stanza parser only checking for valid Base64 characters. This caused the
    parser to start accepting stanzas with non-canonical last body lines (where
    the Base64 encoding would have trailing bits that could not be decoded into
    full bytes); calling AgeStanza::body on these stanzas would cause a panic.
    This release fixes the parser to reject non-canonical last body lines, turning
    the panic back into an error.

rage v0.7.0

18 Oct 17:19
c93b914
Compare
Choose a tag to compare

rage

Added

  • -i/--identity now accepts passphrase-encrypted age identity files.
  • The -j PLUGIN_NAME flag, which allows decrypting with a plugin using its "default mode" (in which no identity-specific information is required). This flag is equivalent to using -i/--identity with an identity file containing the default plugin identity (containing no data).

Changed

  • MSRV is now 1.51.0.
  • *-linux.tar.gz release binaries are now built with Ubuntu 18.04, and require a system with a minimum of glibc 2.27.

age

Added

  • age::encrypted::Identity, for decrypting files with passphrase-encrypted age identity files.
  • age::IdentityFileEntry enum, representing the possible kinds of entries within an age identity file.
  • age::{DecryptError, EncryptError, PluginError}: Clone bounds.
  • age::cli_common::UiCallbacks: Clone + Copy bounds.
  • age::cli_common::Passphrase::random, for generating a secure passphrase.
  • age::cli_common::ReadError
  • age::secrecy, which re-exports the secrecy crate.

Changed

  • MSRV is now 1.51.0.
  • age::IdentityFile::into_identities now returns Vec<IdentityFileEntry>.
  • age::cli_common::read_identities:
    • Encrypted age files will now be parsed and assumed to be encrypted age identities. This assumption is checked at file-decryption time.
    • New max_work_factor parameter for controlling the work factor when decrypting encrypted identities.
    • Identities are now returned in the same order as filenames (and top-to-bottom from within each file). Plugin identities are no longer coalesced; there is one Box<dyn Identity> per plugin identity.
    • age::cli_common::ReadError is now returned instead of a user-specified error type. The error constructor parameters have been removed from the function.
  • age::Callbacks::prompt has been renamed to Callbacks::display_message.
    • age::cli_common::UiCallbacks::display_message no longer uses pinentry (which displays a temporary prompt that can be dismissed), so the message is now part of the visible CLI output.

Removed

  • IdentityFile::split_into (replaced by IdentityFileEntry::Plugin).

age-plugin 0.2.0

Changed

  • MSRV is now 1.51.0.
  • age_plugin::Callbacks methods now return age_core::plugin::Error instead of () for internal errors, following changes to age_core::plugin::Result.

age-core

Added

  • age_core::secrecy, which re-exports the secrecy crate.
  • age_core::plugin::Error

Changed

  • MSRV is now 1.51.0.
  • The body property of age_core::format::AgeStanza has been replaced by the AgeStanza::body method, to enable enclosing parsers to defer Base64 decoding until the very end.
  • age_core::plugin::Result now only takes a single generic argument, and uses age_core::plugin::Error for its inner error type.

rage v0.6.0

02 May 01:22
3e3e6a8
Compare
Choose a tag to compare

rage

Added

  • Plugin support!
  • 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).

rage v0.5.1

13 Feb 17:53
Compare
Choose a tag to compare

Fixed

  • Bumped dependencies to i18n-embed-fl 0.3 and i18n-embed 0.10.2 to fix a
    transient dependency breakage, that broke cargo install rage because
    cargo install ignores Cargo.lock.

rage v0.5.0

22 Nov 19:45
48f5382
Compare
Choose a tag to compare
rage v0.5.0 Pre-release
Pre-release

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

rage v0.4.0

25 Mar 01:37
ffa85ec
Compare
Choose a tag to compare
rage v0.4.0 Pre-release
Pre-release

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.

rage v0.3.1

11 Feb 13:55
v0.3.1
Compare
Choose a tag to compare
rage v0.3.1 Pre-release
Pre-release

Version bump to fix nightly builds. No other changes from v0.3.0.

rage v0.3.0

09 Feb 21:00
v0.3.0
56b974c
Compare
Choose a tag to compare
rage v0.3.0 Pre-release
Pre-release

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.

rage v0.2.0

11 Jan 00:15
v0.2.0
Compare
Choose a tag to compare
rage v0.2.0 Pre-release
Pre-release

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.

rage v0.1.1

30 Dec 03:07
v0.1.1
a89a889
Compare
Choose a tag to compare
rage v0.1.1 Pre-release
Pre-release

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.