OpenPGP keys on a smartcard, YubiKey or Nitrokey with GnuPG

Updated November 2026

An OpenPGP card keeps your secret keys inside a small chip that never lets them out. Your computer sends data in, the card signs or decrypts it, and malware on the computer cannot copy the key. The safe setup is: keep the primary key offline as a backup, and put three subkeys (sign, encrypt, authenticate) on the card for daily use.

What an OpenPGP card is

“OpenPGP card” is a smartcard specification that GnuPG supports directly. A card has three key slots: Signature, Encryption and Authentication. The same specification is built into USB tokens:

Every card has two PINs. The user PIN (default 123456) unlocks signing and decryption. The Admin PIN (default 12345678) is needed to change settings and load keys. Both YubiKey and Nitrokey documentation give these defaults. Nitrokey’s documentation says a PIN is blocked after three wrong attempts. An optional Reset Code can unblock the user PIN without the Admin PIN.

Primary key [SC] offline backup only Subkey [S] Subkey [E] Subkey [A] OpenPGP card 1 Signature 2 Encryption 3 Authentication
Subkeys go to the card’s three slots; the primary key is kept offline for certifying, renewing and revoking.

Before you start

Check the card and change the PINs

gpg --card-status

This prints the card’s serial number, Key attributes, PIN retry counter (remaining tries for the user PIN, Reset Code and Admin PIN) and which slots hold keys. Change both PINs straight away:

gpg --card-edit
gpg/card> admin
Admin commands are allowed
gpg/card> passwd
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Choose 3 first (Admin PIN), then 1 (user PIN). Yubico’s ykman documentation gives a minimum of 6 characters for the user PIN and 8 for the Admin PIN. Write the Admin PIN down and keep it with your key backup.

Set the key type on the card

Many cards are set to RSA 2048 by default. If your subkeys are ed25519/cv25519, change the slot type first, still in admin mode:

gpg/card> key-attr

GnuPG asks for each slot (“Changing card key attribute for: Signature key”), offers (1) RSA and (2) ECC, and for ECC lets you choose “Curve 25519”. Use the same type as the subkey you will load. Then type quit.

Move the subkeys to the card

gpg --edit-key FPR
gpg> key 1
gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2
gpg> key 1
gpg> key 2
gpg> keytocard
   (1) Signature key
Your selection? 1
gpg> key 2
gpg> key 3
gpg> keytocard
   (3) Authentication key
Your selection? 3
gpg> save

key N toggles the selection of subkey number N in the order they are listed; a * marks the selected one. Select exactly one subkey before each keytocard. If no subkey is selected, GnuPG offers to move the primary key and asks “Really move the primary key? (y/N)”; answer no for this setup. GnuPG asks for your key passphrase and the Admin PIN. Nothing changes on disk until you type save: then the local secret subkeys are replaced by stubs that point to the card.

Check that it worked

gpg -K FPR

In the listing, ssb> means the subkey is on a smartcard, and a Card serial no. line shows which card. sec# means the primary secret key is not available on this machine. To keep the primary key only in your offline backup, first confirm the backup restores, then remove the primary key’s file from this computer. gpg -K --with-keygrip FPR prints a Keygrip under each key; GnuPG stores each secret key as ~/.gnupg/private-keys-v1.d/KEYGRIP.key. Delete only the file whose keygrip belongs to the sec line, and gpg -K then shows sec#. Whenever you need the primary key (to extend the expiry, add subkeys or certify other keys), restore the backup on an offline machine or temporarily. If unsure, leave the primary key on disk with a strong passphrase; the card already protects the daily-use subkeys.

Test it: echo test | gpg --armor --sign should ask for the card PIN, not for your passphrase.

Generate keys on the card instead

You can also let the card create the keys (gpg --card-edit, admin, generate). The secret keys then never exist outside the card, but you also cannot back them up. GnuPG asks “Make off-card backup of encryption key? (Y/n)”; the GnuPG Card HOWTO recommends yes, because without it everything encrypted to the card is lost if the card breaks. Signing and authentication keys made on the card cannot be backed up at all; if the card is lost you revoke them and make new ones.

YubiKey extras: touch policy

A YubiKey can require you to touch its contact for every operation, so malware cannot quietly use the key while the token is plugged in:

ykman openpgp info
ykman openpgp keys set-touch sig on
ykman openpgp keys set-touch enc on
ykman openpgp keys set-touch aut on

The policies are on, off (the default), fixed (cannot be turned off without deleting the key), cached (touch once, valid 15 seconds) and cached-fixed. ykman openpgp reset wipes all OpenPGP data and sets the PINs back to their defaults.

Use the card for SSH

gpg-agent can act as your SSH agent and use the authentication subkey on the card.

  1. Turn on SSH support:
    echo enable-ssh-support >> ~/.gnupg/gpg-agent.conf
    gpgconf --kill gpg-agent
  2. Point SSH at gpg-agent. The gpg-agent manual gives this snippet for ~/.bashrc:
    export GPG_TTY=$(tty)
    unset SSH_AGENT_PID
    if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
      export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
    fi
  3. Get your SSH public key and add it to ~/.ssh/authorized_keys on the servers:
    gpg --export-ssh-key FPR
    The output is one line such as ssh-ed25519 AAAAC3Nz… openpgp:0xBD33A6A9. It comes from the latest valid subkey with authentication capability.
  4. Test with ssh-add -L (it should list that key) and log in. Keys on an OpenPGP card are offered automatically; you do not need to list them in sshcontrol.

If the PIN prompt appears on the wrong terminal or not at all, run gpg-connect-agent updatestartuptty /bye. On Windows, the option for the built-in OpenSSH is enable-win32-openssh-support, and for PuTTY enable-putty-support.

When things go wrong

“No SmartCard daemon” or “OpenPGP card not available”
Install scdaemon, re-plug the token, and run gpgconf --kill all. Some cards show another application first; in gpg --card-edit the openpgp command switches to the OpenPGP application.
User PIN blocked
Use passwd → 2 - unblock PIN with the Admin PIN, or the unblock command with a Reset Code.
Admin PIN blocked or card lost
You cannot recover keys from the card. Reset the card (for example ykman openpgp reset, or factory-reset in admin mode), restore your subkeys from the backup and load them again, or revoke the subkeys and create new ones.
“Secret key not available” on a second computer
The second computer needs the public key and the stubs. Import your public key there and run gpg --card-status with the card inserted; GnuPG links the card keys to it. The fetch command in --card-edit downloads the public key from the URL stored on the card (set it with url).

Sources