We saw in the previous article the generation of OpenPGP keys. As a reminder, we have in our keychain private keys:

wilson@spaceship:~$ gpg2 --list-secret-keys

sec#  rsa4096/1A8132B1 2017-10-05 [C] [expires: 2018-10-05]
uid         [ultimate] Wilson Eleven <wilson.eleven@labs.com>
ssb   rsa4096/B73A9C79 2017-10-05 [E] [expires: 2018-10-05]
ssb   rsa4096/9CC8B2FB 2017-10-05 [S] [expires: 2018-10-05]
ssb   rsa4096/8047B454 2017-10-05 [A] [expires: 2018-10-05]

We also exported the keys in files:

  • 1A8132B1.priv.asc: contains all private keys
  • 1A8132B1.pub.asc: contains all public keys
  • 1A8132B1.sub_priv.asc: contains only the private keys of the subkeys

With this configuration, we have an effective strategy against theft or loss of the private key that is used for certification. If an attacker take the computer, he will not be able to certify another key. However, the private keys that allow to sign, encrypt and authenticate are still present on the computer. So, in case of the theft of the keys, it would be possible to sign messages during a certain time (the time that the stolen subkey is revoked).

To counter this attack, it is possible to place private keys in a smart card. These devices are very resistant to key extraction techniques. In addition to physical attacks, there is a pin code with 3 tries only. Then it’s locked.

We will see in this article the export of the private keys of the subkeys in a smart card. For this example, I will use a Yubikey 4.

Yubikey, what is it?

Yubikey is a device the size of a classic USB key. This key makes it possible to perform double authentication on website, such as Google or Github. Thus, if a person is in possession of both the email and the password of the victim, the attacker will not be able to connect without this usb key. This is the principle of double authentication, you must be in possession of two secrets.

Yubikey implements an open protocol: universal 2nd factor.

In addition to this main protocol, it supports others: OpenPGP, TOTP, HOTP, challenge-response.

The one that will interest us is OpenPGP.

How to get one

I recommend you go through the official store to ensure the origin of the product. We are on products related to safety, it’s important to know where the purchased product comes from.

For those who have a Github account, there is a promotional offer that allows to have -10% on the cart. Interesting :){:rel=”nofollow noreferrer”}. However, it’s valid only once. I recommend you order at least 2 products. The second will be useful to make a backup in the unfortunate event of the loss of the first one.

Last but not least, our OpenPGP key was generated with a size of 4096 bits. Only the version 4 of the Yubikey allows to save keys of this size. Version 3 and NEO only support keys up to 3072 bits.

Install the necessary tools

As a reminder, we started our generation of OpenPGP key with a machine running Ubuntu 16.04 and GnuPG 2.1.11. To be able to export the keys to the Yubikey, we need to install additional tools beforehand.

wilson@spaceship:~$ sudo apt-get install -y gnupg-agent pinentry-curses scdaemon pcscd yubikey-personalization libusb-1.0-0-dev

Customize the Yubikey with gpg

Before using the Yubikey, check that the warranty tape has not been broken. If so, do not use it.

Insert the Yubikey into a USB port and type the following command to verify that the card is well recognized.

wilson@spaceship:~$ gpg2 --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006064764950000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 06476495
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
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]

The card is blank, there is no personal information. It is recommended to supplement the information in case a nobody would find this key.

Edit the card and switch to admin mode. You can enter help to get the list of available commands.

wilson@spaceship:~$ gpg2 --card-edit
gpg/card> admin
Admin commands are allowed

First of all, we’ll change the PIN key administration code and user PIN. By default, the administrator PIN is 12345678 and the user PIN is 123456.

The administrator PIN is required for some operations on the card, such as the key export, and to unlock when a PIN code has been entered 3 times by mistake.

Enter passwd to change them. Let’s start with the administrator PIN and then the user PIN.

gpg/card> passwd
gpg: OpenPGP card no. D2760001240102010006064764950000 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>

Then enter the information to customize your key:

gpg/card> name
Cardholder's surname: Wilson
Cardholder's given name: Eleven

gpg/card> lang
Language preferences: fr

gpg/card> login
Login data (account name): wilson.eleven@labs.com

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

gpg/card> quit

The key is now configured. We can export the private keys of the subkeys in the smart card.

Export the keys to the Yubikey

The goal is to move the secret keys of the subkeys into the Yubikey. In order to do so, we will select each subkey one by one with the key n command and move it in the card with keytocard. In the end, there will be no more secrets in the gpg keychain.

Let’s edit the key.

wilson@spaceship:~$ gpg2 --expert --edit-key 1A8132B1
gpg (GnuPG) 2.1.11; Copyright (C) 2016 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.

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
ssb  rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb  rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

gpg>

Let’s export the encryption key to B73A9C79.

gpg> key 1

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
ssb  rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb  rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

The small asterisk in front of the key’s fingerprint indicates that it’s selected.

Enter keytocard to export it to the Yubikey. Then type 2 which is the only choice. The Yubikey can store the 3 types subkeys.

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

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
     card-no: 0006 06476495
ssb  rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb  rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

gpg will ask you for the password of the secret encryption key and then the admin pin code of the Yubikey key. Once the Yubikey admin pin code entered, the secret encryption key is in the Yubikey. We can check it right after moving the other two keys.

