Coder Social home page Coder Social logo

age-plugin-yubikey's Introduction

YubiKey plugin for age clients

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.

Installation

Environment CLI command
Cargo (Rust 1.65+) cargo install age-plugin-yubikey
Homebrew (macOS or Linux) brew install age-plugin-yubikey
Arch Linux pacman -S age-plugin-yubikey
Debian Debian package
NixOS Add to config:
environment.systemPackages = [
pkgs.age-plugin-yubikey
];
Or run nix-env -i age-plugin-yubikey
Ubuntu 20.04+ Debian package
OpenBSD pkg_add age-plugin-yubikey (security/age-plugin-yubikey)

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

Help from new packagers is very welcome.

Linux, BSD, etc.

On non-Windows, non-macOS systems, you need to ensure that the pcscd service is installed and running.

Environment CLI command
Debian or Ubuntu sudo apt-get install pcscd
Fedora sudo dnf install pcsc-lite
OpenBSD As root do:
pkg_add pcsc-lite ccid
rcctl enable pcscd
rcctl start pcscd
FreeBSD As root do:
pkg install pcsc-lite libccid
service pcscd enable
service pcscd start
Arch sudo pacman -S pcsclite pcsc-tools yubikey-manager
sudo systemctl enable pcscd
sudo systemctl start pcscd

When installing via Cargo, you also need to ensure that the development headers for the pcsc-lite library are available, so that the pcsc-sys crate can be compiled.

Environment CLI command
Debian or Ubuntu sudo apt-get install libpcsclite-dev
Fedora sudo dnf install pcsc-lite-devel

Windows Subsystem for Linux (WSL)

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:

  1. Install age-plugin-yubikey on the Windows host.
  2. Install an age client inside the WSL environment.
  3. Ensure that age-plugin-yubikey.exe is available in the WSL environment's PATH. For default WSL setups, the Windows host's PATH is automatically added to the WSL environment's PATH (see this Microsoft blog post for more details).

Configuration

age-plugin-yubikey identities have two parts:

  • The secret key material, which is stored inside a YubiKey.
  • An age identity file, which contains information that an age client can use to figure out which YubiKey secret key should be used.

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

To use the identity with an age client, it needs to be stored in a file. When using the above programmatic flags, you can do this by redirecting standard output to a file. On a Unix system like macOS or Ubuntu:

$ age-plugin-yubikey --identity --slot SLOT > yubikey-identity.txt

Usage

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

Advanced topics

Agent support

age-plugin-yubikey does not provide or interact with an agent for decryption. It does however attempt to 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. This does not work for YubiKey 4 series.

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.
    • This is why the YubiKey 4 series does not support PIN cache preservation: their serial can only be obtained by switching to the OTP applet.
  • 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.

Manual setup and technical details

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.

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.

age-plugin-yubikey's People

Contributors

dependabot[bot] avatar pierreprinetti avatar robinp avatar str4d avatar tekumara avatar vlkrs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

age-plugin-yubikey's Issues

PIN Policy Ignored

Environment

  • OS: NixOS
  • age-plugin-yubikey version: 0.1.0

What were you trying to do

I'm working on a PR to agenix (ryantm/agenix#46) to add support for this plugin.

What happened

In order to make that viable, I set my generated identity's PIN policy to never, however, when I go to decrypt the files, it still asks for my PIN each time regardless.

command cat age-yubikey-identity.txt
#       Serial: 11300418, Slot: 2
#         Name: age identity ...
#      Created: Fri, 04 Jun 2021 03:22:04 +0000
#   PIN policy: Never  (A PIN is NOT required to decrypt)
# Touch policy: Never  (A physical touch is NOT required to decrypt)
# ...agenix -i age-yubikey-identity.txt -e aws.age
Enter PIN for YubiKey with serial 11300418:

Don't be confused by the use of agenix above, the same thing happens with rage as well (which agenix uses under the hood).

Cannot generate an identity with Yubikey 4

Environment

  • OS: Alpine Linux 3.16.2
  • age-plugin-yubikey version: 0.3.0

What were you trying to do

Generate an identity to install to my Yubikey 4.

What happened

$ ./age-plugin-yubikey
✨ Let's get your YubiKey set up for age! ✨

This tool can create a new age identity in a free slot of your YubiKey.
It will generate an identity file that you can use with an age client,
along with the corresponding recipient. You can also do this directly
with:
    age-plugin-yubikey --generate

If you are already using a YubiKey with age, you can select an existing
slot to recreate its corresponding identity file and recipient.

When asked below to select an option, use the up/down arrow keys to
make your choice, or press [Esc] or [q] to quit.

thread 'main' panicked at 'range end index 4 out of range for slice of length 0', /home/djmoch/.cargo/registry/src/github.com-1ecc6299db9ec823/yubikey-0.5.0/src/transaction.rs:160:9

Error `invalid type "age1yubikey"` with current Go Age

Environment

  • OS: Fedora 35, linux 5.15.5
  • age-plugin-yubikey version: 0.2.0
  • age version: 1.0.0
  • rage version: 0.7.0

What were you trying to do

  • Generated a new age key
  • Tried encrypting some sample data
  • Encryption works with rage 0.7.0
  • Encryption fails with age 1.0.0 with error age: error: malformed recipient "age1yubikey1qgqsp5z24ff2wkezx0x8vdsv7hwywhj68tp9m6hfchjuunlx8h5pzx33eal": invalid type "age1yubikey"

What happened

  • Generated key successfully
> age-plugin-yubikey
✨ Let's get your YubiKey set up for age! ✨

[...]

🔑 Select a YubiKey: Yubico YubiKey OTP+FIDO+CCID 00 00 (Serial: 123)
🕳️  Select a slot for your age identity: Slot 20 (Empty)
📛 Name this identity [age identity TAG_HEX]: AGE_ENC_20
🔤 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 identity in slot 20? yes


Enter PIN for YubiKey with serial 123 (default is 123456): [hidden]

✨ Your YubiKey is using the default management key.
✨ We'll migrate it to a PIN-protected management key.
... Success!
👆 Please touch the YubiKey

📝 File name to write this identity to: age-yk-id-20.txt

✅ Done! This YubiKey identity is ready to go.

🔑 Here's your shiny new YubiKey recipient:
  age1yubikey1qgqsp5z24ff2wkezx0x8vdsv7hwywhj68tp9m6hfchjuunlx8h5pzx33eal

Here are some example things you can do with it:

- Encrypt a file to this identity:
  $ cat foo.txt | age -r age1yubikey1qgqsp5z24ff2wkezx0x8vdsv7hwywhj68tp9m6hfchjuunlx8h5pzx33eal -o foo.txt.age

- Decrypt a file with this identity:
  $ cat foo.txt.age | age -d -i age-yk-id-20.txt > foo.txt

