Introduction

Before you begin, it would probably be a good idea to have three flash drives and a Yubikey.

  1. Your first USB stick will be a Live USB that will boot the airgapped system.
  2. The second will store the packages that you will need to install on the newly booted airgapped machine
  3. The last USB stick will hold the newly generated master key. It would probably be a good idea to store this stick in a safe
  4. Your Yubikey will hold a copy of your generated subkeys for use going forward

Purpose

The goal of this post is to document the process I used to add keys to my Yubikey, please do plenty of research before simply following this guide as best practices may have changed.

Booting up an airgapped machine

In this guide, as in the tutorial this is based on, we will be using an Ubuntu live USB.

When running on an Ubuntu machine, "Startup Disk Creator" can be used to make the live USB if you don't already have one created.

Downloading required packages

Before you can boot your live USB you need to download all the required packages and save them to one of the USB sticks.

To download the packages, the easiest way I found was to install the packages after connecting to the internet on the Live USB system. After saving the packages, reboot and this time rather than connecting to the internet, install the packages saved to the USB drive.

After starting up the live system and connecting to the internet:

Add the universe repository:

# add-apt-repository universe

Add the Yubikey ppa:

# add-apt-repository ppa:yubico/stable

Run update to download new package lists:

# apt update

Install packages with the "download-only" flag:

# apt-get --download-only install \
    scdaemon yubikey-personalization \
    libccid pcscd rng-tools gnupg2 ykpersonalize

Copy the files to USB drive, for example:

$ mkdir /media/usb/MyPackages
$ cp -a /var/cache/apt/archives/*.deb /media/usb/MyPackages

Installing the packages

Reboot your live system after ensuring the computer is no longer connected to the internet (i.e. unplug any Ethernet cables)

Install the packages copied to the USB earlier:

# dpkg -i /media/usb/MyPackages

Generating keys

First start rngd to ensure computed has plenty of random bits available:

# rngd -r /dev/urandom

The default GPG workspace for GPG is ~/.gnupg. We can set this to something easier to work with by setting $GNUPGHOME.

$ export GNUPGHOME="$HOME/workspace"
$ mkdir $GNUPGHOME

In this guide, we will generate one master key and three subkeys, each with a single responsibility:

  • sign-only key
  • encryption key
  • authentication key

Generating master key

$ gpg2 --full-gen-key

Running this command will open a menu to configure options before creating the new key

  • Select key type: Select (4) sign-only
  • Choose the larger size (4096 bit.)
  • Enter your personal information (name and email)
  • Select an expiration date for the key

List public keys:

$ gpg2 --list-keys

List private keys:

$ gpg2 --list-secret-keys

Using the output from the above command, save the key id to a variable for use later, for example:

$ export KEYID=AD2A33A5833064D4065EF6D7AFC3D78A4CB7C59D

Generate a revocation certificate

Since we are going to kept the master key on a USB key in storage, it is a good idea to generate a revocation certificate while we have access to the master key.

$ gpg2 --output $GNUPGHOME/revocation-certificate.txt --gen-revoke $KEYID

Select option (1) "Key has been compromised" and add a comment when asked.

Creating subkeys

Generate sign-only subkey

$ gpg2 --expert --edit-key $KEYID

This should open up the builtin GPG REPL.

  • Start sub key creation be running the "addkey" command
  • Select option (4) Sign-only key
  • Select your key size (Yubikey 4: 4096 and Yubikey Neo: 2048) and expiration date
  • After this type y twice to confirm
  • Lastly, type save to save changes and exit

Generate encryption subkey

$ gpg2 --expert --edit-key $KEYID

This should open up the builtin GPG REPL.

  • Start sub key creation be running the "addkey" command
  • Select option (6) RSA encryption only
  • Select your key size (Yubikey 4: 4096 and Yubikey Neo: 2048) and expiration date
  • After this type y twice to confirm
  • Lastly, type save to save changes and exit

Generate authentication subkey

$ gpg2 --expert --edit-key $KEYID

This should open up the builtin GPG REPL.

  • Start sub key creation be running the "addkey" command
  • Select option (8) RSA set your own ability, and toggle the options until you see Current allowed actions: Authenticate
  • Select your key size (Yubikey 4: 4096 and Yubikey Neo: 2048) and expiration date
  • After this type y twice to confirm
  • Lastly, type save to save changes and exit

Add additional email addresses to the key (optional)

$ gpg2 --edit-key $KEYID

This should open up the builtin GPG REPL.

  • Running the "adduid" command
  • Follow the prompts to enter your "Real name", "Email" and "Comment"
  • After this enter o to confirm
  • Lastly, type save to save changes and exit

Check the keyring

Listing keys should produce output like this now:

$ gpg2 --list-keys
pub   rsa4096 2018-06-23 [SC] [expires: 2023-06-22]
    68207CD9783F93ECBFF9653640D9D08813E47FC4
uid           [ultimate] Paul Schwendenman <schwendenman.paul@example.com>
uid           [ultimate] Paul Schwendenman <paul@example.org>
sub   rsa2048 2018-06-23 [S] [expires: 2023-06-22]
sub   rsa2048 2018-06-23 [E] [expires: 2023-06-22]
sub   rsa2048 2018-06-23 [A] [expires: 2023-06-22]

Export Public key

$ gpg2 -a --export $KEYID > public-key.asc

Copy your public key to a USB for later use, I'd recommend the one we used to store the air gapped packages.

Importing the public key on your machine later:

$ gpg2 --import < public-key.asc

Backing up master key to USB drive

Create a backup copy of your GNUPGHOME before adding subkeys to Yubikey:

$ cp -r $GNUPGHOME{,.bak}

Check connection to your Yubikey

Insert your Yubikey

Ensure that gpg is able to see your smart card:

$ gpg2 --card-status

Also check that the detected serial number matches the one on the key.

If your key is not present, you may need to restart pcscd:

$ sudo service pcscd restart

You may need to disable OTP on your Yubikey, I believe that newer Yubikeys are shipped configured to run all three modes (OTP, U2F and PGP) simultaneously. However, if you have issues perhaps look into enabling CCID or disabling OTP and deleting it from the configured slots using the yubikey-personalization tool.

Setting up your Yubikey

The Yubikey has two PINs. The admin pin is used to manage the user pin, and the user pin is used to manage access to the keys.

Change the admin pin (default: 123456678):

$ 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

Your selection? 3

And then user pin (default: 123456):

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

Your selection? 1

You can now leave the passwd menu:

PIN changed.

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

Your selection? Q

Be sure to write both pins down to be stored with the USB with your backed-up GPG key, since the pin can't be used to open the backed up GPG key, it is fine to store them together. Otherwise you'll have to repeat the moving key steps after resetting the Yubikey if you ever forgot the pins.

After changing both pins, change the other registration fields: "Name", "Login", "URL", etc. After changing the desired values, you can exit with quit.

For example, changing the name:

gpg/card> name
Cardholder's surname: Schwendenman
Cardholder's given name: Paul

To list fields and check your settings use the list command:

gpg/card> list

Manufacturer .....: Yubico
Name of cardholder: Paul Schwendenman
Language prefs ...: en
URL of public key : https://whatsdoom.com/40D9D08813E47FC4.txt
Login data .......: paul

If you have a keybase account you can use it to host public keys, for example:

https://keybase.io/whatsdoom/key.asc

Obviously, you would have to add the newly created key to keybase using you public after you restart to your normal system at the end.

Enabling touch-only mode

If you have a Yubikey 4 (rather than a Neo), you can enable "touch-only" mode which requires a touch to return the result of crytographic operations.

Information can be found on Yubico's site.

Moving subkeys to Yubikey

Note moving keys is destructive ensure you have backed up the keys before proceeding.

Carefully add each key to the correct spot, the sequence should look something like:

$ gpg2 --edit-key $KEYID
> key 1
> keytocard
> 1
> key 1
> key 2
> keytocard
> 2
> key 2
> key 3
> keytocard
> 3
> save

Check that you have successfully moved you keys:

$ gpg2 --card-status

You should now see the key information in the output.

Next steps

You are now ready to use the Yubikey on you normal machine. Ensure that you have copied the backup directory (${GNUPGHOME}.bak) to your flash drive. After you have double checked that the backup directory was safely copied, you can restart you live system and boot the normal system.

On your normal machine, install the following packages to use your Yubikey:

sudo apt-get -y install scdaemon libccid gnupg2 pcsc-tools

Remember to use your yubikey, you'll need to import the public key in to the keyring.

$ gpg2 --import < public-key.asc

You can now use your key to sign git commits, send encrypted messages and ssh into remote machines!