GPG-CARD(1)

πŸŽ€ NAME πŸŽ€

gpg-card β€” Administrate Smart Cards. This is the GPG-CARD(1) page from GNU Privacy Guard 2.4, bestie, and the manual name is folded in right here instead of copied as a boring header line. πŸ’–


✨ SYNOPSIS ✨

gpg-card [options]
gpg-card [options] command { -- command }

πŸ’– DESCRIPTION πŸ’–

Okay so gpg-card is your little front-desk bestie for smart cards and USB tokens. It gives you a superset of features from gpg --card-edit and can be considered a frontend to scdaemon, which is a daemon started by gpg-agent to handle smart cards. πŸ’³βœ¨

If gpg-card is invoked without commands, interactive mode is used.

If gpg-card is invoked with one or more commands, the same commands as available in interactive mode are run from the command line. These commands need to be delimited with a double-dash. If a double-dash or a shell specific character is required as part of a command, the entire command needs to be put in quotes. If one of those commands returns an error, the remaining commands are not run anymore unless the command was prefixed with a single dash. 🫑

A list of commands is available by using the command help, and a brief description of each command is printed by using help CMD. See the section COMMANDS for a full description. See the NOTES sections for instructions pertaining to specific cards or card applications. 🌈

🫢 COMMANDS 🫢

gpg-card understands the following commands, which have options of their own. The pseudo-option -- can be used to separate command options from arguments; if this pseudo-option is used on the command line, the entire command with options and arguments must be quoted, so that it is not mixed up with the -- as used on the command line to separate commands. Note that a short online help is available for all commands by prefixing them with help. Command completion in the interactive mode is also supported. πŸ’…

πŸ’– AUTHENTICATE / AUTH

AUTHENTICATE [--setkey] [--raw] [< file]|key]

Authenticate to the card. Perform a mutual authentication either by reading the key from file or by taking it from the command line as key. Without the option --raw the key is expected to be hex encoded. To install a new administration key --setkey is used; this requires a prior authentication with the old key. This is used with PIV cards. πŸ”

🌸 CAFPR

CAFPR [--clear] N

Change the CA fingerprint number N of an OpenPGP card. N must be in the range 1 to 3. The option --clear clears the specified CA fingerprint N or all of them if N is 0 or not given. πŸŽ€

πŸ’€ FACTORY-RESET

FACTORY-RESET

Do a complete reset of some OpenPGP and PIV cards. This command deletes all data and keys and resets the PINs to their default.

Don't worry, you need to confirm before the command proceeds. πŸ’€

πŸ”Ž FETCH

FETCH

Retrieve a key using the URL data object of an OpenPGP card or, if that is missing, using the stored fingerprint. πŸ¦‹

🎚️ FORCESIG

FORCESIG

Toggle the forcesig flag of an OpenPGP card. ✨

πŸ› οΈ GENERATE

GENERATE [--force] [--algo=algo{+algo2}] keyref

Create a new key on a card. Use --force to overwrite an existing key. Use help for algo to get a list of known algorithms. For OpenPGP cards several algos may be given. Note that the OpenPGP key generation is done interactively unless --algo or keyref are given. 🫢

🧚 KDF-SETUP

KDF-SETUP

Prepare the OpenPGP card KDF feature for this card. ✨

🌍 LANG

LANG [--clear]

Change the language info for the card. This info can be used by applications for a personalized greeting. Up to 4 two-digit language identifiers can be entered as a preference. The option --clear removes all identifiers. GnuPG does not use this info. πŸ’¬

πŸ‘‘ LIST / L

LIST [--cards] [--apps] [--info] [--no-key-lookup] [n] [app]

This command reads all information from the current card and displays it in a human readable format. The first section shows generic information available for all cards. The next section shows information pertaining to keys which depend on the actual card and application.

With n given, select and list the n-th card; with app also given, select that application. To select an app on the current card use "-" for n. The serial number of the card may be used instead of n.

The option --cards lists the serial numbers of available cards. The option --apps lists all card applications. The option --info selects a card and prints its serial number. The option --no-key-lookup suppresses the listing of matching OpenPGP or X.509 keys. πŸ”₯