- Recreate the identity file:
  $ age-plugin-yubikey -i --serial 123 --slot 20 > age-yk-id-20.txt

- Recreate the recipient:
  $ age-plugin-yubikey -l --serial 123 --slot 20

💭 Remember: everything breaks, have a backup plan for when this YubiKey does.


> cat age-yk-id-20.txt 
#       Serial: 123, Slot: 20
#         Name: AGE_ENC_20
#      Created: Sat, 04 Dec 2021 05:17:26 +0000
#   PIN policy: Once   (A PIN is required once per session, if set)
# Touch policy: Always (A physical touch is required for every decryption)
#    Recipient: age1yubikey1qgqsp5z24ff2wkezx0x8vdsv7hwywhj68tp9m6hfchjuunlx8h5pzx33eal
  • Tried encrypting a test string, failed to encrypt with age 1.0.0
> echo "testo testo" | age -r age1yubikey1qgqsp5z24ff2wkezx0x8vdsv7hwywhj68tp9m6hfchjuunlx8h5pzx33eal -o test.txt.age
age: error: malformed recipient "age1yubikey1qgqsp5z24ff2wkezx0x8vdsv7hwywhj68tp9m6hfchjuunlx8h5pzx33eal": invalid type "age1yubikey"
age: report unexpected or unhelpful errors at https://filippo.io/age/report
  • Tried encrypting and decrypting with rage 0.7.0, success
[21:38:32] cat@ /home/cat/.config/age
> echo "testo testo" | rage -r age1yubikey1qgqsp5z24ff2wkezx0x8vdsv7hwywhj68tp9m6hfchjuunlx8h5pzx33eal -o test.txt.age

