Yubikey 4 as a GPG Smart Card

The Yubikey is a small USB token which can be used for OTP, U2F and CCID

I don’t use my Yubikey for anything other than CCID as I prefer to use Authy on my phone instead, I do however leave the OTP feature enabled so that udev gives the correct permissions to the card.

I generated my GPG keys on a LiveCD and backed them up to a USB Drive

Arch provide the udev rules in the package named yubikey-personalization

/usr/lib/udev/rules.d/69-yubikey.rules

ACTION!="add|change", GOTO="yubico_end"

# Udev rules for letting the console user access the Yubikey USB
# device node, needed for challenge/response to work correctly.

# Yubico Yubikey II
ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0010|0110|0111|0114|0116|0401|0403|0405|0407|0410", \
    ENV{ID_SECURITY_TOKEN}="1"

LABEL="yubico_end"

You will also need yubikey-manager if you want to enable touch-to-sign which protects you against malware accessing your key without you knowing.

Setup GPG-Agent

~/.gnupg/gpg-agent.conf

enable-ssh-support
pinentry-program /usr/bin/pinentry-curses
default-cache-ttl 60
max-cache-ttl 120
write-env-file
use-standard-socket

Generate GPG Key

root@host ~ % gpg --full-gen-key
gpg (GnuPG) 2.1.20; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

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)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
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) 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: Real Name
Email address: username@example.com
Comment:
You selected this USER-ID:
    "Real Name <username@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /home/matt/.gnupg/trustdb.gpg: trustdb created
gpg: key CB552D2D943B076C marked as ultimately trusted
gpg: directory '/home/matt/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/matt/.gnupg/openpgp-revocs.d/049797118B105FF682FE5435CB552D2D943B076C.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   rsa4096 2017-04-19 [SC]
      049797118B105FF682FE5435CB552D2D943B076C
      049797118B105FF682FE5435CB552D2D943B076C
uid                      Real Name <username@example.com>

Add any extra identities

root@host ~ % gpg --edit-key CB552D2D943B076C                                                                                                           :(
gpg (GnuPG) 2.1.20; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
[ultimate] (1). Real Name <username@example.com>

gpg> adduid
Real name: Real Name
Email address: username@example.org
Comment:
You selected this USER-ID:
    "Real Name <username@example.org>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
[ultimate] (1)  Real Name <username@example.com>
[ unknown] (2). Real Name <username@example.org>

gpg> save

Backup your Master Key and Revocation Cert

root@host ~ % gpg -o /path/to/backup/location/CB552D2D943B076C.master.key -a --export-secret-key CB552D2D943B076C
root@host ~ % cp ~/.gnupg/openpgp-revocs.d/*CB552D2D943B076C.key /path/to/backup/location/CB552D2D943B076C.rev

Create subkeys

Sign Subkey

root@host ~ % gpg --expert --edit-key CB552D2D943B076C
gpg (GnuPG) 2.1.20; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
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) 1y
Key expires at Fri 20 Apr 2018 00:00:43 BST
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> save

Encryption Subkey

root@host ~ % gpg --expert --edit-key CB552D2D943B076C
gpg (GnuPG) 2.1.20; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
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) 1y
Key expires at Fri 20 Apr 2018 00:02:06 BST
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> save

Authentication Subkey

root@host ~ % gpg --expert --edit-key CB552D2D943B076C
gpg (GnuPG) 2.1.20; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
Your selection? 8

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? E

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions:

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? A

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
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) 1y
Key expires at Fri 20 Apr 2018 00:04:27 BST
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>
gpg> save

Backup your Subkeys

root@host ~ % gpg -o /path/to/backup/location/CB552D2D943B076C.master.key --export-secret-keys CB552D2D943B076C
root@host ~ % gpg -o /path/to/backup/location/CB552D2D943B076C.subkeys.key --export-secret-subkeys CB552D2D943B076C

Setup your Yubikey

The default admin pin is 123456789 and the default user pin is 123456

root@host ~ % ykpersonalize -m86
root@host ~ % gpg --card-edit

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006052295010000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: Serial
Name of cardholder:
Language prefs ...:
Sex ..............:
URL of public key :
Login data .......:
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
Admin commands are allowed

gpg/card> passwd
gpg: OpenPGP card no. D2760001240102010006052295010000 detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? q

gpg/card> name
Cardholder's surname: Real
Cardholder's given name: Name

gpg/card> lang
Language preferences: en

gpg/card> url
URL to retrieve public key: https://keybase.io/username/key.asc

gpg/card> sex
Sex ((M)ale, (F)emale or space): m

gpg/card> login
Login data (account name): real

gpg/card> quit

Load Subkeys onto Yubikey

root@host ~ % gpg --expert --edit-key CB552D2D943B076C                                                                                                  :(
gpg (GnuPG) 2.1.20; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> toggle

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> key 1

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]

Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

You need a passphrase to unlock the secret key for
user: "Real Name"
4096-bit RSA Key, ID A5F038262802C441, created 2017-04-19

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
     card-no: Serial
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> key 1

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
     card-no: Serial
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> key 2

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
     card-no: Serial
ssb* rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> keytocard

Signature key ....: 8F09 65A5 6F21 E807 B175  EAA0 A5F0 3826 2802 C441
Encryption key....: [none]
Authentication key: [none]

Please select where to store the key:
   (2) Encryption key
Your selection? 2

You need a passphrase to unlock the secret key for
user: "Real Name"
4096-bit RSA Key, ID A5F038262802C441, created 2017-04-19

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
     card-no: Serial
ssb* rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
     card-no: Serial
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> key 2

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
     card-no: Serial
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
     card-no: Serial
ssb  rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> key 3

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
     card-no: Serial
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
     card-no: Serial
ssb* rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> keytocard

Signature key ....: 8F09 65A5 6F21 E807 B175  EAA0 A5F0 3826 2802 C441
Encryption key....: 879B 578C 22A5 C7CA 2E1C  EB0F C0BA A03A CAD0 BB8F
Authentication key: [none]

Please select where to store the key:
   (3) Authentication key
Your selection? 3

You need a passphrase to unlock the secret key for
user: "Real Name"
4096-bit RSA Key, ID A5F038262802C441, created 2017-04-19

sec  rsa4096/CB552D2D943B076C
     created: 2017-04-19  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb rsa4096/A5F038262802C441
     created: 2017-04-19  expires: 2018-04-19  usage: S
     card-no: Serial
ssb  rsa4096/C0BAA03ACAD0BB8F
     created: 2017-04-19  expires: 2018-04-19  usage: E
     card-no: Serial
ssb* rsa4096/CC31B6000E0B6839
     created: 2017-04-19  expires: 2018-04-19  usage: A
     card-no: Serial
[ultimate] (1). Real Name <username@example.org>
[ultimate] (2)  Real Name <username@example.com>

gpg> save

Take a final backup of subkey stubs

root@host ~ % gpg -o /path/to/backup/location/CB552D2D943B076C.mastersubs.key --export-secret-keys CB552D2D943B076C
root@host ~ % gpg -o /path/to/backup/location/CB552D2D943B076C.subkeysubs.key --export-secret-subkeys CB552D2D943B076C
root@host ~ % -o /path/to/backup/location/CB552D2D943B076C.pub.key --export CB552D2D943B076C

After this you can transfer the public key to your online machine and mark your public key as ultimately trusted