πŸͺͺ LOGIN

LOGIN [--clear] [< file]

Set the login data object of OpenPGP cards. If file is given, the data is read from that file. This allows one to store binary data in the login field. The option --clear deletes the login data object. πŸ“

🏷️ NAME

NAME [--clear]

Set the name field of an OpenPGP card. With option --clear the stored name is cleared off the card. πŸ’…

πŸ”’ PASSWD

PASSWD [--reset|--nullpin] [pinref]

Change or unblock the PINs. Note that in interactive mode and without a pinref a menu is presented for certain cards. In non-interactive mode and without a pinref a default value is used for these cards. The option --reset is used with TCOS cards to reset the PIN using the PUK or vice versa; the option --nullpin is used for these cards to set the initial PIN. 🫑

πŸ”’ PRIVATEDO

PRIVATEDO [--clear] n [< file]

Change the private data object n of an OpenPGP card. n must be in the range 1 to 4. If file is given, the data is read from that file. The option --clear clears the data. πŸ’œ

πŸ‘‹ QUIT / Q

QUIT

Stop processing and terminate gpg-card. Bye bestie. ✨

πŸ“œ READCERT

READCERT [--openpgp] certref > file

Read the certificate for key certref and store it in file. With option --openpgp an OpenPGP keyblock wrapped in a dedicated CMS content type (OID=1.3.6.1.4.1.11591.2.3.1) is expected and extracted to file. Note that for current OpenPGP cards a certificate may only be available at the certref "OPENPGP.3". πŸŽ€

πŸ”„ RESET

RESET

Send a reset to the card daemon. πŸŒ€

πŸ’¬ SALUTATION / SALUT

SALUTATION [--clear]

Change the salutation info for the card. This info can be used by applications for a personalized greeting. The option --clear removes this data object. GnuPG does not use this info. 🌸

🚨 UIF

UIF N [on|off|permanent]

Change the User Interaction Flag. That flag tells whether the confirmation button of a token shall be used. N must be in the range 1 to 3. "permanent" is the same as "on" but the flag can't be changed anymore. πŸ’₯

πŸ”“ UNBLOCK

UNBLOCK

Unblock a PIN using a PUK or Reset Code. Note that OpenPGP cards prior to version 2 can't use this; instead PASSWD can be used to set a new PIN. 🫢

πŸ”— URL

URL [--clear]

Set the URL data object of an OpenPGP card. That data object can be used by gpg's --fetch command to retrieve the full public key. The option --clear deletes the content of that data object. πŸ¦‹

βœ… VERIFY

VERIFY [chvid]

Verify the PIN identified by chvid or the default PIN. ⭐

πŸ“ WRITECERT

WRITECERT certref < file
WRITECERT --openpgp certref [< file|fpr]
WRITECERT --clear certref

Write a certificate to the card under the id certref. The option --clear removes the certificate from the card. The option --openpgp expects an OpenPGP keyblock and stores it encapsulated in a CMS container; the keyblock is taken from file or directly from the OpenPGP key identified by fingerprint fpr. πŸ’Œ

πŸ”‘ WRITEKEY

WRITEKEY [--force] keyref keygrip

Write a private key object identified by keygrip to the card under the id keyref. Option --force allows overwriting an existing key. πŸ—οΈ

πŸ” CHECKKEYS

CHECKKEYS [--ondisk] [--delete-clear-copy] [--delete-protected-copy]

Print a list of keys noticed on all inserted cards. With --ondisk only smartcard keys with a copy on disk are listed. With --delete-clear-copy copies of smartcard keys stored on disk without any protection will be deleted. With --delete-protected-copy password protected copies of smartcard keys stored on disk will be deleted.

This command creates missing shadow keys. The delete options print the status of the keys before they are deleted.

The format of the output is:

  • Serial number β€” A hex-string with the serial number of the card.
  • Type β€” This gives the type of the card's application. For example "OpenPGP" or "PIV".
  • Keygrip β€” A hex-string identifying a key.
  • Keyref β€” The application slot where the key is stored on the card. For example "OpenPGP.1".
  • Status β€” The status of the key. The most common value is "shadowed" for a key where only the public key along with the card's serial number is stored on the disk. The value "clear" indicates that a copy of the card's key is stored unprotected on disk. The value "protected" indicates that a copy of the card's key is stored on disk but is protected by a password. The value "error" may also be shown if there was a problem reading information from the card.

