This article describes how I bootstrap my personal GPG keys. Extra security measurements can be taken when using GPG keys for mission-critical purposes such as initializing HashiCorp Vault KMS.
- GnuPG 2.0.x
- 1 USB key (or CD/DVD) for the OS (preferably a write-protected USB key like this)
- 2 USB keys or more for backing up the generated GPG keys
- 1 USB key to transfer the subkeys into day-to-day machines
Ideally, the whole key generation process should be performed on a completely offline machine booting a Live CD version of an open-source OS. One of the example documents of this practice can be found here.
Having said that, however, computer systems are complex. Even if we trust an open-source OS, we can only have limited confidence in the underlying hardware. There are some attempts at gaining more trust on the assembling process and the firmware. Even then, we still don’t have a clear picture of what is underneath. I won’t go any further on this topic, but keep that in mind.
Personally, I use CentOS on a “normal” laptop and I think it is good enough in my case. And just to be on the safe side, I disable all the network interfaces and remove the SSD. Tails is a nice Linux distro for security and privacy but it has some drawbacks: secure boot is not well supported (yet?) and it comes with modern (2.1.x) GPG (I’ll explain later). CentOS 7 LiveGNOME, however, supports secure boot out-of-the-box and has the right stable (2.0.x) GPG.
The first step is obtaining and verifying the CentOS 7 LiveGNOME ISO file, putting it into a (non-writable) bootable media and booting the system. While verifying the ISO file, you will notice that we have a chicken-and-egg problem: we need a trusted machine with GPG installed! That is another problem you have to think of if you plan to generate GPG keys for mission-critical purposes.
In this section, I will show you how to generate a GPG master key and several subkeys. The master key is kept completely offine and is only used to certify the subkeys. Each of the subkeys only serves one purpose: encrypt, sign or authentication.
First of all, there are some changes and some “features” (1, 2, 3, 4) in GnuPG 2.1.x that make it unreliable. As I mentioned above, CentOS 7 LiveGNOME comes with GPG 2.0.x, which is perfect for this task. You can use any open-source OS you like, just make sure that it has GPG 2.0.x installed.
By default, the String-to-Key (S2K) function is used to derive a key from the passphrase. That key is used to encrypt your GPG private keys at rest. From the GnuPG man page:
--s2k-cipher-algo name Use name as the cipher algorithm used to protect secret keys. The defau- lt cipher is AES128. This cipher is also used for conventional encrypti- on if --personal-cipher-preferences and --cipher-algo is not given. --s2k-digest-algo name Use name as the digest algorithm used to mangle the passphrases. The de- fault algorithm is SHA-1. --s2k-mode n Selects how passphrases are mangled. If n is 0 a plain passphrase (whic- h is not recommended) will be used, a 1 adds a salt to the passphrase a- nd a 3 (the default) iterates the whole process a number of times (see --s2k-count). Unless --rfc1991 is used, this mode is also used for conv- entional encryption. --s2k-count n Specify how many times the passphrase mangling is repeated. This value may range between 1024 and 65011712 inclusive. The default is inquired from gpg-agent. Note that not all values in the 1024-65011712 range are legal and if an illegal value is selected, GnuPG will round up to the nearest legal value. This option is only meaningful if --s2k-mode is 3.
3, which is Iterated and Salted S2K. The default cipher and digest algorithms are
SHA1, respectively. I prefer to use these values instead:
--s2k-cipher-algo AES256 --s2k-digest-algo SHA512 --s2k-count 65011712
personal-digest-preferences can be changed to
SHA512 (however, it may not be compatible with other software) Those parameters are used when encrypting or signing with your GPG keys.
Generating the Master Key
Some OSes have both versions of GPG:
gpg for 1.x and
gpg2 for 2.x. Again, make sure that you use the correct 2.0.x version. Here are the steps to generate a new GPG master key:
- Open terminal
VALID_FOR, etc. to the correct ones:
Generating the Subkeys
The string after
echo contains the answers that you would normally input when creating subkeys manually. For example:
gpg --expert --edit-key "$EMAIL" gpg> addkey Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) (10) ECC (sign only) (11) ECC (set your own capabilities) (12) ECC (encrypt only) (13) Existing key Your selection? 8 Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Sign Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? s Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? e Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? a Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Authenticate (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? q RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 1y Key expires at Fri 10 Aug 2018 10:32:24 PM EDT Is this correct? (y/N) y Really create? (y/N) y 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. sec rsa4096/0x608641233323A2E0 created: 2017-08-11 expires: 2020-08-10 usage: SC trust: ultimate validity: ultimate ssb rsa4096/0xB0119B677632552F created: 2017-08-11 expires: 2018-08-11 usage: E ssb rsa4096/0x0C756A11735E30D9 created: 2017-08-11 expires: 2018-08-11 usage: S ssb rsa4096/0x27D24F72AC456F15 created: 2017-08-11 expires: 2018-08-11 usage: A [ultimate] (1). John Doe <[email protected]>
Plug in one of the backup USB keys and change the current directory to its root. Then generate the revocation certificate:
You can see what hash algorithm is used by the
digest algo 10 means
After that backup your keys:
gpg folder in
/tmp should also be copied to the USB key. The same steps should be performed to backup the GPG keys to the remaining USB keys. Those USB keys should be kept completely offline at separate locations.
Plug in the USB used for transferring the subkeys to day-to-day machines and export the subkey:
The subkeys can be imported into the GPG keyring on your day-to-day machines:
Listing your freshly generated keys in the GPG keyring:
You’ll notice something like
sec# rsa4096/..., the
# means the private key of the master key is not present on the machine.
To change the algorithms of your existing GPG keys, a changing passphrase operation needs to be performed, even if the same old passphrase is re-used:
To find out which algorithms are currently used to protect your GPG keys (won’t work with “modern” (2.1.x) GPG):
algo: 9 means
hash: 10 means