Yubikey NEO for GPG, SSH and Profit

Reading time ~6 minutes

TLDR

I am updating my GPG keys

Process

I am cleaning up my GPG keys along the way as part of my DR plan. At the moment I have a mess of keys everywhere! Most legacy keys have expired, been revoked or ultimately lost through mismanagement. My aim is to arrive at a point where I can carry with me my identity for both SSH and GPG.

I am generating a day-to-day GPG key to use via my Yubikey NEO. I will also create a backup GPG smart card using a spare German Privacy Foundation Cryptostick v1.2. Finally, the master copy remains on a physically secured USB key(s).

What follows below is notes on recreating this whole thing from scratch again.

Trusted Live Environment

To generate new keys I first boot a ancient laptop using an isostick and a copy of the Fedora 21 Workstation image. After verifying the sha256sum I copied the ISO to the isostick and can boot via the virtual CD-ROM.

Once booted and presented with the installers grub menu, select Troubleshooting then Test this media & start Fedora Live. At this stage I also press tab and remove the quiet rhbg arguments so that I get feedback on the boot process.

At the gnome prompt click Try Fedora to continue into the live OS.

Extending the Live Environment

The first time you boot you will need to connect your environment to the Internet and grab some packages for offline use later.

sudo yum install yum-utils
yumdownloader --resolve ykpers-devel libyubikey-devel libusb-devel autoconf gnupg gnupg2-smime pcsc-lite pcsc-lite-libs
yumdownloader --resolve gnupg-agent libpth20 pinentry-curses libccid pcscd scdaemon libksba8

Full deps in the case of resolve not working, it seems that pre-installed packages are not pulled into the download directory leaving you with broken deps.

autoconf-2.69-16.fc21.noarch.rpm
elfutils-0.161-2.fc21.x86_64.rpm
elfutils-libelf-0.161-2.fc21.x86_64.rpm
elfutils-libs-0.161-2.fc21.x86_64.rpm
glibc-2.20-7.fc21.x86_64.rpm
glibc-common-2.20-7.fc21.x86_64.rpm
gnupg-1.4.18-4.fc21.x86_64.rpm
gnupg2-smime-2.0.25-2.fc21.x86_64.rpm
libgudev1-216-17.fc21.x86_64.rpm
libusb-devel-0.1.5-5.fc21.x86_64.rpm
libusbx-devel-1.0.19-2.fc21.x86_64.rpm
libyubikey-1.11-3.fc21.x86_64.rpm
libyubikey-devel-1.11-3.fc21.x86_64.rpm
m4-1.4.17-6.fc21.x86_64.rpm
nss-softokn-freebl-3.17.4-1.fc21.x86_64.rpm
pcre-8.35-8.fc21.x86_64.rpm
pcsc-lite-1.8.13-1.fc21.x86_64.rpm
pcsc-lite-ccid-1.4.18-1.fc21.x86_64.rpm
pcsc-lite-libs-1.8.13-1.fc21.x86_64.rpm
systemd-216-17.fc21.x86_64.rpm
systemd-compat-libs-216-17.fc21.x86_64.rpm
systemd-libs-216-17.fc21.x86_64.rpm
systemd-python-216-17.fc21.x86_64.rpm
systemd-python3-216-17.fc21.x86_64.rpm
ykpers-1.16.1-1.fc21.x86_64.rpm
ykpers-devel-1.16.1-1.fc21.x86_64.rpm

After yum has downloaded the packages to your working directory copy them to media you can attach to your offline machine.

Reboot to start a clean instance and mount your storage containing the downloaded packages.

yum localinstall *

Now we can get started generating keys!

RAID

While some people might trust their cold storage, since I am using what are actually very crappy USB keys I thought I might RAID then just in case one decides to flip a bit on me.

Creating the array

First lets test both disks are actually OK

dd if=/dev/zero of=/dev/disk/by-id/YOUR-DISK

Create the RAID partitions

fdisk /dev/disk/by-id/YOUR-DISK
n
p
1
enter
enter
t
fd
w

Create the array

mdadm --create md0 -n 2 -l 1 /dev/sdc1 /dev/sdd1

Lets format it!

mkfs.ext4 /dev/md0
mkdir /tmp/raid
mount /dev/md0 /tmp/raid

Further use

Once we are done we will stop the array to unplug the USB keys

umount /dev/md0
mdadm -S md0

To re-use this array next time we scan for existing RAID with both disks plugged in

mdadm --assemble -s

Generate the master key

After opening your terminal window, you need to update the environment variables for gnupg.

export GNUPGHOME=/tmp/raid/gnupg
mkdir $GNUPGHOME

Note: You cannot mount this on a vfat volume as gpg-agent will not be able to open a unix socket.

Now we update our config

cat > $GNUPGHOME/gpg.conf
personal-cipher-preferences AES256 AES192 AES
personal-digest-preferences SHA512 SHA384 SHA256 SHA224
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
use-agent

Note: You can’t opt out of 3DES and SHA with this configuration. gnupg will automatically add them to the trailing end of your preferences.

After the configuration is done we generate the master key to be used only for signing operations.

    gpg2 --gen-key
    Your Selection? 4
    4096
    2y
    y
    Sam Wilson
    [email protected]
    O

Now we can add our extra UID’s

    gpg2 --edit-key <YOUR KEY ID>
    adduid
    Sam Wilson
    [email protected]
    O
    uid 1
    primary
    save