🧸 YUBIKEY

YUBIKEY cmd args

Various commands pertaining to Yubikey tokens, with cmd being:

  • LIST β€” List supported and enabled Yubikey applications.
  • ENABLE usb|nfc|all [otp|u2f|opgp|piv|oath|fido2|all] β€” Enable the specified or all applications on the given interface.
  • DISABLE β€” Disable the specified or all applications on the given interface.

🌸 NOTES (OPENPGP) 🌸

The support for OpenPGP cards in gpg-card is not yet complete. For missing features, please continue to use gpg --card-edit. 🫢

πŸ¦‹ NOTES (PIV) πŸ¦‹

GnuPG has support for PIV cards ("Personal Identity Verification" as specified by NIST Special Publication 800-73-4). This section describes how to initialize (personalize) a fresh Yubikey token featuring the PIV application (requires Yubikey-5). We assume that the credentials have not yet been changed and thus are:

  • Authentication key β€” This is a 24 byte key described by the hex string 010203040506070801020304050607080102030405060708.
  • PIV Application PIN β€” This is the string 123456.
  • PIN Unblocking Key β€” This is the string 12345678.

See the example section on how to change these defaults. For production use it is important to use secure values for them. Note that the Authentication Key is not queried via the usual Pinentry dialog but needs to be entered manually or read from a file. The use of a dedicated machine to personalize tokens is strongly suggested. πŸ’–

So to actually see what's on the card, you just hit it with the list command. In the following we're gonna be in interactive mode (that gpg/card> string is the prompt, iykyk). A fresh card's output is giving:

gpg/card> list
Reader ...........: 1050:0407:X:0
Card type ........: yubikey
Card firmware ....: 5.1.2
Serial number ....: D2760001240102010006090746250000
Application type .: OpenPGP
Version ..........: 2.1
[...]

See that Application type line? That's GnuPG telling you it picked the OpenPGP application of the Yubikey β€” because GnuPG gives the OpenPGP application the highest priority, periodt. So if you wanna use the PIV application on your Yubikey, you've got a few methods, bestie:

Method one ✨ β€” on a Yubikey 5 or later you can just disable the OpenPGP application on the key itself:

gpg/card> yubikey disable all opgp
gpg/card> yubikey list
Application  USB    NFC
-----------------------
OTP          yes    yes
U2F          yes    yes
OPGP         no     no
PIV          yes    no
OATH         yes    yes
FIDO2        yes    yes
gpg/card> reset

That reset is not optional, bestie β€” it's required so the GnuPG system rereads the card. And lowkey the best part: disabled applications keep all their data and can be re-enabled at any time (just use help yubikey).

Method two πŸŽ€ β€” works on literally every Yubikey version: turn off OpenPGP card support inside scdaemon. Add this line

disable-application openpgp

to ~/.gnupg/scdaemon.conf and restart scdaemon β€” either by killing the process or by using gpgconf --kill scdaemon.

Method three πŸ¦‹ β€” change the default order in which scdaemon tries card applications. For example, to prefer PIV over OpenPGP you literally just add

application-priority piv

to ~/.gnupg/scdaemon.conf and restart scdaemon. Heads up: this only affects tokens that support both PIV and OpenPGP β€” it doesn't hamper your OpenPGP-only tokens at all. 🫢


Once you've done one of these, list in gpg-card shows you this:

gpg/card> list
Reader ...........: 1050:0407:X:0
Card type ........: yubikey
Card firmware ....: 5.1.2
Serial number ....: FF020001008A77C1
Application type .: PIV
Version ..........: 1.0
Displayed s/n ....: yk-9074625
PIN usage policy .: app-pin
PIN retry counter : - 3 -
PIV authentication: [none]
      keyref .....: PIV.9A
Card authenticat. : [none]
      keyref .....: PIV.9E
Digital signature : [none]
      keyref .....: PIV.9C
