Overview

This post follows on from the initial setup post. The aim for this post is around setting up the GPG applet.
A lot of initial choices and methods are based off my original GPG guide. This will cover creating new keys based on elliptic curve cryptography.

I have revoked my previous GPG keys with the finger print of 174D 1B90 066F F847 7A95 E69E 7FB0 D040 76E0 A15A.

Requirements

  • YubiKey 5, any model
  • Tails
  • Two new USB keys

Preparation steps

Use the Off-line stage section from my Yubikey 5 setup for all steps during this article.

Creating the keys

USB stick setup

Firstly clearly label your USB sticks. One will be used to store our Master key and revocation certificate. This USB stick should never be mounted outside of the secure Tails environment.

The second USB stick will be used to transfer things like our public key to our normal operating environment.

Create the following directories :

/mnt/master
/mnt/dirty

Where master is our first USB stick and dirty is the second.
Mount each USB stick onto the above directories.

Encrypted master key storage

To store my master keys and other sensitive materials I use a LUKS container. I create a file vs use a raw device like a USB stick to ensure I can copy the LUKS volume to any storage medium.
For example I have this LUKS container backed up on a m-disk blu-ray and on a USB stick in more then one location.
Pass-phrases are stored in my password manager.

Open up a root level terminal and follow the below to create the container.
I create this on the master USB stick in the following manner.

dd if=/dev/zero bs=1M count=1024 of=/mnt/master/gpg-luks.volume
cryptsetup luksFormat /mnt/master/gpg-luks.volume
cryptsetup luksOpen /mnt/master/gpg-luks.volume gpg-luks
mkfs.ext4 /dev/mapper/gpg-luks
mkdir /mnt/luks-crypt
mount /dev/mapper/gpg-luks /mnt/luks-crypt

GPG setup

Next we setup where GPG will store its user data. By default this is ~/.gnupg however we want it on our luks container.
We can achieve this via the following commands :

export GNUPGHOME=/mnt/luks-crypt
mkdir $GNUPGHOME
chmod 700 $GNUPGHOME

We will also need a default config file for GPG.
Again, the settings selected here and why I have selected them are explained in the original guide.

For now create a this file $GNUPGHOME/gpg.conf, with the following contents :

default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAMELLIA256 CAMELLIA192 CAMELLIA128 TWOFISH
cert-digest-algo SHA512

Yubikey setup

The Yubikey from factory is set to store RSA key types, however we want to use elliptic curve keys. Thus we need to edit the card.
Plug in the YubiKey and run the following command gpg --edit-card.
At the gpg/card> prompt type admin, you will be prompted for the password in the next step.
Next we change the key attributes via the key-attr command.
I will use ECC/Curve 25519 over the NIST curve due to security issues with the NIST curves.

It should look similar to this output :

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

You can then check that the Yubikey is configured correctly via the list command.
Under the section Key attributes You should see the following :
Key attributes ...: ed25519 cv25519 ed25519

Once done enter quit to exit the card edit menu.

Master keys and revocation certificate

Now its time to create the new off line master key and revocation certificate. I use the --quick-gen-key option that takes care of generating the key and the revocation certificate in one step.

Issue the command :

 gpg --quick-gen-key "Brendan Horan <brendanhoran@basstech.net>" ed25519 sign 0

I don't want my master key to expire, hence the time value of 0.
The output of the above command looks like this :

gpg --quick-gen-key "Brendan Horan <brendanhoran@basstech.net>" ed25519 sign 0
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: /mnt/luks-crypt/trustdb.gpg: trustdb created
gpg: key 60932F9ECAA57A91 marked as ultimately trusted
gpg: directory '/mnt/luks-crypt/openpgp-revocs.d' created
gpg: revocation certificate stored as '/mnt/luks-crypt
/openpgp-revocs.d/AA2BF3D687A2E671610587E460932F9ECAA57A91.rev'
public and secret key created and signed.

pub   ed25519 2020-07-12 [SC]
      AA2BF3D687A2E671610587E460932F9ECAA57A91
uid                      Brendan Horan <brendanhoran@basstech.net>

I then export my secret keys as a backup :

gpg -a --export-secret-keys AA2BF3D687A2E671610587E460932F9ECAA57A91 > $GNUPGHOME/master_key.txt

Addition ID's

I like to add additional ID's to my keys, I normally add my most common/most used email addresses as additional ID's.

To do that issue the following command :

gpg --edit-key AA2BF3D687A2E671610587E460932F9ECAA57A91

We then add additional ID's like tis :

gpg> adduid
Real name: Brendan Horan
Email address: brendan@horan.hk
Comment:
You selected this USER-ID:
    "Brendan Horan <brendan@horan.hk>"

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

After this the ID will be unknown, you should give it a trust level. I set this to ultimate.

Ensure you only have one ID toggled active as indicated by an * after the ID index number. Then issue the trust command.

Output of the trust command looks like :

[ultimate] (1). Brendan Horan <brendanhoran@basstech.net>
[ unknown] (2)* Brendan Horan <brendan@horan.hk>

Please decide how far you trust this user to correctly verify other users keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y

Once done, issue the save command to write this to the key.

Subkeys

I use subkeys for my encryption, authentication and signing keys.
This allows me to store them easily on the Yubikey. I set expiry dates on all my subkeys. You can refer back to the original article for more details on why.

To generate sub keys simply run the following :

gpg --quick-add-key AA2BF3D687A2E671610587E460932F9ECAA57A91 cv25519 encr 365d
gpg --quick-add-key AA2BF3D687A2E671610587E460932F9ECAA57A91 ed25519 auth 365d
gpg --quick-add-key AA2BF3D687A2E671610587E460932F9ECAA57A91 ed25519 sign 365d

Take a look to ensure they where created correctly :

gpg --list-keys
/mnt/luks-crypt/pubring.kbx
---------------------------------
pub   ed25519 2020-07-12 [SC]
      AA2BF3D687A2E671610587E460932F9ECAA57A91
uid           [ultimate] Brendan Horan <brendanhoran@basstech.net>
uid           [ultimate] Brendan Horan <brendan@horan.hk>
sub   cv25519 2020-07-12 [E] [expires: 2021-07-12]
sub   ed25519 2020-07-12 [A] [expires: 2021-07-12]
sub   ed25519 2020-07-12 [S] [expires: 2021-07-12]

It is now a good time to take a backup of all the keys.

gpg -a --export-secret-keys AA2BF3D687A2E671610587E460932F9ECAA57A91 > $GNUPGHOME/master_with_subkeys.txt
gpg -a --export-secret-subkeys AA2BF3D687A2E671610587E460932F9ECAA57A91 > $GNUPGHOME/subkey_stubs.txt
gpg -a --export AA2BF3D687A2E671610587E460932F9ECAA57A91 > $GNUPGHOME/public_key.txt

You should also copy the public_key.txt to the dirty usb stick. This is the only section that needs to be transfered to your daily workstation.

Move the subkeys to the Yubikey

Nothing much in this process has changed.
You can follow the previous guide to move the subkeys to the Yubikey.

References