- Strong 2FA - hardware authenticator
- Strong MFA - hardware authenticator and PIN or Biometric
- Passwordless - hardware authenticator and PIN without passwords (FIDO2/WebAuthn/passkey)
- UTF
- FIDO
- FIDO2
- Smart Card (PIV)
- OpenPGP
- OTP
- OATH-TOTP
- OATH_HOTP
- USB-A, USB-C, NFC, Lightning communication
- IP68
- Non-upgradable firmware
The firmware of a YubiKey can not be changed (it’s read-only). This means that when new features become available, you would need to purchase that latest version of YubiKey. Also be aware of the firmware version when purchasing.
| Firmware | FIDO2 | FIDO U2F | PIV | OATH-TOTP | OTP | OPENPGP |
| 5.7 | 100 | unlimited | 4 | 64 | 2 credentials, unlimited services | 3 subkeys [S E A] |
| 5.0 - 5.6 | 25 | unlimited | 4 | 32 | 2 credentials, unlimited services | 3 subkeys [S E A] |
There are many different YubIkey types and versions available. Check the YubiKey devices webpage for further specifications.
The YubiKey 5 offers several security applications. Each application is managed individually, and therefor multiple PIN codes needs to be set. In total, the YubiKey 5 has 5 PIN codes, 1 PUK admin code, and 1 Reset code.
| Interface | PINs | Description |
|---|---|---|
| FIDO2 | 1 PIN | Authenticate to services without a password. |
| No default Pin | ||
| The PIN is set during the first time link to service | ||
| GPG | 1 User PIN | Encrypting, decrypting, signing, and SSH |
| 1 Unlock PIN | Defaults | |
| 1 Admin PIN | User Pin : 123456 | |
| Admin Pin : 12345678 | ||
| PIV | 2 PINs | x509 certificates / keypairs. Bitlocker, Veracrypt, SSH, etc |
| 1 Management | Defaults | |
| User Pin : 123456 | ||
| Admin Pin : 12345678 |
Install the yubikey-manager software:
sudo pacman -S yubikey-manager
sudo systemctl enable pcscd.service
sudo systemctl start pcscd.serviceWithe the software installed, plug in the YubiKey and check the type and firmware to understand the capabilities:
ykman info
# Device type: YubiKey 5 NFC
# Serial number: XXXXXXXX
# Firmware version: 5.4.3
# Form factor: Keychain (USB-A)
# Enabled USB interfaces: OTP, FIDO, CCID
# NFC transport is enabled
# Applications USB NFC
# Yubico OTP Enabled Enabled
# FIDO U2F Enabled Enabled
# FIDO2 Enabled Enabled
# OATH Enabled Enabled
# PIV Enabled Enabled
# OpenPGP Enabled Enabled
# YubiHSM Auth Enabled EnabledA YubiKey has different applications (modes) that can be enabled / disabled / configured and reset individually.
The yubikey-manager python library is used to configure all aspects of the YubiKey. It contains sections to configure the application:
| info | show general information |
| list | list connected YubiKeys |
| script | run a python script |
| config | configure the YubiKey, enable or disable applications |
| fido | manage the FIDO applications |
| hsmauth | manage the YubiHSM Auth application |
| oath | manage the OATH application |
| openpgp | manage the OpenPGP application |
| otp | manage the YubiOTP application |
| piv | manage the PIV application |
The following notes provide sample scripts to configure a 5-Series YubiKey.
There is one PIN that rules them all. The YubiKey has a master config application that allows enabling or disabling each individual application on the YubiKey. When an application is disabled, its configuration and secrets cannot be accessed or changed — or wiped. This is particularly important to take note of, since otherwise wiping an application’s config and secrets (aka a “factory reset”) does not require the application’s own PIN or passphrase.
The YubiKey provides a 128-bit lock code to protect changes to this master config app. By default, YubiKey comes with no lock code set. However, in order to prevent an adversary who gains access to a computer while a YubiKey is plugged in from being able to lock you out of all your YubiKey secrets, a master lock code should be set.
The lock-code is a string of 32 hex digits. Run the following command to set the lock code for the YubiKey to a new random number:
ykman config set-lock-code --generate
# Using a randomly generated lock code: dac67aece839402edca8272528e837a6
# Lock configuration with this lock code? [y/N]:
yThe lock-code is required every time an application is enabled / disabled.
It is not possible to factory reset the entire YubiKey with a single command.
Instead each application provides an individual reset function, that only wipes the setting / keys / etc of that application. You require the application’s admin PIN to reset the application.
ykman -f openpgp reset # wipes all OpenPGP data, and sets all PINs to their default values
ykman -f fido reset # wipes all FIDO, FIDO U2F credentials and removes the PIN code
ykman -f oath reset # wipes all accounts and restores factory settings
ykman -f piv reset # wipes all data and restores factory settings for the PIV applicationThe enable OpenPGP mode on YubiKey execute the following commands:
ykman config usb -f -e OPENPGPKey Derived Function enables YubiKey to store the hash of a PIN rather than the PIN itself, preventing the PIN to be transfered in plan text.
NOTE: KDF must be enabled BEFORE changing the PINs or moving sub-keys to YubiKey.
gpg --card-edit
gpg/card> admin
# Admin commands are allowed
gpg/card> kdf-setup
# Enabling KDF ensures PIN is not stored on the YubiKey, only its hash. It needs to be done before changing PIN. More.The OpenPGP app has 3 PINs:
- User PIN,
- Reset PIN (aka PUK, PIN Unblock Key),
- Admin PIN.
The user PIN is used for day-to-day access to OpenPGP private keys. The reset PIN is not necessary as it can be controlled by the admin PIN. The admin PIN is used to change the settings of the OpenPGP app itself (and to unblock or change the user PIN if is forgotten or entered incorrectly too many times). When prompted to enter a “PIN” with no “admin” qualifier, this usually means to enter the user PIN, not the admin PIN.
gpg --edit-card
gpg/card> admin
gpg/card> passwd
# gpg: OpenPGP card no. ABCDE123456789000006123456780000 detected
# 1 - change PIN
# 2 - unblock PIN
# 3 - change Admin PIN
# 4 - set the Reset Code
# Q - quit
# Your selection?
1Enter 1 at the prompt for the passwd command, and enter 123456 at the first PIN prompt (the default user PIN is 123456). Next, enter the new user PIN (prompted twice). Do not use a number — instead use a simple passphrase (like “horse apple garden”) that’s at least 6 characters long and easy to type (required several times a day). Make sure it’s different than any other PIN or passphrase ever used before.
Your selection? 1
# PIN changed.
# 1 - change PIN
# 2 - unblock PIN
# 3 - change Admin PIN
# 4 - set the Reset Code
# Q - quit
# Your selection?Next, enter 3 to set the admin PIN, and enter 12345678 at the first PIN prompt (the default admin PIN is 12345678). Next, enter the new admin PIN (prompted twice). Like with the user PIN above, do not use a number — instead use a simple passphrase at least 8 characters long. It doesn’t need to be any stronger than the user PIN, just different (enough so that an adversary wouldn’t be able to guess the admin PIN if she finds out your user PIN).
Your selection? 3
# PIN changed.
# 1 - change PIN
# 2 - unblock PIN
# 3 - change Admin PIN
# 4 - set the Reset Code
# Q - quit
Your selection? qBackup the PIN codes (see Backup PINS)
Assuming you have generated the necessary GPG key-chain using the gpg-provision.py script, the gpg key-chain is stored in the /tmp/gpg_xxxxx folder.
To instruct the GnuPG utility where the gpg-keychain is stored, execute the following pointing to the correct folder:
export GNUPGHOME=/tmp/gpg_xxxxxFrom here use the GnuPG utility to edit the key, select the key, and send to card:
[user@archlinux ~]$ gpg --edit-key user
# Secret key is available.
# sec ed25519/0xC8A9786CD87AEECB
# created: 2024-06-30 expires: never usage: C
# trust: ultimate validity: ultimate
# ssb ed25519/0xF11A65E1A88F0237
# created: 2024-06-30 expires: never usage: S
# ssb cv25519/0xA8B11410DB58AC7A
# created: 2024-06-30 expires: never usage: E
# ssb ed25519/0x952E563E4CEB347B
# created: 2024-06-30 expires: never usage: A
# [ultimate] (1). user <user@email.com>
gpg> key 1
# sec ed25519/0xC8A9786CD87AEECB
# created: 2024-06-30 expires: never usage: C
# trust: ultimate validity: ultimate
# ssb* ed25519/0xF11A65E1A88F0237
# created: 2024-06-30 expires: never usage: S
# ssb cv25519/0xA8B11410DB58AC7A
# created: 2024-06-30 expires: never usage: E
# ssb ed25519/0x952E563E4CEB347B
# created: 2024-06-30 expires: never usage: A
# [ultimate] (1). user <user@email.com>
gpg> keytocard
# Please select where to store the key:
# (1) Signature key
# (3) Authentication key
Your selection? 1
# sec ed25519/0xC8A9786CD87AEECB
# created: 2024-06-30 expires: never usage: C
# trust: ultimate validity: ultimate
# ssb* ed25519/0xF11A65E1A88F0237
# created: 2024-06-30 expires: never usage: S
# ssb cv25519/0xA8B11410DB58AC7A
# created: 2024-06-30 expires: never usage: E
# ssb ed25519/0x952E563E4CEB347B
# created: 2024-06-30 expires: never usage: A
# [ultimate] (1). user <user@email.com>
# Note: the local copy of the secret key will only be deleted with "save".
gpg> key 1
gpg> key 2
# sec ed25519/0xC8A9786CD87AEECB
# created: 2024-06-30 expires: never usage: C
# trust: ultimate validity: ultimate
# ssb ed25519/0xF11A65E1A88F0237
# created: 2024-06-30 expires: never usage: S
# ssb* cv25519/0xA8B11410DB58AC7A
# created: 2024-06-30 expires: never usage: E
# ssb ed25519/0x952E563E4CEB347B
# created: 2024-06-30 expires: never usage: A
# [ultimate] (1). user <user@email.com>
gpg> keytocard
# Please select where to store the key:
# (2) Encryption key
Your selection? 2
# sec ed25519/0xC8A9786CD87AEECB
# created: 2024-06-30 expires: never usage: C
# trust: ultimate validity: ultimate
# ssb ed25519/0xF11A65E1A88F0237
# created: 2024-06-30 expires: never usage: S
# ssb* cv25519/0xA8B11410DB58AC7A
# created: 2024-06-30 expires: never usage: E
# ssb ed25519/0x952E563E4CEB347B
# created: 2024-06-30 expires: never usage: A
# [ultimate] (1). user <user@email.com>
# Note: the local copy of the secret key will only be deleted with "save".
gpg> key 2
gpg> key 3
# sec ed25519/0xC8A9786CD87AEECB
# created: 2024-06-30 expires: never usage: C
# trust: ultimate validity: ultimate
# ssb ed25519/0xF11A65E1A88F0237
# created: 2024-06-30 expires: never usage: S
# ssb cv25519/0xA8B11410DB58AC7A
# created: 2024-06-30 expires: never usage: E
# ssb* ed25519/0x952E563E4CEB347B
# created: 2024-06-30 expires: never usage: A
# [ultimate] (1). user <user@email.com>
gpg> keytocard
# Please select where to store the key:
# (3) Authentication key
Your selection? 3
# sec ed25519/0xC8A9786CD87AEECB
# created: 2024-06-30 expires: never usage: C
# trust: ultimate validity: ultimate
# ssb ed25519/0xF11A65E1A88F0237
# created: 2024-06-30 expires: never usage: S
# ssb cv25519/0xA8B11410DB58AC7A
# created: 2024-06-30 expires: never usage: E
# ssb* ed25519/0x952E563E4CEB347B
# created: 2024-06-30 expires: never usage: A
# [ultimate] (1). user <user@email.com>
# Note: the local copy of the secret key will only be deleted with "save".
gpg> saveAs an alternative to creating GPG keys with the GnuPG utility, the GPG keys can be created directly on the YubiKey device. This is the safest method of creating GPG keys, as the key never leaves the device itself. Note however, that the YubiKey generated GPG keys can not be backed up. In other words, when the YubiKey is lost or compromised, all access to services is compromised as well.
Use the key-attr command so that when you generate your keys, it will generate Curve 25519 keys instead of RSA keys:
gpg --edit-card
gpg/card> admin
gpg/card> key-attr
# Changing card key attribute for: Signature key
# Please select what kind of key you want:
# (1) RSA
# (2) ECC
# Your selection?Select the ECC option:
Your selection? 2
# Please select which elliptic curve you want:
# (1) Curve 25519
# (4) NIST P-384
# Your selection?Select Curve 25519:
# Your selection? 1
# The card will now be re-configured to generate a key of type: ed25519
# Note: There is no guarantee that the card supports the requested size.
# If the key generation does not succeed, please check the
# documentation of your card to see what sizes are allowed.Enter the admin PIN when prompted to save your changes for that key. Select the same options (ECC and Curve 25519) as the prompts continue for the encryption key and authentication key:
# Changing card key attribute for: Encryption key
# Please select what kind of key you want:
# (1) RSA
# (2) ECC
Your selection? 2
# Please select which elliptic curve you want:
# (1) Curve 25519
# (4) NIST P-384
Your selection? 1
# The card will now be re-configured to generate a key of type: cv25519
# Changing card key attribute for: Authentication key
# Please select what kind of key you want:
# (1) RSA
# (2) ECC
Your selection? 2
# Please select which elliptic curve you want:
# (1) Curve 25519
# (4) NIST P-384
Your selection? 1
# The card will now be re-configured to generate a key of type: ed25519
# gpg/card>Next, generate a new set of OpenPGP keys on the YubiKey, using the generate command:
gpg/card> generate
# Make off-card backup of encryption key? (Y/n)Enter n to ensure that the private keys never leave the YubiKey, and enter the admin PIN when prompted:
Make off-card backup of encryption key? (Y/n) n
# Please note that the factory settings of the PINs are
# PIN = '123456' Admin PIN = '12345678'
# You should change them using the command --change-pin
# 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)Then enter 0 to prevent the keys from expiring:
Key is valid for? (0) 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:When prompted for real name, email address, and comment, use the “real name” field for the display name or alias associated with the OpenPGP key, the “email address” field for the email account associated with the key, and the “comment” field for a word or phrase that will distinguish this key from other keys. For example, I might enter the following for real name, email address, and comment:
Real name: user
Email address: user@email.com
Comment: YubiKey1
#You selected this USER-ID:
"user (YubiKey1) <user@email.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? oEnter the admin PIN, and then the user PIN. The ID of the newly generated master key will be printed:
# gpg: key 0xABCDEF1234567890 marked as ultimately trusted
# gpg: revocation certificate stored as '/home/user/.gnupg/openpgp-revocs.d/1234567890ABCDEF1234567890ABCDEF12345678.rev'
# public and secret key created and signed.
gpg/card>gpg/card> quit
# pub ed25519/0xABCDEF1234567890 2023-01-01 [SC]
# 1234567890ABCDEF1234567890ABCDEF12345678
# uid [ultimate] user (YubiKey1) <user@email.com>
# sub ed25519/0xFEDCBA0987654321 2023-01-01 [A]
# sub cv25519/0x1234567890ABCDEF 2023-01-01 [E]Validate that the sub-keys have been transfered to the YubiKey, which will be the case if the gpg folder has stubs for the sub-keys identified with sbb>.
[user@archlinux ~]$ gpg -K
# /home/user/test/.gnupg/pubring.kbx
# ---------------------------------------
# sec# ed25519/0xC8A9786CD87AEECB 2024-06-30 [C]
# Key fingerprint = F4F0 55D1 4680 AAD7 1456 5D63 C8A9 786C D87A EECB
# uid [ultimate] user <user@email.com>
# ssb> ed25519/0xF11A65E1A88F0237 2024-06-30 [S]
# ssb> cv25519/0xA8B11410DB58AC7A 2024-06-30 [E]
# ssb> ed25519/0x952E563E4CEB347B 2024-06-30 [A][user@archlinux ~]$ gpg --card-status
# Reader ...........: 1050:0407:X:0
# Application ID ...: D2760001240100000006250875120000
# Application type .: OpenPGP
# Version ..........: 3.4
# Manufacturer .....: Yubico
# Serial number ....: XXXXXXXX
# Name of cardholder: [not set]
# Language prefs ...: [not set]
# Salutation .......:
# URL of public key : [not set]
# Login data .......: user
# Signature PIN ....: not forced
# Key attributes ...: ed25519 cv25519 ed25519
# Max. PIN lengths .: 127 127 127
# PIN retry counter : 3 0 3
# Signature counter : 0
# KDF setting ......: single
# UIF setting ......: Sign=off Decrypt=off Auth=off
# Signature key ....: 638B FE47 E2AD 28BA CE3A B114 F11A 65E1 A88F 0237
# created ....: 2024-06-30 21:44:16
# Encryption key....: A4CB 2108 6F42 2142 6485 FA3C A8B1 1410 DB58 AC7A
# created ....: 2024-06-30 21:44:17
# Authentication key: 14A3 3094 4499 4F9F 430D 8927 952E 563E 4CEB 347B
# created ....: 2024-06-30 21:44:17
# General key info..: sub ed25519/0xF11A65E1A88F0237 2024-06-30 user <user@email.com>
# sec# ed25519/0xC8A9786CD87AEECB created: 2024-06-30 expires: never
# ssb> ed25519/0xF11A65E1A88F0237 created: 2024-06-30 expires: never
# card-no: 0006 25087512
# ssb> cv25519/0xA8B11410DB58AC7A created: 2024-06-30 expires: never
# card-no: 0006 25087512
# ssb> ed25519/0x952E563E4CEB347B created: 2024-06-30 expires: never
# card-no: 0006 25087512To test the functionality of encryption and decryption test the YubKey with the pass functionality:
[user@archlinux ~]$ pass generate test 32
# The generated password for test is:
# a=l~65v1d#c"L)O%99_zEotE4YY60Pm=
[user@archlinux ~]$ pass test
# a=l~65v1d#c"L)O%99_zEotE4YY60Pm=Assuming that no existing GPG keys exist on the machine, follow to following steps to setup GnuPG to use an existing (configured) YubiKey on a new computer.
Assuming at some stage you have configured github with your public key for signing your commits, you can use the following command to import your public key from github:
[user@archlinux ~]$ curl https://github.com/user.gpg | gpg --import
# gpg: keybox '/home/user/test/pubring.kbx' created
# % Total % Received % Xferd Average Speed Time Time Time Current
# Dload Upload Total Spent Left Speed
# 100 1273 100 1273 0 0 2295 0 --:--:-- --:--:-- --:--:-- 2301
# gpg: /home/user/test/trustdb.gpg: trustdb created
# gpg: key C8A9786CD87AEECB: public key "user <user@outlook.com>" imported
# gpg: Total number processed: 1
# gpg: imported: 1Once the public key has been imported, the gpg stubs can be created with the following command:
[user@t570 ~]$ gpg --card-status
# Reader ...........: 1050:0407:X:0
# Application ID ...: D2760001240100000006250875120000
# Application type .: OpenPGP
# Version ..........: 3.4
# Manufacturer .....: Yubico
# Serial number ....: XXXXXXXX
# Name of cardholder: [not set]
# Language prefs ...: [not set]
# Salutation .......:
# URL of public key : [not set]
# Login data .......: user
# Signature PIN ....: not forced
# Key attributes ...: ed25519 cv25519 ed25519
# Max. PIN lengths .: 127 127 127
# PIN retry counter : 3 0 3
# Signature counter : 0
# KDF setting ......: single
# UIF setting ......: Sign=off Decrypt=off Auth=off
# Signature key ....: 638B FE47 E2AD 28BA CE3A B114 F11A 65E1 A88F 0237
# created ....: 2024-06-30 21:44:16
# Encryption key....: A4CB 2108 6F42 2142 6485 FA3C A8B1 1410 DB58 AC7A
# created ....: 2024-06-30 21:44:17
# Authentication key: 14A3 3094 4499 4F9F 430D 8927 952E 563E 4CEB 347B
# created ....: 2024-06-30 21:44:17
# General key info..: sub ed25519/F11A65E1A88F0237 2024-06-30 user <user@email.com>
# sec# ed25519/C8A9786CD87AEECB created: 2024-06-30 expires: never
# ssb> ed25519/F11A65E1A88F0237 created: 2024-06-30 expires: never
# card-no: 0006 25087512
# ssb> cv25519/A8B11410DB58AC7A created: 2024-06-30 expires: never
# card-no: 0006 25087512
# ssb> ed25519/952E563E4CEB347B created: 2024-06-30 expires: never
# card-no: 0006 25087512After the completion of the YubiKey configuration write down and store safely all PIN, PUK and Lock codes. Note that a password manager might not be accessible if a PIN / PUK is no longer known.
YubiKey Serial Number: 1234578 Nickname: YUBIKEY1 Config lock code: dac67aece839402edca8272528e837a6 OpenPGP master key ID: 0x012345678ABCDE12 OpenPGP user PIN: difficult password OpenPGP admin PIN: difficult password PIV PIN: password PIV PUK: password FIDO PIN: difficult password OATH password: difficult password OTP slot 1: private laptop OTP slot 1 access code: 123456789abc OTP slot 1 secret: difficult password