Key management ...: [none]
      keyref .....: PIV.9D

If you've got several tokens plugged into the computer, gpg-card will show you only one of them. To see a different token, hand the number of the token (0, 1, 2, ...) to the list command as an argument. And the command list --cards prints a list of all the inserted tokens. πŸ’…

Okay so quick note: that Displayed s/n is printed on the token itself and it's also shown in Pinentry prompts asking for the PIN β€” so you can actually match up which key it's yelling about. The four standard key slots are always shown, and if other key slots are initialized they get shown too.

Here's the tea on the four standard slots:

  • PIV authentication key (internal reference PIV.9A) β€” used to authenticate the card and the card holder. Using the associated private key is protected by the Application PIN, which needs to be provided once, and then the key can be used until the card is reset or removed from the reader or USB port. GnuPG uses this key with its Secure Shell support.
  • Card authentication key (PIV.9E) β€” also known as the CAK, used to support physical access applications. Its private key is not protected by a PIN and can thus immediately be used. 😳
  • Digital signature key (PIV.9C) β€” used to digitally sign documents. The associated private key is protected by the Application PIN, which needs to be provided for each signing operation.
  • Key management key (PIV.9D) β€” used for encryption. Its private key is protected by the Application PIN, which needs to be provided only once, so decryption operations can then happen until the card is reset or removed from the reader or USB port.

So now we generate three of the four keys. Note that GnuPG does currently not use the Card authentication key β€” but that key is mandatory by the PIV standard, so we create it too. πŸ’€ Key generation requires that we authenticate to the card. You can do that either on the command line (which, fair warning, would reveal the key):

gpg/card> auth 010203040506070801020304050607080102030405060708

or by reading the key from a file. That file needs to consist of one LF-terminated line with the hex-encoded key (as above):

gpg/card> auth < myauth.key

As usual, help auth gives you help for this command. An error message gets printed if a non-matching key is used. The authentication stays valid until a reset of the card or until the card is removed from the reader or the USB port. And ngl, one gotcha: in non-interactive mode the < needs to be quoted so the shell doesn't interpret it as its own redirection symbol. πŸ™ˆ

Here are the actual commands to generate the keys:

gpg/card> generate --algo=nistp384 PIV.9A
PIV card no. yk-9074625 detected
gpg/card> generate --algo=nistp256 PIV.9E
PIV card no. yk-9074625 detected
gpg/card> generate --algo=rsa2048 PIV.9C
PIV card no. yk-9074625 detected

If a key has already been created for one of the slots, an error gets printed β€” to create a new key anyway you can use the --force option. And listen: only the private and public keys have been created, but no certificates are stored in the key slots. In fact, GnuPG uses its own non-standard method to store just the public key in place of the certificate. So other applications won't be able to make use of these keys until gpgsm or another tool has been used to create and store the respective certificates. πŸ‘‘

Let's see what list shows now:

gpg/card> list
Reader ...........: 1050:0407:X:0
Card type ........: yubikey
Card firmware ....: 5.1.2
Serial number ....: FF020001008A77C1
Application type .: PIV
Version ..........: 1.0
Displayed s/n ....: yk-9074625
PIN usage policy .: app-pin
PIN retry counter : - 3 -
PIV authentication: 213D1825FDE0F8240CB4E4229F01AF90AC658C2E
      keyref .....: PIV.9A  (auth)
      algorithm ..: nistp384
Card authenticat. : 7A53E6CFFE7220A0E646B4632EE29E5A7104499C
      keyref .....: PIV.9E  (auth)
      algorithm ..: nistp256
Digital signature : 32A6C6FAFCB8421878608AAB452D5470DD3223ED
      keyref .....: PIV.9C  (sign,cert)
      algorithm ..: rsa2048
Key management ...: [none]
      keyref .....: PIV.9D

The primary info for each key is the keygrip β€” a 40-byte hex-string identifying the key. It's a unique identifier for the specific parameters of a key, and it's what gpg-agent and other parts of GnuPG use to associate a private key with its protocol-specific certificate format (X.509, OpenPGP, or SecureShell). Below the keygrip you get the key reference along with the key usage capabilities. And finally the algorithm is printed in the format used by {gpg}. At this point no other info is shown, because for these new keys gpg won't be able to find matching certificates. 🧚