[21:39:14] cat@ /home/cat/.config/age
> cat test.txt.age 
age-encryption.org/v1
-> piv-p256 /Ghj/w A2WpYUuG0RnqNqzUyDrGq55lXTCuaR5dqtM19P4OK2DH
jVlT9ZsqZ73zs5C3bS6I2U5gYISwR8jFfXDAODQbt6s
-> d,`K%5-grease
++416eYz7ZkGoYhQTcUsdcqPoeI
--- O2mTiDy+DNkhd4C4ajqYITKmXDJAMiD5TpnG48P48ec
�ɟ)��׬ vBE�|ɪL�c^B���
                     롡g��x�i<z⏎                                                                 

[21:39:17] cat@ /home/cat/.config/age  
> cat test.txt.age | rage -d -i age-yk-id-20.txt > test.txt 

[21:40:11] cat@ /home/cat/.config/age  
> cat test.txt
testo testo

Notes

  • Please let me know if there's any debug info I can provide to help!

Enable providing YubiKey PIN via environment variable

In programmatic use cases, the GUI or TUI used by pinentry (or the fallback interactive prompt) won't work. Instead, if the environment variable AGE_YUBIKEY_PIN is set, we should just use that as the PIN and never prompt for one.

There is a potential issue here in that if we don't have sufficiently-clear error messages, a user with an accidentally-configured environment might block their PIN while trying to get their script to work. We should make sure that we both log the fact that an environment variable is being used, and include that in any PIN-related errors.

UX: Why not support for YubiKey NEO?

What were you trying to do

Setting up an age key on my YubiKey Neo.

What happened

All want well until it asked me to touch the YK and failed (I've added the final response from my YK):

age-plugin-yubikey --generate --name 'YRO Yubi Neo - age'

Enter PIN for YubiKey with serial 4XXXXX8 (default is 123456): [hidden]
👆 Please touch the YubiKey
[TRACE yubikey::apdu] <<< Response { status_words: IncorrectSlotError, data: [] }
[ERROR yubikey::piv] failed to generate new key (incorrect slot)
Error: Error while communicating with YubiKey: key error

I finally found out here, that the YK Neo is not supported.
But it still has PIV support, so I was wondering why?
If it's just that it needed some customization and you didn't have one handy, I might be able to help.

[BUG] `yubikey-piv` has been renamed to yubikey

Environment

  • OS: N/A
  • age-plugin-yubikey version: 0.1

What were you trying to do

INstall age-plugin-yubikey

What happened

    Updating crates.io index
  Downloaded age-plugin-yubikey v0.1.0
  Downloaded 1 crate (34.6 KB) in 0.64s
  Installing age-plugin-yubikey v0.1.0
error: failed to compile `age-plugin-yubikey v0.1.0`, intermediate artifacts can be found at `/var/folders/dh/6d8rl8lj3nn5k73d6qkb982w0000gp/T/cargo-installg3snb9`

Caused by:
  no matching package named `yubikey-piv` found
  location searched: registry `crates-io`
  required by package `age-plugin-yubikey v0.1.0`

Please upload a 0.1.1 release depending on the yubikey library instead. The yubikey-piv library was yanked yesterday.

UX: plugin interface documentation

What were you trying to do

I'm interested in writing an age plugin along similar lines to age-plugin-yubikey.

What happened

I searched but couldn't find any documentation on the plugin interface exposed by rage (and age at some point I guess).

It is possible to read the code and play around with age-plugin-yubikey to figure out how to implement an equivalent interface, but I wondered: is there any documentation on the plugin executable interface? For example: which commands or flags are required? which are optional? what are their arguments? what do they return? etc.

Does any documentation along those lines exist?

Panic on invalid Bech32 payload of identity encoding when using `-j yubikey`

Environment

  • OS: macOS
  • age-plugin-yubikey version: v0.2.0

What were you trying to do

$ echo foo | go run ./cmd/age -r age1yubikey1qwt50d05nh5vutpdzmlg5wn80xq5negm4uj9ghv0snvdd3yysf5yw3rhl3t | AGEDEBUG=plugin go run ./cmd/age -j yubikey -d
-> add-identity AGE-PLUGIN-YUBIKEY-18S3VSX

-> recipient-stanza 0 piv-p256 OIF48w A+sLGjuKxFIZE96R8iY7yYmCGoX9FtUpvJAT4ZpTqPRW
WppHUnBkdZgRRxrcv3IefnTIF8qNKf4+PVKTlxNx/QM
-> done

thread 'main' panicked at 'range end index 4 out of range for slice of length 0', /Users/filippo/.cargo/registry/src/github.com-1ecc6299db9ec823/age-plugin-yubikey-0.2.0/src/key.rs:220:54
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
age: error: yubikey plugin: failed to read line: EOF
age: report unexpected or unhelpful errors at https://filippo.io/age/report
exit status 1

Cargo says 0.2.0 is the latest version

Environment

  • OS: Arch linux
  • age-plugin-yubikey version: 0.2.0

What were you trying to do

Update to 0.3.0

What happened

Cargo says 0.2.0 is the latest.

$ age-plugin-yubikey -V
age-plugin-yubikey 0.2.0

$ cargo install-update age-plugin-yubikey
    Updating registry 'https://github.com/rust-lang/crates.io-index'

Package             Installed  Latest  Needs update
age-plugin-yubikey  v0.2.0     v0.2.0  No

No packages need updating.
Overall updated 0 packages.

Provide way to delete a key from a slot

Although one can already overwrite a slot, there is no way to delete it, which might be desirable to avoid the extra --list entry.

There should probably by a y/n confirmation prompt unless --force is used. That probably makes it ok to operate on non-age slots too.

age-plugin-yubikey support for RSA keys -- specifically, CAC ones

In Bug #39, it was said:
"We will therefore not support ssh-rsa keys (which don't match what the plugin's protocol requires) and cannot support ssh-ed25519 keys (which use a curve that YubiKey's PIV applet doesn't even support)"

I wanted to ask politely if this requirement for not supporting ssh-rsa keys could be reconsidered.

US federal government issues smartcards/CAC cards/PIV cards (various names are used) and at the moment they have RSA keys on them (an auth key, an encrypt key, etc).

For us, its either impossible or strongly discouraged to attempt to add a key of any type - and it would be EXTREMELY useful to be able to use the existing encryption key on the card (rsa) with age through this plugin.

However, I'm not a card expert and certainly not an age expert - so I don't know if there are technical details of what I just asked that make it impossible.

Question regarding generation of the shared secret with the YubiKey

As I understand it, the main benefit of external hardware security keys like the YubiKey is that the private keys never leave the device. This does not prevent any encrypted data to be leaked, which could happen on every decryption, but it makes it impossible for they decryption keys to ever be compromised. To not expose the keys, decryption happens on the hardware token itself.

After looking through this implementation for using the YubiKey as age recipient, I was a bit confused as to how exactly this is achieved.

If I am not mistaken, a shared secret is derived from the private key located on the YubiKey:

let shared_secret = match decrypt_data(
&mut self.yubikey,
line.epk_bytes.decompress().as_bytes(),
AlgorithmId::EccP256,
SlotId::Retired(self.slot),
) {
Ok(res) => res,
Err(_) => return Ok(Err(())),
};

This private key obviously does not leave the device, but the generated shared secret is exposed and could be leaked when decrypting. So the shared secret should be different for every encryption/decryption for the same Yubikey recipient by generating some sort of salt and saving that in the header of the encrypted file.

Is this how it is done or is there even a smarter way to do this? This information would be very useful regarding whether a similar implementation could be used to utilize Fido2 keys with hmac-secret extension as another form of age/rage recipient (for which I started a discussion FiloSottile/age#390).

Thank you for this plugin and also for the amazing work regarding age/rage in general!

UX: Print message to touch the Yubikey when touch expected

I currently get no prompt to touch the Yubikey when decrypting files.
This diff with additions doesn't work:

diff --git a/src/key.rs b/src/key.rs
index 01b5209..0855f3f 100644
--- a/src/key.rs
+++ b/src/key.rs
@@ -521,6 +521,9 @@ impl Connection {
             _ => false,
         };
 
+        if needs_touch {
+            println!("👆 Please touch the YubiKey.");
+        }
         // The YubiKey API for performing scalar multiplication takes the point in its
         // uncompressed SEC-1 encoding.
         let shared_secret = match decrypt_data(
$ cat foo.txt.age | ./rage/rage -d -i age-yubikey-identity-c60b9683.txt > foo.txt
Error: invalid response

[ Did rage not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/rage/report                            ]

I had a look at the code but couldn't see if you're redirecting stdout which I assume is used to communicate with rage and gets polluted by the println.

Remove need for PIN when encrypting to a YubiKey identity

We don't need a PIN to access slot certificates, so we can determine the recipient for a slot without requesting a PIN from the user. However, the RecipientPluginV1 implementation just reuses Stub::connect() -> Connection, which requests and verifies the PIN.

We should separate connecting from authenticating, and only run the second stage inside IdentityPluginV1.

"Could not open YubiKey" error message while inserted, after decrypting with GPG

Hi I encountered this bug/issue while trying to decrypt an age encrypted file.

Steps to reproduce:

  1. Encrypt a file with Age
  2. Encrypt another file with GPG gpg --encrypt --armor
  3. Decrypting the age encrypted file works as expected
  4. Decrypt the GPG encrypted file with GPG key on yubikey gpg --decrypt (Yubikey asks for pin on GPG interface)
  5. Decrypting the age encrypted file fails with the message:
    Please insert YubiKey with serial XXX (press [1] for "YubiKey is plugged in" or [2] for "Skip this YubiKey") # select 1
    Could not open YubiKey. Please insert YubiKey with serial XXX (press [1] for "YubiKey is plugged in" or [2] for "Skip this YubiKey")
    

Workaround: reinsert the yubikey and decryption works as expected.

Any idea why this might happen?

By the way, thanks for making and maintaining this plugin, it is really nice.

Smart card reader is not being ignored by `--list`, `--list-all` when no card inserted

What were you trying to do

I was trying to use age-plugin-yubikey.

What happened

Short

I am getting the following error:

age-plugin-yubikey --list-all

Error: Error while communicating with YubiKey: PC/SC error
Cause: The operation requires a Smart Card, but no Smart Card is currently in the device

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

and I don't know where to go from here.
It would be nice to have a beginner's guide section for people that aren't familiar with PIV and get here because they know age and happen to have a yubikey laying around for other things (FIDO for example)

Longer

Thank you for developing this plugin!
I got here because I am familiarizing myself with age/rage and using it for various tasks.
As I also own a yubikey, I thought it would be interesting to combine it with age and check this plugin out.
But, I am not at all familiar with PIV/smart cards, and it is a bit daunting to understand how to put the pieces together.
I think that yubico could make more effort to make it easier to introduce the PIV features, but I also guess that most people know what they are doing when getting a key as a smart card replacement.
So maybe I am just an odd duck in this case :D

It would be helpful if the README could link to relevant resources to familiarize beginners with PIV and that additional functionality.
Especially a way to test that everything else works before starting age-plugin-yubikey, as I assume that I have some other issues and that it isn't the plugin's fault.
That is my main request for the issue :)

To provide some additional information for my error message: If I run pcsc_scan the yubikey is detected and identified as a smart card.

UX: How to upload my SSH key to YubiKey?

What were you trying to do

Upload SSH key to YubiKey

What happened

I have no idea how to do it! I was pointed to here from elsewhere. Currently I have nice setup where I have SSH key in YubiKey using OpenPGP. I can generate SSH key using OpenPGP then make paper backup of it, store it to Yubikey and authenticate using pgp agent.

I'm trying to replicate this behavior with age/rage, but can't figure out how can I upload my SSH key to the YubiKey.

I suspect it's not possible to generate SSH key on my computer (to make backup of it) and store it to YubiKey. Maybe if that's the case it could be mentioned. If that is the case, I have to stick with OpenPGP generated SSH key, which can be uploaded using yubikey management tools.

UX: Generic error message on Windows 11

What were you trying to do

I've been trying to set up this plugin on Windows to use with WSL, as I sadly am dependent on Windows-only VPN software for work. However, I've been completely unable to get this to work on Windows 11, on either of my computers. The main problem here is the error message which offers no clues as to what is wrong making it hard to find the root cause of my problem.

I'm actually not 100% sure if this is a UX issue or a bug (or both), but no one else has reported a similar problem that I've seen, so I'm assuming it's me doing something dumb.

  1. I've used age-plugin-yubikey on Linux to set up an age identity on my Yubikeys successfully. Everything works as expected.
  2. I rebooted my computer into Windows 11.
  3. I dropped the released, precompiled age-plugin-yubikey binary into C:\Windows\System32, as it's on my $PATH.
  4. I've unblocked the executable:
    image
  5. Inserted a Yubikey into the computer.
  6. Opened up WSL and tried to list the identities on the Yubikey.

What happened

I get a generic error message, as shown in the transcript below. The Yubikey is fully functional in Windows, as I use to to log on the computer itself and as a second factor for a lot of websites (both Yubikey 2FA and FIDO).

$ age-plugin-yubikey.exe -i
Error: Error while communicating with YubiKey: generic error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

$ age-plugin-yubikey.exe --list
Error: Error while communicating with YubiKey: generic error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

$ age-plugin-yubikey.exe --list-all
Error: Error while communicating with YubiKey: generic error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

$ age-plugin-yubikey.exe --serial ******** --list
Error: Error while communicating with YubiKey: generic error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

Things I've tried:

  • Running age-plugin-yubikey as Administrator
  • Multiple computers
  • Multiple different Yubikeys, all with an age key installed in PIV slot 10.

"Error while communicating with YubiKey: authentication error" when using `--pin-policy always`

Environment

  • OS: Windows 10, macOS Monterey
  • age-plugin-yubikey version: 0.3.0
  • Yubikey 5C NFC

What were you trying to do

Trying to generate a new Age key through age-plugin-yubikey using the --pin-policy always option, but running into a weird error which causes it to fail generation after touching the YubiKey, whereas omitting this option or setting it to never succeeds as expected.

Fiddling with the option options like --touch-policy does not cause this problem.

What happened

$ age-plugin-yubikey --generate --pin-policy always

Enter PIN for YubiKey with serial 22317870(default is 123456): [hidden]
👆 Please touch the YubiKey
Error: Error while communicating with YubiKey: authentication error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

Omitting --pin-policy always succeeds as normal

$ age-plugin-yubikey --generate

Enter PIN for YubiKey with serial 22317870 (default is 123456): [hidden]
👆 Please touch the YubiKey
#       Serial: 22317870, Slot: 1
#         Name: age identity c8caa1bd
#      Created: Fri, 04 Nov 2022 12:12:26 +0000
#   PIN policy: Once   (A PIN is required once per session, if set)
# Touch policy: Always (A physical touch is required for every decryption)
#    Recipient: age1yubikey1qdszmlws3r8f69argu7u2kkxp02nnfcdsxmjfs49ghehc6ufp6dqjxw0lyk
AGE-PLUGIN-YUBIKEY-19694GQVZER92R0GZMVQ69

UX: Print message if Yubikey is waiting for touch

This might fit better in the Rage and/or Age repo; I don't really know exactly where/how this would be handled. Let me know and I can close this bug and reopen elsewhere if needed. :)

What were you trying to do

Decrypt a file using an age key on my Yubikey

What happened

Ran this to decrypt:

> cat test.txt.age | rage -d -i age-yk-id-20.txt > test.txt

Terminal sat quietly waiting for a Yubikey touch. It's easy to miss that it might be waiting for this, so it may be nice to print a message to the console when awaiting a key touch. E.g.:

> cat test.txt.age | rage -d -i age-yk-id-20.txt > test.txt
Awaiting Yubikey touch...
# user touches key, operation completes
> 

UX: Make --identity behave the same as --list

  • Both commands should print all slots from all connected YubiKeys by default.
  • When printing multiple slots, print a stderr notice saying "generated recipients/identities for X slots. If you intended to select a slot, use --slot"
  • If --serial is specified (without --slot) then print all slots in that YubiKey (with the notice).
  • If --slot is specified then then instead print a single slot (requiring --serial if necessary to select a single YubiKey).

Touching YK while prompting PIN causes error

Environment

  • OS: macOS
  • age-plugin-yubikey version: 0.1.0

What were you trying to do

I accidentally touched the YK too soon while pressing enter on the PIN prompt, so the touch arrived before the PIN. I expected it to just ignore the touch.

What happened

[age-plugin-yubikey] Please insert YubiKey with serial 15413828
[age-plugin-yubikey] Enter PIN for YubiKey with serial 15413828
[age-plugin-yubikey] Enter value:
age: error: age-plugin-yubikey: "Invalid YubiKey PIN"

x25519 support for Yubikey

We would like to combine Age and Yubikey, but we are interested in using curves that are not currently supported with this plugin like x25519, secp521r1 etc.
It's technically feasible, over the openpgp smartcard application on the Yubikey, but I see that this plugin uses the Yubikey Rust library which only has PIV support so it seems pretty difficult to add this functionality to the current plugin.
So I guess my question is: is this something you are interested in as well or does it make more sense if we create a new plugin for it?

"size error" generating a key on macOS 12.4

Environment

  • OS: macOS 12.4 (21F79)
  • age-plugin-yubikey version: age-plugin-yubikey 0.3.0

What were you trying to do

I'm trying to generate an age key on my two yubikey 4c nanos' PIV slot. Each of the yubikeys has a GPG key stored on it, and each is connected to a different mac - one M1 max macbook pro, and one to an x86-64 macbook pro. The PINs are somewhere between 9 and 15 digits long (but only numerical). Neither successfully generates a key, reporting "size error".

What happened

On the M1 max machine:

:;    age-plugin-yubikey -- --generate --name 'personal 4c'

Enter PIN for YubiKey with serial 6900832 (default is 123456): [hidden]
Error: Error while communicating with YubiKey: size error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

Same on the intel machine:

:;    ~/.cargo/bin/age-plugin-yubikey --generate --name 'work 4c'

Enter PIN for YubiKey with serial 15748267 (default is 123456): [hidden]
Error: Error while communicating with YubiKey: size error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

Clarify what kind of Yubikey is required in README.

There are a few different kinds of yubikey and I'm unsure which is required for usage with age-plugin-yubikey.

For example I have one of those cheap github-branded ones somewhere. I know I can't use that one for storing gpg keys. I suppose I can't use it for age either? Can we say what is required in README?

Thanks.

Updating touch-policy to "cached"&pin-policy to "once": no effect on existing slots

Environment

  • OS: macOS ventura
  • age-plugin-yubikey version: 0.3.2

What were you trying to do

I used age-plugin-yubikey --pin-policy once --touch-policy cached to reduce the number of times I have to provide my PIN and touch the key (especially for rekeying secrets with https://github.com/ryantm/agenix).

What happened

:;    age-plugin-yubikey --pin-policy once --touch-policy cached
✨ Let's get your YubiKey set up for age! ✨

This tool can create a new age identity in a free slot of your YubiKey.
It will generate an identity file that you can use with an age client,
along with the corresponding recipient. You can also do this directly
with:
    age-plugin-yubikey --generate

If you are already using a YubiKey with age, you can select an existing
slot to recreate its corresponding identity file and recipient.

When asked below to select an option, use the up/down arrow keys to
make your choice, or press [Esc] or [q] to quit.

🔑 Select a YubiKey: Yubico YubiKey FIDO+CCID (Serial: 6900832)
🕳️  Select a slot for your age identity: Slot 1 (asf personal 4c, created: Sun, 05 Jun 2022 14:25:06 +0000)
Use existing identity in slot 1? yes

📝 File name to write this identity to: age-yubikey-identity-18fdcdd5.txt
File exists. Overwrite it? yes

✅ Done! This YubiKey identity is ready to go.

🔑 Here's the corresponding YubiKey recipient:
  age1yubikey1q0m3cprmex0d2thamkx9pwvhsqwcm2gel50rdxmeclvkgqtem9dxz4smpwv

Here are some example things you can do with it:

- Encrypt a file to this identity:
  $ cat foo.txt | rage -r age1yubikey1q0m3cprmex0d2thamkx9pwvhsqwcm2gel50rdxmeclvkgqtem9dxz4smpwv -o foo.txt.age

- Decrypt a file with this identity:
  $ cat foo.txt.age | rage -d -i age-yubikey-identity-18fdcdd5.txt > foo.txt

- Recreate the identity file:
  $ age-plugin-yubikey -i --serial 6900832 --slot 1 > age-yubikey-identity-18fdcdd5.txt

- Recreate the recipient:
  $ age-plugin-yubikey -l --serial 6900832 --slot 1

💭 Remember: everything breaks, have a backup plan for when this YubiKey does.

and then,

:;    cat age-yubikey-identity-18fdcdd5.txt
#       Serial: 6900832, Slot: 1
#         Name: asf personal 4c
#      Created: Sun, 05 Jun 2022 14:25:06 +0000
#   PIN policy: Once   (A PIN is required once per session, if set)
# Touch policy: Always (A physical touch is required for every decryption)
#    Recipient: age1yubikey1q0m3cprmex0d2thamkx9pwvhsqwcm2gel50rdxmeclvkgqtem9dxz4smpwv
AGE-PLUGIN-YUBIKEY-1VPXXJQYZRR7UM4GESUNXL
:;    rage -i identities/personal-4c.txt -d some-secret.age
Enter PIN for YubiKey with serial 6900832:
yay!
:;    rage -i identities/personal-4c.txt -d some-secret.age
Enter PIN for YubiKey with serial 6900832:
yay!

Note that each PIN prompt also requires a touch of the yubikey. I'm not sure what's going on here, but my hypothesis is that existing slots' settings can't be changed? Is that right?

UX: request for clarification - does "--identity" print secret data?

What were you trying to do

I'm trying to figure out how to use age-plugin-yubikey to safely store my nix secrets with agenix. agenix requires an "identity" file be present to decrypt the stored secrets, and I'm trying to figure out if it's safe to store output of age-plugin-yubikey --identity in the repo (assuming it's akin to the gpg "key grips" you get with smart cards), or if that contains any of the secret data that would otherwise rest safely on my yubikey.

What happened

I was hoping the docs could clear that up, but they refer to "identities stored on yubikeys" and then show how to print an identity in https://github.com/str4d/age-plugin-yubikey#configuration; so it would be good to have clarification on how secret the information printed really is.

Hash public key directly into stanza tag

The stanza tag is currently hashing the bech32, which feels redundant. The SSH stanza tag is a hash of the SSH wire format, so here we could hash the public key directly.

RUSTSEC-2021-0145 RUSTSEC-2020-0159 RUSTSEC-2020-0071

user@linux ~ $ osv-scanner age-plugin-yubikey/
Scanning dir age-plugin-yubikey/
Scanning /home/user/age-plugin-yubikey/ at commit aaa445c4ac9c8d7d45ba0c652e5cdefed0e7853b
Scanned /home/user/age-plugin-yubikey/Cargo.lock file and found 179 packages
╭───────────────────────────────────────────────────┬───────────┬─────────┬─────────┬───────────────────────────────╮
│ OSV URL (ID IN BOLD)                              │ ECOSYSTEM │ PACKAGE │ VERSION │ SOURCE                        │
├───────────────────────────────────────────────────┼───────────┼─────────┼─────────┼───────────────────────────────┤
│ https://osv.dev/vulnerability/RUSTSEC-2021-0145   │ crates.io │ atty    │ 0.2.14  │ age-plugin-yubikey/Cargo.lock │
│ https://osv.dev/vulnerability/RUSTSEC-2020-0159   │ crates.io │ chrono  │ 0.4.19  │ age-plugin-yubikey/Cargo.lock │
│ https://osv.dev/vulnerability/GHSA-wcg3-cvx6-7396 │ crates.io │ time    │ 0.1.43  │ age-plugin-yubikey/Cargo.lock │
│ https://osv.dev/vulnerability/RUSTSEC-2020-0071   │           │         │         │                               │
╰───────────────────────────────────────────────────┴───────────┴─────────┴─────────┴───────────────────────────────╯

UX: Needed to install pcscd on Ubuntu

What were you trying to do

Install and run age-plugin-yubikey on an Ubuntu desktop OS.

What happened

$ age-plugin-yubikey --list-all
Error: Error while communicating with YubiKey: PC/SC error
Cause: The Smart card resource manager is not running

Solution

I resolved this by running sudo apt-get install pcscd. (I also had to install libpcsclite-dev previously to satisfy a compile-time dependency)

Send SIGHUP to yubikey-agent

Similarly to gpg-agent, yubikey-agent keeps an exclusive open connection to the PIV applet.

yubikey-agent is nicer than gpg-agent, so all you need to do is send it SIGHUP to have it release the lock.

Should be easy to add support for this along with the gpg-agent killing?

Cannot provide PIN for second plugged-in key

What were you trying to do

I had two YubiKeys plugged in, and an age file encrypted to both of them. However, the first YK it selected I didn't know the PIN for, so I clicked "Cancel" hoping it would skip to the next key.

What happened

Error: '⁨age-plugin-yubikey⁩' couldn't use an identity: ⁨A PIN is required for YubiKey with serial ######

UX: setup stuck at "Please touch the YubiKey"

What were you trying to do

I'm trying to follow Configuration docs

What happened

$ age-plugin-yubikey --version
age-plugin-yubikey 0.3.2

$ age-plugin-yubikey

⏳ Please insert the YubiKey you want to set up.
🔑 Select a YubiKey: Yubico YubiKey OTP+FIDO+CCID (Serial: 41XXX36)
🕳️  Select a slot for your age identity: Slot 1 (Empty)
📛 Name this identity [age identity TAG_HEX]: lly
🔤 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 identity in slot 1? yes


Enter PIN for YubiKey with serial 4160736 (default is 123456): [hidden]
👆 Please touch the YubiKey
... hangs ...

Any tips what I'm missing?

Device

  • I have a YubiKey 4 nano with 4.2.6 firmware
  • os: macOS Monterey v12.5.12
  • I've already tried the "reset" with the official YubiKey Manager (see screenshot below)

Screenshot

image

Drop version from HKDF label

age-encryption.org/v1/piv-p256 is nested under age-encryption.org/v1, which is a format version that can be orthogonal of the plugin stanza version.

This stanza can be simply age-encryption.org/piv-p256.

FR: Put the same age key on multiple Yubikeys

For backup reasons I would like to be able to put an age private key on more than one Yubikey so in case one Yubikey breaks, gets lost, is unusable in some other way, I would have another key that could decrypt my files. I might have overlooked such a feature, if so, please let me know how to do it.

UX: Add example commands to end of TUI

At the end of the interactive process, it would be nice to have copy-pastable commands for:

  • age encryption
  • age decrypt
  • age-plugin-yubikey -i (recreate identity file, teaches you it's not a secret)
  • age-plugin-yubikey -l

UX: timing of when to touch the YubiKey during identity generation is not clear

What were you trying to do

When attempting to set up the initial identity on the YubiKey there is a step after PIN entry where the plugin prompts the user to touch the YubiKey. (This prompt was not preserved in my Terminal output.) However, after touching the YubiKey, the plugin fails to generate the identity.

After a lot of fussing and experimenting, I discovered that if I touch the YubiKey before running the plugin command, and if I run through the prompts quickly enough, the plugin does not prompt me to touch and the identity generation succeeds.

My setup is an Apple Silicon MacBook Pro running macOS 12.2. I used Terminal.app with age-plugin-yubikey version 0.3.0. My YubiKey is a YubiKey 5 NFC with firmware 5.4.3.

What happened

setup@Cheonmachong age-plugin-yubikey % ./age-plugin-yubikey
[INFO  i18n_embed::requester] Current Locale: [LanguageIdentifier { language: Language(Some("en")), script: None, region: Some(Region("US")), variants: None }]
[DEBUG i18n_embed] Selecting translations for domain "age_plugin_yubikey"
[DEBUG i18n_embed] Searching for available languages, found language file: "en-US/age_plugin_yubikey.ftl"
[DEBUG i18n_embed] Requested Languages: [LanguageIdentifier { language: Language(Some("en")), script: None, region: Some(Region("US")), variants: None }]
[DEBUG i18n_embed] Available Languages: [LanguageIdentifier { language: Language(Some("en")), script: None, region: Some(Region("US")), variants: None }]
[DEBUG i18n_embed] Supported Languages: [LanguageIdentifier { language: Language(Some("en")), script: None, region: Some(Region("US")), variants: None }]
[DEBUG i18n_embed] Attempting to load language file: "en-US/age_plugin_yubikey.ftl"
[DEBUG i18n_embed::fluent] Loaded language file: "en-US/age_plugin_yubikey.ftl" for language: "en-US"
✨ Let's get your YubiKey set up for age! ✨

This tool can create a new age identity in a free slot of your YubiKey.
It will generate an identity file that you can use with an age client,
along with the corresponding recipient. You can also do this directly
with:
    age-plugin-yubikey --generate

If you are already using a YubiKey with age, you can select an existing
slot to recreate its corresponding identity file and recipient.

When asked below to select an option, use the up/down arrow keys to
make your choice, or press [Esc] or [q] to quit.

[INFO  yubikey::yubikey] connected to reader: Yubico YubiKey OTP+FIDO+CCID
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: SelectApplication, p1: 4, p2: 0, data: [160, 0, 0, 3, 8] }
[TRACE yubikey::transaction] >>> [0, 164, 4, 0, 5, 160, 0, 0, 3, 8]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [97, 17, 79, 6, 0, 0, 16, 0, 1, 0, 121, 7, 79, 5, 160, 0, 0, 3, 8] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetVersion, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 253, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [5, 4, 3] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetSerial, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 248, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [1, 17, 241, 73] }
[INFO  yubikey::yubikey] connected to reader: Yubico YubiKey OTP+FIDO+CCID
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: SelectApplication, p1: 4, p2: 0, data: [160, 0, 0, 3, 8] }
[TRACE yubikey::transaction] >>> [0, 164, 4, 0, 5, 160, 0, 0, 3, 8]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [97, 17, 79, 6, 0, 0, 16, 0, 1, 0, 121, 7, 79, 5, 160, 0, 0, 3, 8] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetVersion, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 253, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [5, 4, 3] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetSerial, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 248, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [1, 17, 241, 73] }
[INFO  yubikey::yubikey] connected to reader: Yubico YubiKey OTP+FIDO+CCID
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: SelectApplication, p1: 4, p2: 0, data: [160, 0, 0, 3, 8] }
[TRACE yubikey::transaction] >>> [0, 164, 4, 0, 5, 160, 0, 0, 3, 8]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [97, 17, 79, 6, 0, 0, 16, 0, 1, 0, 121, 7, 79, 5, 160, 0, 0, 3, 8] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetVersion, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 253, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [5, 4, 3] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetSerial, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 248, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [1, 17, 241, 73] }
[INFO  yubikey::yubikey] connected to reader: Yubico YubiKey OTP+FIDO+CCID
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: SelectApplication, p1: 4, p2: 0, data: [160, 0, 0, 3, 8] }
[TRACE yubikey::transaction] >>> [0, 164, 4, 0, 5, 160, 0, 0, 3, 8]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [97, 17, 79, 6, 0, 0, 16, 0, 1, 0, 121, 7, 79, 5, 160, 0, 0, 3, 8] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetVersion, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 253, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [5, 4, 3] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetSerial, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 248, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [1, 17, 241, 73] }
🔑 Select a YubiKey: Yubico YubiKey OTP+FIDO+CCID (Serial: 17953097)
[INFO  yubikey::yubikey] connected to reader: Yubico YubiKey OTP+FIDO+CCID
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: SelectApplication, p1: 4, p2: 0, data: [160, 0, 0, 3, 8] }
[TRACE yubikey::transaction] >>> [0, 164, 4, 0, 5, 160, 0, 0, 3, 8]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [97, 17, 79, 6, 0, 0, 16, 0, 1, 0, 121, 7, 79, 5, 160, 0, 0, 3, 8] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetVersion, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 253, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [5, 4, 3] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetSerial, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 248, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [1, 17, 241, 73] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 5] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 5]
[TRACE yubikey::apdu] <<< Response { status_words: Other(24922), data: [83, 130, 1, 86, 112, 130, 1, 77, 48, 130, 1, 73, 48, 129, 240, 160, 3, 2, 1, 2, 2, 20, 72, 245, 43, 55, 128, 115, 140, 152, 116, 1, 21, 218, 153, 41, 33, 220, 139, 80, 222, 173, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 32, 23, 13, 50, 50, 48, 52, 51, 48, 50, 48, 53, 55, 50, 55, 90, 24, 15, 50, 48, 53, 50, 48, 52, 51, 48, 48, 48, 48, 48, 48, 48, 90, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 53, 134, 114, 18, 186, 241, 97, 161, 216, 170, 179, 160, 100, 60, 236, 219, 181, 23, 23, 166, 185, 161, 196, 43, 227, 143, 111, 153, 237, 36, 23, 94, 174, 138, 129, 43, 80, 75, 226, 95, 50, 62, 68, 52, 110, 92, 236, 64, 15, 171, 81, 94, 63, 106, 63, 72, 183, 234, 115, 61, 171, 139, 100, 5, 48] }
[TRACE yubikey::transaction] The card indicates there is 90 bytes more data for us
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetResponseApdu, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 192, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 32, 7, 88, 209, 113, 52, 183, 164, 41, 5, 12, 202, 89, 130, 212, 25, 124, 179, 58, 210, 131, 127, 117, 151, 214, 119, 101, 164, 161, 124, 218, 145, 152, 2, 33, 0, 204, 40, 113, 255, 223, 224, 227, 7, 179, 91, 111, 147, 204, 95, 244, 186, 162, 35, 81, 38, 126, 199, 169, 116, 1, 57, 98, 117, 171, 72, 20, 109, 113, 1, 0, 254, 0] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 10] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 10]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 11] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 11]
[TRACE yubikey::apdu] <<< Response { status_words: Other(24922), data: [83, 130, 1, 86, 112, 130, 1, 77, 48, 130, 1, 73, 48, 129, 240, 160, 3, 2, 1, 2, 2, 20, 72, 90, 230, 128, 21, 70, 178, 46, 56, 206, 129, 108, 124, 51, 69, 230, 123, 39, 147, 236, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 32, 23, 13, 50, 50, 48, 52, 51, 48, 50, 48, 53, 55, 50, 55, 90, 24, 15, 50, 48, 53, 50, 48, 52, 51, 48, 48, 48, 48, 48, 48, 48, 90, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 193, 167, 14, 132, 93, 63, 26, 162, 81, 1, 157, 33, 167, 246, 41, 170, 215, 114, 197, 123, 122, 118, 86, 44, 234, 85, 244, 127, 16, 188, 188, 199, 255, 121, 32, 217, 173, 208, 101, 165, 183, 83, 228, 60, 173, 167, 2, 22, 237, 139, 43, 220, 154, 217, 254, 168, 0, 253, 13, 119, 187, 94, 170, 79, 48] }
[TRACE yubikey::transaction] The card indicates there is 90 bytes more data for us
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetResponseApdu, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 192, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 32, 17, 197, 47, 199, 192, 23, 194, 244, 2, 105, 10, 241, 226, 38, 87, 194, 123, 67, 187, 51, 151, 76, 11, 29, 241, 185, 31, 104, 182, 226, 33, 171, 2, 33, 0, 251, 48, 93, 238, 118, 117, 196, 76, 112, 236, 255, 89, 223, 29, 230, 201, 65, 221, 175, 217, 249, 196, 7, 206, 239, 182, 75, 253, 10, 34, 240, 144, 113, 1, 0, 254, 0] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 13] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 13]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 14] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 14]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 15] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 15]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 16] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 16]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 17] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 17]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 18] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 18]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 19] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 19]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 20] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 20]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 21] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 21]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 22] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 22]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 23] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 23]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 24] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 24]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 25] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 25]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 26] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 26]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 27] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 27]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 28] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 28]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 29] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 29]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 30] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 30]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 31] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 31]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 32] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 32]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 1] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 1]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
🕳️  Select a slot for your age identity: Slot 1 (Empty)
📛 Name this identity [age identity TAG_HEX]: Passwords
🔤 Select a PIN policy: Always (A PIN is required for every decryption, if set)
👆 Select a touch policy: Never  (A physical touch is NOT required to decrypt)
Generate new identity in slot 1? yes

[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 5] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 5]
[TRACE yubikey::apdu] <<< Response { status_words: Other(24922), data: [83, 130, 1, 86, 112, 130, 1, 77, 48, 130, 1, 73, 48, 129, 240, 160, 3, 2, 1, 2, 2, 20, 72, 245, 43, 55, 128, 115, 140, 152, 116, 1, 21, 218, 153, 41, 33, 220, 139, 80, 222, 173, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 32, 23, 13, 50, 50, 48, 52, 51, 48, 50, 48, 53, 55, 50, 55, 90, 24, 15, 50, 48, 53, 50, 48, 52, 51, 48, 48, 48, 48, 48, 48, 48, 90, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 53, 134, 114, 18, 186, 241, 97, 161, 216, 170, 179, 160, 100, 60, 236, 219, 181, 23, 23, 166, 185, 161, 196, 43, 227, 143, 111, 153, 237, 36, 23, 94, 174, 138, 129, 43, 80, 75, 226, 95, 50, 62, 68, 52, 110, 92, 236, 64, 15, 171, 81, 94, 63, 106, 63, 72, 183, 234, 115, 61, 171, 139, 100, 5, 48] }
[TRACE yubikey::transaction] The card indicates there is 90 bytes more data for us
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetResponseApdu, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 192, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 32, 7, 88, 209, 113, 52, 183, 164, 41, 5, 12, 202, 89, 130, 212, 25, 124, 179, 58, 210, 131, 127, 117, 151, 214, 119, 101, 164, 161, 124, 218, 145, 152, 2, 33, 0, 204, 40, 113, 255, 223, 224, 227, 7, 179, 91, 111, 147, 204, 95, 244, 186, 162, 35, 81, 38, 126, 199, 169, 116, 1, 57, 98, 117, 171, 72, 20, 109, 113, 1, 0, 254, 0] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 10] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 10]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 11] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 11]
[TRACE yubikey::apdu] <<< Response { status_words: Other(24922), data: [83, 130, 1, 86, 112, 130, 1, 77, 48, 130, 1, 73, 48, 129, 240, 160, 3, 2, 1, 2, 2, 20, 72, 90, 230, 128, 21, 70, 178, 46, 56, 206, 129, 108, 124, 51, 69, 230, 123, 39, 147, 236, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 32, 23, 13, 50, 50, 48, 52, 51, 48, 50, 48, 53, 55, 50, 55, 90, 24, 15, 50, 48, 53, 50, 48, 52, 51, 48, 48, 48, 48, 48, 48, 48, 90, 48, 36, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 89, 117, 98, 105, 99, 111, 32, 80, 73, 86, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 193, 167, 14, 132, 93, 63, 26, 162, 81, 1, 157, 33, 167, 246, 41, 170, 215, 114, 197, 123, 122, 118, 86, 44, 234, 85, 244, 127, 16, 188, 188, 199, 255, 121, 32, 217, 173, 208, 101, 165, 183, 83, 228, 60, 173, 167, 2, 22, 237, 139, 43, 220, 154, 217, 254, 168, 0, 253, 13, 119, 187, 94, 170, 79, 48] }
[TRACE yubikey::transaction] The card indicates there is 90 bytes more data for us
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetResponseApdu, p1: 0, p2: 0, data: [] }
[TRACE yubikey::transaction] >>> [0, 192, 0, 0, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 32, 17, 197, 47, 199, 192, 23, 194, 244, 2, 105, 10, 241, 226, 38, 87, 194, 123, 67, 187, 51, 151, 76, 11, 29, 241, 185, 31, 104, 182, 226, 33, 171, 2, 33, 0, 251, 48, 93, 238, 118, 117, 196, 76, 112, 236, 255, 89, 223, 29, 230, 201, 65, 221, 175, 217, 249, 196, 7, 206, 239, 182, 75, 253, 10, 34, 240, 144, 113, 1, 0, 254, 0] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 13] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 13]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 14] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 14]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 15] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 15]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 16] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 16]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 17] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 17]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 18] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 18]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 19] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 19]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 20] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 20]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 21] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 21]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 22] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 22]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 23] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 23]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 24] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 24]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 25] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 25]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 26] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 26]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 27] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 27]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 28] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 28]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 29] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 29]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 30] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 30]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 31] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 31]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 32] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 32]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 1] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 1]
[TRACE yubikey::apdu] <<< Response { status_words: NotFoundError, data: [] }

Enter PIN for YubiKey with serial 17953097 (default is 123456): [hidden]
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: Verify, p1: 0, p2: 128, data: [54, 50, 53, 50, 50, 57, 54, 51] }
[TRACE yubikey::transaction] >>> [0, 32, 0, 128, 8, 54, 50, 53, 50, 50, 57, 54, 51]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [] }
[TRACE yubikey::transaction] going to send 5 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GetData, p1: 63, p2: 255, data: [92, 3, 95, 193, 9] }
[TRACE yubikey::transaction] >>> [0, 203, 63, 255, 5, 92, 3, 95, 193, 9]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [83, 28, 136, 26, 137, 24, 4, 246, 42, 150, 19, 33, 134, 31, 113, 119, 168, 252, 94, 163, 212, 52, 208, 136, 141, 249, 147, 63, 160, 222] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: Authenticate, p1: 3, p2: 155, data: [124, 2, 128, 0] }
[TRACE yubikey::transaction] >>> [0, 135, 3, 155, 4, 124, 2, 128, 0]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [124, 10, 128, 8, 155, 71, 30, 235, 209, 7, 247, 53] }
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: Authenticate, p1: 3, p2: 155, data: [124, 20, 128, 8, 20, 211, 92, 211, 71, 129, 29, 223, 129, 8, 65, 21, 180, 116, 187, 129, 123, 142] }
[TRACE yubikey::transaction] >>> [0, 135, 3, 155, 22, 124, 20, 128, 8, 20, 211, 92, 211, 71, 129, 29, 223, 129, 8, 65, 21, 180, 116, 187, 129, 123, 142]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [124, 10, 130, 8, 23, 227, 221, 4, 198, 241, 241, 68] }
[TRACE yubikey::transaction] going to send 11 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: GenerateAsymmetric, p1: 0, p2: 130, data: [172, 9, 128, 1, 17, 170, 1, 3, 171, 1, 1] }
[TRACE yubikey::transaction] >>> [0, 71, 0, 130, 11, 172, 9, 128, 1, 17, 170, 1, 3, 171, 1, 1]
[TRACE yubikey::apdu] <<< Response { status_words: Success, data: [127, 73, 67, 134, 65, 4, 219, 38, 32, 188, 217, 239, 31, 213, 51, 50, 2, 31, 217, 224, 17, 118, 141, 204, 154, 2, 213, 1, 193, 53, 139, 51, 42, 128, 132, 177, 63, 134, 154, 206, 207, 232, 7, 46, 75, 231, 137, 164, 23, 165, 146, 34, 206, 50, 66, 179, 228, 170, 62, 217, 114, 184, 1, 95, 85, 253, 30, 35, 181, 203] }
[TRACE yubikey::transaction] going to send 38 bytes in this go
[TRACE yubikey::apdu] >>> Apdu { cla: 0, ins: Authenticate, p1: 17, p2: 130, data: [124, 36, 130, 0, 129, 32, 153, 26, 233, 128, 4, 156, 65, 216, 110, 159, 11, 59, 208, 155, 54, 17, 174, 123, 207, 22, 79, 162, 220, 42, 193, 225, 88, 85, 139, 239, 93, 127] }
[TRACE yubikey::transaction] >>> [0, 135, 17, 130, 38, 124, 36, 130, 0, 129, 32, 153, 26, 233, 128, 4, 156, 65, 216, 110, 159, 11, 59, 208, 155, 54, 17, 174, 123, 207, 22, 79, 162, 220, 42, 193, 225, 88, 85, 139, 239, 93, 127]
[TRACE yubikey::apdu] <<< Response { status_words: SecurityStatusError, data: [] }
[ERROR yubikey::transaction] failed sign command with code 6982
Error: Error while communicating with YubiKey: authentication error

[ Did this not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/age-plugin-yubikey/report              ]

UX: In TUI, ask for filename to store identity in

It's confusing to finish the interactive flow and end up with an age identity printed to stdout with no idea how to use it. We have --generate and --identity now for printing to stdout, so for the TUI we should instead ask for a filename to store the identity in. This also frees up the end of the TUI for other notices.

The default filename should be age-yubikey-identity-TAG.txt.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.