#openpgp #piv #tools #tool #cargo #pgp

app openpgp-piv-tools

A CLI tool for using PIV devices in an OpenPGP context

2 releases

0.0.2 Jun 24, 2023
0.0.1 Jun 15, 2023

#2053 in Cryptography


859 lines


crates.io openpgp-piv-tools status-badge Mastodon Matrix: #openpgp-card:matrix.org

This crate implements opgpiv, an exploratory CLI tool that exposes the functionality in openpgp-piv-sequoia to use PIV devices in an OpenPGP context.

Uploading OpenPGP component keys to the YubiKey PIV application

Import of key material to cards is possible via the PIV interface.

By default, the upload command automatically chooses the appropriate subkey from the OpenPGP key (assuming exactly one subkey exists for the requested function) and uploads it to the appropriate key slot in the PIV application:

  • Authentication subkey: PIV Authentication key 9A
  • Signing subkey: PIV Digital signature key 9C
  • Encryption subkey: PIV Key management key 9D
$ cargo run -- upload --serial 16019180 --slot dec --key /tmp/janus.key

Currently supported slot identifiers: sig, dec, aut, ret01, ret02, ret03, ret04, ret05 (the slots for retired keys ["retXX"] can be used for decryption keys).

Alternatively, the --fingerprint of a component key can be explicitly specified, like this:

$ cargo run -- upload --serial 16019180 --slot dec --key /tmp/janus.key --fingerprint 6771DFE6E3E7C57E36E67A8CBC64A0240E63DA8A

After also uploading the sig subkey:

$ cargo run -- upload --serial 16019180 --slot sig --key /tmp/janus.key

let's inspect the status of the PIV application:

$ cargo run -- status --serial 16019180
=== PIV device, Serial 16019180: Yubico YubiKey OTP+FIDO+CCID 01 00 (version: 5.2.7) ===
Slot 9A [Authentication]

Slot 9C [Signature]
  Serial:      5f:84:ef:01:df:bc:a6:01:a1:a1:57:14:6b:f7:d1:56:0c:17:a9:ac
  Issuer:      CN=Janus <janus@example.org>
  Subject PKI: Rsa2048

Slot 9D [KeyManagement]
  Serial:      67:71:df:e6:e3:e7:c5:7e:36:e6:7a:8c:bc:64:a0:24:0e:63:da:8a
  Issuer:      CN=Janus <janus@example.org>
  Subject PKI: Rsa2048


(Adding the -v flag additionally outputs the full X.509 certificate information, for debugging purposes.)


We encrypt a message to the "Janus" key:

$ sq key extract-cert /tmp/janus.key --output /tmp/janus.cert
$ echo "hello world" | sq encrypt --recipient-file /tmp/janus.cert > /tmp/enc

And then decrypt it on the PIV device:

$ cat /tmp/enc | cargo run -- decrypt --serial 16019180 --cert /tmp/janus.key


Analogously, we can generate an OpenPGP signature on the PIV device:

$ echo "foo" | cargo run -- sign --serial 16019180 --cert /tmp/janus.cert > /tmp/sig

And verify the signature:

$ echo "foo" | sq verify --signer-file /tmp/janus.cert --detached /tmp/sig


~1M SLoC