Okay so we could have created the Key management key with the generate command too, but instead we're gonna create that key off-card so that a backup exists. To do that, a key needs to be created with either gpg or gpgsm, or imported in one of these tools. In our example we create a self-signed X.509 certificate (exit the gpg-card tool first):

$ gpgsm --gen-key -o encr.crt
   (1) RSA
   (2) Existing key
   (3) Existing key from card
Your selection? 1
What keysize do you want? (3072) 2048
Requested keysize is 2048 bits
Possible actions for a RSA key:
   (1) sign, encrypt
   (2) sign
   (3) encrypt
Your selection? 3
Enter the X.509 subject name: CN=Encryption key for yk-9074625,O=example,C=DE
Enter email addresses (end with an empty line):
> otto@example.net
>
Enter DNS names (optional; end with an empty line):
>
Enter URIs (optional; end with an empty line):
>
Create self-signed certificate? (y/N) y
These parameters are used:
    Key-Type: RSA
    Key-Length: 2048
    Key-Usage: encrypt
    Serial: random
    Name-DN: CN=Encryption key for yk-9074625,O=example,C=DE
    Name-Email: otto@example.net

Proceed with creation? (y/N)
Now creating self-signed certificate.  This may take a while ...
gpgsm: about to sign the certificate for key: &34798AAFE0A7565088101CC4AE31C5C8C74461CB
gpgsm: certificate created
Ready.
$ gpgsm --import encr.crt
gpgsm: certificate imported
gpgsm: total number processed: 1
gpgsm:               imported: 1

Note that last step, which imported the created certificate. And btw, if you instead created a certificate signing request (CSR) instead of a self-signed certificate and sent it off to a CA, you'd do the exact same import step with the certificate you received from the CA. 🌈

Take note of the keygrip (prefixed with an ampersand) as shown during the certificate creation β€” or list it again using gpgsm --with-keygrip -k otto@example.net. Now to move the key and certificate to the card, start gpg-card again and enter:

gpg/card> writekey PIV.9D 34798AAFE0A7565088101CC4AE31C5C8C74461CB
gpg/card> writecert PIV.9D < encr.crt

If you entered a passphrase to protect the private key, you'll be asked for it via the Pinentry prompt. On success the key and the certificate have been written to the card, and list shows:

[...]
Key management ...: 34798AAFE0A7565088101CC4AE31C5C8C74461CB
      keyref .....: PIV.9D  (encr)
      algorithm ..: rsa2048
      used for ...: X.509
        user id ..: CN=Encryption key for yk-9074625,O=example,C=DE
        user id ..: <otto@example.net>

In case the same key (identified by the keygrip) has been used for several certificates, you'll see several used for parts. With this, the encryption key is now fully functional and can be used to decrypt messages encrypted to this certificate. πŸŽ‰

Take care, bestie: the original key is still stored on-disk and should be moved to a backup medium. You do that by simply copying the file 34798AAFE0A7565088101CC4AE31C5C8C74461CB.key from the directory ~/.gnupg/private-keys-v1.d/ to the backup medium and deleting the file at its original place. Don't skip this one fr fr. 😭

Last example time, bestie: we’re making a self-signed certificate for digital signatures. Bounce out of gpg-card with quit or Ctrl+D, then grab gpgsm:

$ gpgsm --learn
$ gpgsm --gen-key -o sign.crt
Please select what kind of key you want:
   (1) RSA
   (2) Existing key
   (3) Existing key from card
Your selection? 3
Serial number of the card: FF020001008A77C1
Available keys:
   (1) 213D1825FDE0F8240CB4E4229F01AF90AC658C2E PIV.9A nistp384
   (2) 7A53E6CFFE7220A0E646B4632EE29E5A7104499C PIV.9E nistp256
   (3) 32A6C6FAFCB8421878608AAB452D5470DD3223ED PIV.9C rsa2048
   (4) 34798AAFE0A7565088101CC4AE31C5C8C74461CB PIV.9D rsa2048
