All key creation should be performed on a live booted machine without network access. A common way is to live boot Tails and perform all key generation steps inside it. Then copy the generated keys to a USB-stick that is kept in a safe place offline. From here on out all commands should be performed on a live booted Tail machine without network access.

Like mentioned in the goals section, we'll start by creating a GPG key that has primary key pair that can only Certify. To start the process we run:

$ gpg2 --expert --full-generate-key

(We use the flag --expert and --full-generate-key to get all available options when generating our key.)

The first prompt asks what kind of key we want to generate, here we select (8) RSA (set your own capabilities), so that we get to choose what actions the key can perform. In the actions prompt we untoggle all actions except for Certify. In the keysize prompt we input 4096 bits. The Yubikey supports storing keys that are 4096-bits so we will use 4096 bits on all key pairs.

After the GPG key has been created we can verify that it actually exists:

$ gpg2 --list-keys 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 gpg: next trustdb check due at 2018-09-17 /home/me/.gnupg/pubring.kbx ---------------------------- pub rsa4096 2017-09-17 [C] [expires: 2018-09-17] FAB89F7D27C399063F600B036B3D0050CAE0C3C4 uid [ultimate] Richard Zetterberg <richard.zetterberg@example.com>

Next step is to create our 3 subkey pairs from that primary key pair. We use the key ID from the previous step and run:

$ gpg2 --expert --edit-key FAB89F7D27C399063F600B036B3D0050CAE0C3C4

When starting that command we are presented with a overview of the key and a gpg> prompt that accept commands. We start by entering:

gpg> addkey

We are now shown the key creation prompt again. This time we also select (8) RSA (set your own capabilities) for key type. However, this time we only select Sign capability. Same key size as before, 4096-bits.

After creating our Sign subkey, we should see the overview and the gpg> command prompt again:

sec rsa4096/6B3D0050CAE0C3C4 created: 2017-09-17 expires: 2018-09-17 usage: C trust: ultimate validity: ultimate ssb rsa4096/425E1FD67112482A created: 2017-09-17 expires: 2018-09-17 usage: S [ultimate] (1). Richard Zetterberg <richard.zetterberg@example.com> gpg>

By the way, when gpg list keys, it uses the following terminology:

sec SECret key ssb Secret SuBkey pub PUBlic key sub public SUBkey

Next we perform the same addkey steps for the separate Encrypt and Authenticate keys. When done we should see this:

sec rsa4096/6B3D0050CAE0C3C4 created: 2017-09-17 expires: 2018-09-17 usage: C trust: ultimate validity: ultimate ssb rsa4096/425E1FD67112482A created: 2017-09-17 expires: 2018-09-17 usage: S ssb rsa4096/5993DBCB1C9AC33B created: 2017-09-17 expires: 2018-09-17 usage: E ssb rsa4096/8DB918AB30C19F1C created: 2017-09-17 expires: 2018-09-17 usage: A [ultimate] (1). Richard Zetterberg <richard.zetterberg@example.com> gpg>

We then save our changes:

gpg> quit Save changes? (y/N) y

Now when listing keys we will see our primary key pair and 3 subkey pairs:

$ gpg2 --list-keys /home/me/.gnupg/pubring.kbx ---------------------------- pub rsa4096 2017-09-17 [C] [expires: 2018-09-17] FAB89F7D27C399063F600B036B3D0050CAE0C3C4 uid [ultimate] Richard Zetterberg <richard.zetterberg@example.com> sub rsa4096 2017-09-17 [S] [expires: 2018-09-17] sub rsa4096 2017-09-17 [E] [expires: 2018-09-17] sub rsa4096 2017-09-17 [A] [expires: 2018-09-17]