Generate a revocation certificate

    gpg2 --output $GNUPGHOME/../revocation-certificate.txt --gen-revoke <YOUR KEY ID>
    1
    Created during key creation, emergency use only.

Backup the private keys to ascii

gpg2 -a --export-secret-keys <YOUR KEY ID> > $GNUPGHOME/../masterkey.txt

Generate sub keys

First we generate separate 2048 bit RSA keys for signing, authentication and encryption.

    gpg2 --expert --edit-key <YOUR KEY ID>
    addkey
    4
    2048
    2y
    y
    y
    addkey
    6
    2048
    2y
    y
    y
    addkey
    8
    s
    e
    a
    q
    2048
    2y
    y
    y
    save

Lets backup our sub keys.

gpg2 -a --export-secret-keys <YOUR KEY ID> > $GNUPGHOME/../mastersubkeys.txt
gpg2 -a --export-secret-subkeys <YOUR KEY ID> > $GNUPGHOME/../subkeys.txt

Also backup the $GNUPGHOME binary content in case we need to roll back GPG during later steps.

You can print to hard copy the text files we are created now.

Configure Yuibkey NEO

I found starting up gpg2 --card-edit as liveuser failed to open the smartcard. Running as root resolves the issue.

Lets configure the Yubikey NEO!

    gpg2 --card-edit
    admin
    passwd
    3
    12345678 # Default admin passwd
    <NEWPIN>
    <NEWPIN>
    1
    123456 # Default user passwd
    <NEWPIN>
    <NEWPIN>
    q
    name
    Wilson
    Sam
    lang
    en
    url
    https://www.cycloptivity.net/KEYID.txt
    sex
    m
    quit

Note: If your looking for a random pin generator try < /dev/urandom tr -cd 0-9 | head -c 6.

Now we start to move our sub keys to hardware. This is a one way operation and will leave the backups we took earlier as the only copy of your sub keys (except for the smart card of course!).

    gpg2 --edit-key <YOUR KEY ID>
    toggle
    key 1
    keytocard
    1
    key 1
    key 2
    keytocard
    2
    key 2
    key 3
    keytocard
    3
    save

Note: At this point, I actually hit this bug, after raising a case with Yubico to get a new unit I got started again.

Public key

You need to generate a copy of your master public key to share with the world. Lets make that available quickly.

gpg2 --export -a <KEY ID> >> $GNUPGHOME/../pub.asc

Take a copy of the pub.asc file to your daily laptop along with your Yuibkey.

Setup day to day laptop

Desktop Environments

While technically I should have been able to configure XFCE on my laptop to disable ssh-agent I found this had no effect on Fedora 21.

xfconf-query -c xfce4-session -p /startup/ssh-agent/enabled -n -t bool -s false

Instead its much easier to just hack on this via trusty ~/.bashrc

killall ssh-agent gpg-agent > /dev/null 2>&1
eval $(gpg-agent --daemon --enable-ssh-support)

GPG

On your daily machine we can now publish your primary pub.key as well as import the smartcard for daily use.

To generate the private key stubs and inform your daily GPG of the smartcard run

gpg2 --card-status

After which you should see your smartcard and offline master listed in

gpg2 --list-secret-keys

Other pain points

Smartcard fetch

There is an open issue here where running

gpg2 --card-edit
fetch

actually fails for me where GPG will search for the smartcards signing key ID while actually getting the master offline key ID. Thus the operation fails.

As a workaround you can totally pull the key with curl =\

https://www.cycloptivity.net/6E03FC34.txt | gpg2 --import

Missing Serial Numbers

In Donncha O’Cearbhaill’s very helpful post I found the key to swapping smartcards to avoid the “Please insert Serial Number X” error.

When changing cards first drop your private key

rm ~/.gnupg/private-keys-v1.d/<PRIVATE KEY ID>.key

Then, after a reboot import your smartcard details

gpg2 --card-status
ssh-add -l

References

These posts helped me out a lot when writing this! YMMV

https://help.riseup.net/en/security/message-security/openpgp/best-practices

http://blog.josefsson.org/2014/06/23/offline-gnupg-master-key-and-subkeys-on-yubikey-neo-smartcard/

https://github.com/herlo/ssh-gpg-smartcard-config/blob/master/YubiKey_NEO.rst

http://www.bradfordembedded.com/2013/12/yubikey-smartcard/

http://ekaia.org/blog/2009/05/10/creating-new-gpgkey/

https://www.debian-administration.org/users/dkg/weblog/97

https://developers.yubico.com/ykneo-openpgp/ResetApplet.html

https://josefsson.org/key-transition-2014-06-22.txt

http://www.bootc.net/archives/2013/06/09/my-perfect-gnupg-ssh-agent-setup/

http://dst.lbl.gov/ksblog/2011/05/xfce-without-gpg-agent/

http://docs.xfce.org/xfce/xfce4-session/advanced

http://donncha.is/2014/07/problems-using-an-openpgp-smartcard-for-ssh-with-gpg-agent/

Configuring dual stack IPv6 without DHCPv6-PD

Configuring dual stack IPv6 without DHCPv6-PD Continue reading

Mount Cloudmaker VK2/CT-015

Published on September 21, 2019

Tackling Mount Warrigal VK2/CT-057

Published on September 27, 2018