Skip to content

Latest commit

 

History

History
596 lines (502 loc) · 24.7 KB

File metadata and controls

596 lines (502 loc) · 24.7 KB

Yubikey Introduction

https://github.com/echjansen/pure-security/blob/main/assets/yubikey5.png?raw=true

Key Features

  • 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

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

FirmwareFIDO2FIDO U2FPIVOATH-TOTPOTPOPENPGP
5.7100unlimited4642 credentials, unlimited services3 subkeys [S E A]
5.0 - 5.625unlimited4322 credentials, unlimited services3 subkeys [S E A]

There are many different YubIkey types and versions available. Check the YubiKey devices webpage for further specifications.

YubiKey 5 Pincodes

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.

InterfacePINsDescription
FIDO21 PINAuthenticate to services without a password.
No default Pin
The PIN is set during the first time link to service
GPG1 User PINEncrypting, decrypting, signing, and SSH
1 Unlock PINDefaults
1 Admin PINUser Pin : 123456
Admin Pin : 12345678
PIV2 PINsx509 certificates / keypairs. Bitlocker, Veracrypt, SSH, etc
1 ManagementDefaults
User Pin : 123456
Admin Pin : 12345678

Prerequisites

Software Installation

Install the yubikey-manager software:

sudo pacman -S yubikey-manager
sudo systemctl enable pcscd.service
sudo systemctl start pcscd.service

YubiKey hardware

Withe 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     Enabled

Configuration

A 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:

infoshow general information
listlist connected YubiKeys
scriptrun a python script
configconfigure the YubiKey, enable or disable applications
fidomanage the FIDO applications
hsmauthmanage the YubiHSM Auth application
oathmanage the OATH application
openpgpmanage the OpenPGP application
otpmanage the YubiOTP application
pivmanage the PIV application

The following notes provide sample scripts to configure a 5-Series YubiKey.

Master Lock Code

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]:
y

The lock-code is required every time an application is enabled / disabled.

Reseting YubiKey

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 application

Configure YubiKey for OpenPGP

Enable OpenPGP Mode

The enable OpenPGP mode on YubiKey execute the following commands:

ykman config usb -f -e OPENPGP

Enable Key Derived Function (KDF)

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

Configure PIN codes

The OpenPGP app has 3 PINs:

  1. User PIN,
  2. Reset PIN (aka PUK, PIN Unblock Key),
  3. 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?
1

Enter 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? q

Backup the PIN codes (see Backup PINS)

(optional) Transfer GPG sub-keys to YubiKey

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_xxxxx

From 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> save

(optional) Create GPG sub-keys in YubiKey

As 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? o

Enter 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 GPG sub-keys transfer to YubiKey

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 25087512

Test GPG Encryption

To 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=

Configure YubiKey on another machine

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.

Import public key

Import public key from github

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: 1

Create stub for YubIkey

Once 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 25087512

Backup PINS and PUKS and Lock-Code

After 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