Your selection? 3
Possible actions for a RSA key:
   (1) sign, encrypt
   (2) sign
   (3) encrypt
Your selection? 2
Enter the X.509 subject name: CN=Signing key for yk-9074625,O=example,C=DE
Enter email addresses (end with an empty line):
> otto@example.net
>
Enter DNS names (optional; end with an empty line):
>
Enter URIs (optional; end with an empty line):
>
Create self-signed certificate? (y/N)
These parameters are used:
    Key-Type: card:PIV.9C
    Key-Length: 1024
    Key-Usage: sign
    Serial: random
    Name-DN: CN=Signing key for yk-9074625,O=example,C=DE
    Name-Email: otto@example.net

Proceed with creation? (y/N) y
Now creating self-signed certificate.  This may take a while ...
gpgsm: about to sign the certificate for key: &32A6C6FAFCB8421878608AAB452D5470DD3223ED
gpgsm: certificate created
Ready.
$ gpgsm --import sign.crt
gpgsm: certificate imported
gpgsm: total number processed: 1
gpgsm:               imported: 1

gpgsm --learn is lowkey necessary right now so gpg-agent knows which keys are actually available on the card. The need for this command will eventually be removed. The rest of the commands are similar to creating an on-disk key, except here we select the Digital signature key. During the creation process you’ll be asked for the Application PIN of the card. The final step is to write the certificate to the card using gpg-card:

gpg/card> writecert PIV.9C < sign.crt

Run list again and you’ll see the fully initialized card, no cap:

Reader ...........: 1050:0407:X:0
Card type ........: yubikey
Card firmware ....: 5.1.2
Serial number ....: FF020001008A77C1
Application type .: PIV
Version ..........: 1.0
Displayed s/n ....: yk-9074625
PIN usage policy .: app-pin
PIN retry counter : - [verified] -
PIV authentication: 213D1825FDE0F8240CB4E4229F01AF90AC658C2E
      keyref .....: PIV.9A  (auth)
      algorithm ..: nistp384
Card authenticat. : 7A53E6CFFE7220A0E646B4632EE29E5A7104499C
      keyref .....: PIV.9E  (auth)
      algorithm ..: nistp256
Digital signature : 32A6C6FAFCB8421878608AAB452D5470DD3223ED
      keyref .....: PIV.9C  (sign,cert)
      algorithm ..: rsa2048
      used for ...: X.509
        user id ..: CN=Signing key for yk-9074625,O=example,C=DE
        user id ..: <otto@example.net>
Key management ...: 34798AAFE0A7565088101CC4AE31C5C8C74461CB
      keyref .....: PIV.9D  (encr)
      algorithm ..: rsa2048
      used for ...: X.509
        user id ..: CN=Encryption key for yk-9074625,O=example,C=DE
        user id ..: <otto@example.net>

Now you can sign and encrypt with this card using gpgsm, and you can use the PIV authentication key with ssh:

$ ssh-add -l
384 SHA256:0qnJ0Y0ehWxKcx2frLfEljf6GCdlO55OZed5HqGHsaU cardno:yk-9074625 (ECDSA)

As usual, use ssh-add with the uppercase -L to list the public ssh key. To use the certificates with Thunderbird or Mozilla, please consult the Scute manual for details.

If you want to use the same PIV keys for OpenPGP too β€” for example on a Yubikey, so you don’t have to switch between OpenPGP and PIV β€” that’s also possible:

$ gpgsm --learn
$ gpg --full-gen-key
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 14
Serial number of the card: FF020001008A77C1
Available keys:
   (1) 213D1825FDE0F8240CB4E4229F01AF90AC658C2E PIV.9A nistp384 (auth)
   (2) 7A53E6CFFE7220A0E646B4632EE29E5A7104499C PIV.9E nistp256 (auth)
   (3) 32A6C6FAFCB8421878608AAB452D5470DD3223ED PIV.9C rsa2048 (cert,sign)
   (4) 34798AAFE0A7565088101CC4AE31C5C8C74461CB PIV.9D rsa2048 (encr)
Your selection? 3
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name:
Email address: otto@example.net
Comment:
You selected this USER-ID:
    "otto@example.net"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
