age-plugin-yubikey
is a plugin for age clients
like age
and rage
,
which enables files to be encrypted to age identities stored on YubiKeys.
On Windows, Linux, and macOS, you can use the pre-built binaries.
If your system has Rust 1.60+ installed (either via rustup
or a system
package), you can build directly from source:
cargo install age-plugin-yubikey
Help from new packagers is very welcome.
You can install using Homebrew:
brew install age-plugin-yubikey
On non-Windows, non-macOS systems, you need to ensure that the pcscd
service
is installed and running.
You'll also need the related library in order to build the pcsc-sys dependency. Otherwise you'll have a build error saying:
error: failed to run custom build command for `pcsc-sys v1.2.0`
$ sudo apt-get install pcscd libpcsclite-dev
As root
do:
$ pkg_add pcsc-lite
$ rcctl enable pcscd
$ rcctl start pcscd
As root
do:
$ pkg install pcsc-lite
$ service pcscd enable
$ service pcscd start
WSL does not currently provide native support for USB devices. However, Windows binaries installed on the host can be run from inside a WSL environment. This means that you can encrypt or decrypt files inside a WSL environment with a YubiKey:
- Install
age-plugin-yubikey
on the Windows host. - Install an age client inside the WSL environment.
- Ensure that
age-plugin-yubikey.exe
is available in the WSL environment'sPATH
. For default WSL setups, the Windows host'sPATH
is automatically added to the WSL environment'sPATH
(see this Microsoft blog post for more details).
There are two ways to configure a YubiKey as an age
identity. You can run the
plugin binary directly to use a simple text interface, which will create an age
identity file:
$ age-plugin-yubikey
Or you can use command-line flags to programmatically generate an identity and print it to standard output:
$ age-plugin-yubikey --generate \
[--serial SERIAL] \
[--slot SLOT] \
[--name NAME] \
[--pin-policy PIN-POLICY] \
[--touch-policy TOUCH-POLICY]
Once an identity has been created, you can regenerate it later:
$ age-plugin-yubikey --identity [--serial SERIAL] --slot SLOT
The age recipients contained in all connected YubiKeys can be printed on standard output:
$ age-plugin-yubikey --list
To encrypt files to these YubiKey recipients, ensure that age-plugin-yubikey
is accessible in your PATH
, and then use the recipients with an age client as
normal (e.g. rage -r age1yubikey1...
).
The output of the --list
command can also be used directly to encrypt files to
all recipients (e.g. age -R filename.txt
).
To decrypt files encrypted to a YubiKey identity, pass the identity file to the
age client as normal (e.g. rage -d -i yubikey-identity.txt
).
age-plugin-yubikey
does not provide or interact with an agent for decryption.
It does however preserve the PIN cache by not soft-resetting the YubiKey after a
decryption or read-only operation, which enables YubiKey identities configured
with a PIN policy of once
to not prompt for the PIN on every decryption.
The session that corresponds to the once
policy can be ended in several ways,
not all of which are necessarily intuitive:
- Unplugging the YubiKey (the obvious way).
- Using a different applet (e.g. FIDO2). This causes the PIV applet to be closed which clears its state.
- Generating a new age identity via
age-plugin-yubikey --generate
or the CLI interface. This is to avoid leaving the YubiKey authenticated with the management key.
If the current PIN UX proves to be insufficient, a decryption agent will most
likely be implemented as a separate age plugin that interacts with
yubikey-agent
, enabling
YubiKeys to be used simultaneously with age and SSH.
age-plugin-yubikey
only officially supports the following YubiKey variants,
set up either via the text interface or the --generate
flag:
- YubiKey 4 series
- YubiKey 5 series
NOTE: Nano and USB-C variants of the above are also supported. The pre-YK4 YubiKey NEO series is NOT supported. The blue "Security Key by Yubico" will also not work (as it doesn't support PIV).
In practice, any PIV token with an ECDSA P-256 key and certificate in one of the 20 "retired" slots should work. You can list all age-compatible keys with:
$ age-plugin-yubikey --list-all
age-plugin-yubikey
implements several automatic security management features:
- If it detects that the default PIN is being used, it will prompt the user to change the PIN. The PUK is then set to the same value as the PIN.
- If it detects that the default management key is being used, it generates a
random management key and stores it in PIN-protected metadata.
age-plugin-yubikey
does not support custom management keys.
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.
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.