Skip to content

rage v0.6.0

Compare
Choose a tag to compare
@github-actions github-actions released this 02 May 01:22
· 602 commits to main since this release
3e3e6a8

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