gpg: key C3AFA9ED971BB365 marked as ultimately trusted
gpg: revocation certificate stored as '[...]D971BB365.rev'
public and secret key created and signed.

Note that this key cannot be used for encryption.  You may want to use
the command "--edit-key" to generate a subkey for this purpose.
pub   rsa2048 2019-04-04 [SC]
      7F899AE2FB73159DD68A1B20C3AFA9ED971BB365
uid                      otto@example.net

Heads up: you’ll be asked two times to enter the PIN of your PIV card. If you run gpg in --expert mode you’ll also get the option to change the key’s usage flags. The next typescript shows how to add the encryption subkey:

$ gpg --edit-key 7F899AE2FB73159DD68A1B20C3AFA9ED971BB365
Secret key is available.

sec  rsa2048/C3AFA9ED971BB365
     created: 2019-04-04  expires: never       usage: SC
     card-no: FF020001008A77C1
     trust: ultimate      validity: ultimate
[ultimate] (1). otto@example.net
gpg> addkey
Secret parts of primary key are stored on-card.
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
  (14) Existing key from card
Your selection? 14
Serial number of the card: FF020001008A77C1
Available keys:
   (1) 213D1825FDE0F8240CB4E4229F01AF90AC658C2E PIV.9A nistp384 (auth)
   (2) 7A53E6CFFE7220A0E646B4632EE29E5A7104499C PIV.9E nistp256 (auth)
   (3) 32A6C6FAFCB8421878608AAB452D5470DD3223ED PIV.9C rsa2048 (cert,sign)
   (4) 34798AAFE0A7565088101CC4AE31C5C8C74461CB PIV.9D rsa2048 (encr)
Your selection? 4
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y

sec  rsa2048/C3AFA9ED971BB365
     created: 2019-04-04  expires: never       usage: SC
     card-no: FF020001008A77C1
     trust: ultimate      validity: ultimate
ssb  rsa2048/7067860A98FCE6E1
     created: 2019-04-04  expires: never       usage: E
     card-no: FF020001008A77C1
[ultimate] (1). otto@example.net

gpg> save

Now you can use your PIV card with gpg too, bestie. Iconic.


✨ OPTIONS ✨

gpg-card understands these options, and yes, we’re going through every single one:

  • --with-colons β€” Currently this option has no effect. It’s just vibing.
  • --status-fd n β€” Writes special status strings to the file descriptor n. This program returns only the status messages SUCCESS or FAILURE, which are helpful when the caller uses a double fork approach and can’t easily get the return code of the process.
  • --verbose β€” Enables extra informational output. More tea β˜•.
  • --quiet β€” Disables almost all informational output. Shhh 🀫.
  • --version β€” Prints the version of the program and exits.
  • --help β€” Displays a brief help page and exits.
  • --no-autostart β€” Do not start gpg-agent if it has not yet been started and its service is required. This option is mostly useful on machines where the connection to gpg-agent has been redirected to another machine.
  • --no-history β€” In interactive mode, the command line history is usually saved to and restored from a file below the GnuPG home directory. This option inhibits the use of that file.
  • --agent-program file β€” Specifies the agent program to be started if none is running. The default value is determined by running gpgconf with the option --list-dirs.
  • --gpg-program file β€” Specifies a non-default gpg binary to be used by certain commands.
  • --gpgsm-program file β€” Specifies a non-default gpgsm binary to be used by certain commands.
  • --chuid uid β€” Changes the current user to uid, which may be either a number or a name. This can be used from the root account to run gpg-card for another user. If uid is not the current UID, a standard PATH is set and the envvar GNUPGHOME is unset. To override the latter, the option --homedir can be used. This option has only an effect when used on the command line. This option currently has no effect at all on Windows.

πŸ¦‹ SEE ALSO πŸ¦‹

  • scdaemon(1) β€” go peek at that one too, bestie 🫢

Final vibe check: this page is from GnuPG 2.4.9, dated 2025-02-19, and it’s manual page GPG-CARD(1). Bye bestie β€” go make that card slay πŸ’–βœ¨

πŸ“¦ where this page comes from