Let’s select the signature key. Deselect the first key and select the second.

gpg> key 1

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
     card-no: 0006 06476495
ssb  rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb  rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

gpg> key 2

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
     card-no: 0006 06476495
ssb* rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb  rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

gpg>

The second key is well selected because there is the small asterisk in front of the key 9CC8B2FB.

Repeat the operation with keytocard command and select 1 because it’s a key signature.

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

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
     card-no: 0006 06476495
ssb* rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb  rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

gpg>

It’s ok for the second key. Repeat with the third.

gpg> key 2

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
     card-no: 0006 06476495
ssb  rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb  rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

gpg> key 3

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
     card-no: 0006 06476495
ssb  rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb* rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

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

pub  rsa4096/1A8132B1
     created: 2017-10-05  expires: 2018-10-05  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/B73A9C79
     created: 2017-10-05  expires: 2018-10-05  usage: E
     card-no: 0006 06476495
ssb  rsa4096/9CC8B2FB
     created: 2017-10-05  expires: 2018-10-05  usage: S
ssb* rsa4096/8047B454
     created: 2017-10-05  expires: 2018-10-05  usage: A
[ultimate] (1). Wilson Eleven <wilson.eleven@labs.com>

gpg>

We are done. Type save and quit.

Let’s check that we do not have any secret keys in our gpg keychain anymore.

wilson@spaceship:~$ gpg2 --list-secret-keys
/home/wilson/.gnupg/pubring.gpg
--------------------------------
sec#  rsa4096/1A8132B1 2017-10-05 [C] [expires: 2018-10-05]
uid         [ultimate] Wilson Eleven <wilson.eleven@labs.com>
ssb>  rsa4096/B73A9C79 2017-10-05 [E] [expires: 2018-10-05]
ssb>  rsa4096/9CC8B2FB 2017-10-05 [S] [expires: 2018-10-05]
ssb>  rsa4096/8047B454 2017-10-05 [A] [expires: 2018-10-05]

The chevron > before ssb indicates that the secret key does not exist for this key. It’s a stub.

Let’s check that these secret keys are in the Yubikey.

wilson@spaceship:~$ gpg2 --card-status

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006064764950000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 06476495
Name of cardholder: Eleven Wilson
Language prefs ...: fr
Sex ..............: male
URL of public key : [not set]
Login data .......: wilson.eleven@labs.com
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: 49B7 73DB 292F 8A66 C254  AC97 69FE 9865 9CC8 B2FB
      created ....: 2017-10-05 11:39:18
Encryption key....: 88CD 3F3C BA60 1AFD D0A6  22E9 FE2B A21E B73A 9C79
      created ....: 2017-10-05 11:36:19
Authentication key: 0E2F 255E DE28 F044 474D  E571 F000 F81C 8047 B454
      created ....: 2017-10-05 11:43:21
General key info..: sub  rsa4096/9CC8B2FB 2017-10-05 Wilson Eleven <wilson.eleven@labs.com>
sec#  rsa4096/1A8132B1  created: 2017-10-05  expires: 2018-10-05
ssb>  rsa4096/B73A9C79  created: 2017-10-05  expires: 2018-10-05
                        card-no: 0006 06476495
ssb>  rsa4096/9CC8B2FB  created: 2017-10-05  expires: 2018-10-05
                        card-no: 0006 06476495
ssb>  rsa4096/8047B454  created: 2017-10-05  expires: 2018-10-05
                        card-no: 0006 06476495

We find the personal information in the first part. Then there is the information on the keys stored in the Yubikey.

We see that there is the chevron > before ssb. As seen above, this indicates the absence of the secret key in the keychain. Just below, there is an extra line that tells gpg where to find the secret key. Here we have the serial number of the Yubikey card-no: 0006 06476495. This serial number is also printed on the key physically. If you have multiple Yubikeys, it will be easy to find the one you are looking for.

Conclusion

Through these first two articles, we covered the creation of an OpenPGP key and the export of secrets on a smart card. The use of a smart card provides additional protection against the theft of secret keys. It will not be enough to hack the computer to steal them, but it will be necessary to physically steal the key and the associated PIN code to use the secret keys. Moreover, as seen in the introduction, the secret key cannot be extracted. Our key is well protected, except against the human factor which remains the only threat.

In addition, you can distribute your public key on a key server and other services (GitHub, Kraken, keybase.io){:rel=”nofollow noreferrer”}. This allows you to receive encrypted messages, and sign your commits on GitHub (example on this commit 31dd621){:rel=”nofollow noreferrer”}.

In a future article, we will set up a backup strategy to cover for the potential loss of secret keys. An error can quickly happen, like erasing your computer following a ransomware.

Article en relation

Resources

Remarks

This tutorial uses a Yubikey for storing secrets. Yubikey is the most popular key in the general public, especially for the second authentication factor feature. There are other keys that support OpenPGP such as NitroKey. Unlike the Yubikey, the NitroKey is open-source. Security with closed and proprietary hardware is not a viable solution in the long term. It’s also contradictory to the OpenPGP spirit, that aims to be open. However, I chose the Yubikey for its ease of implementation and its ability to do double authentication.