Skip to content

age v1.1.0: plugin and YubiKeys support

Compare
Choose a tag to compare
@FiloSottile FiloSottile released this 26 Dec 14:57
· 25 commits to main since this release

The age logo, a wireframe of St. Peters dome in Rome, with the text: age, file encryption

age is a simple, modern and secure file encryption tool, format, and Go library. It features small explicit keys, no config options, and UNIX-style composability. Learn more by reading the README, the age(1) man page, the Go API reference, the format specification, or the full release changelog. Watch the repository or follow @filippo@abyssdomain.expert to be notified of new releases.

🛠️ FYI, age now has an extensive test suite which all age implementations are encouraged to adopt.

Plugin support

The age CLI now supports plugins, such as age-plugin-yubikey by @str4d. To try it on macOS with Homebrew:

$ brew upgrade age
$ brew install age-plugin-yubikey
$ age-plugin-yubikey # interactive setup
$ age -r age1yubikey1qwt50d05nh5vutpdzmlg5wn80xq5negm4uj9ghv0snvdd3yysf5yw3rhl3t
$ age -d -i age-yubikey-identity-388178f3.txt

Plugins must be loaded explicitly by using their respective recipient or identity, and are not tied to a specific header stanza type. This means plugins can be used not only to support new recipient types such as PIV tokens (i.e. YubiKeys) or cloud KMS solutions, but also to produce passphrase-encrypted files that can be decrypted without plugins, to store age native private keys on secure elements, or even for agent functionality or to proxy decryption operations to remote machines.

Plugins operate over a simple textual stdin/stdout protocol (C2SP/C2SP#5). Developers are encouraged to reach out with plugin ideas and announcements. Read more in the relevant man page section.

Breaking changes

If -i is used, passphrase-encrypted files are now rejected. Previously, a passphrase-encrypted file was auto-detected and the identity file was ignored. This could lead to unexpected behavior, such as a script blocking for user interaction, based on potentially untrusted input files. Now, age -d must be invoked without -i arguments to decrypt passphrase-encrypted files. A helpful error is printed otherwise. This should not break any automated system as passphrase decryption was always interactive.

Empty final chunks are now rejected. If a payload was a multiple of 64KiB long, there were two valid encryptions for it: with a "full" last chunk encrypting 64KiB, or with an additional "empty" chunk encrypting 0 bytes. age, rage, and all other known implementations only ever produced the former. (Note that age will forever decrypt files it generated.) The latter is now rejected. The specification has been updated (C2SP/C2SP#13) and test cases are included in the test suite.

Minor changes

PKCS#8-encoded Ed25519 private keys (such as 1Password exports) are now supported as SSH identities.

If an armored file is pasted into the terminal, age will now attempt to wait until the end of the file before prompting for a password.

Some invalid files are now correctly rejected, in particular encrypted files with trailing data. (Yay for the test suite!)

If /dev/tty is present but can't be opened, age will now fallback to trying to treat stdin as a terminal as if /dev/tty wasn't present. (Thanks @brandsimon!)

Input prompts now go to the terminal, even if standard error is redirected.

Values of the new armor.Error type are now returned wrapped in decryption errors when appropriate.

Windows binary releases are now signed. (Thanks @technion!)

Documentation and error messages were improved.