# Generating GPG Keys

# Prerequisites

Check that GnuPG is correctly installed

gpg --version

If its not installed, which unlikely for any Linux distributions, you can run the following:

sudo apt update
sudo apt install gnupg

Or for those on Mac OS X (assuming you have Homebrew installed):

brew install gpg

# Initialising configuration files

GnuPG can be optionally configured using the gpg.conf file, which is to be created on ~/.gnupg/. The motivation behind these set of configurations are a result of adopting best practices relevant to using GnuPG. For more information, you can explore this site to learn more about the best practices. As for the configuration files, they will follow this configuration (do note that some of these options have already been deprecated).

Download the configuration file and save it as gpg.conf

curl https://raw.githubusercontent.com/ioerror/duraconf/master/configs/gnupg/gpg.conf > gpg.conf

Note: Do this step on another computer before you move on to the next step, where you will generate the keys on an airgapped computer. Once the file is generated, transfer the file securely to the airgapped computer's ~/.gnupg/ directory

Refresh with new configuration

gpg-connect-agent reloadagent /bye

# Generating Master Key

The informative overview of GnuPG and the recommended master-sub key structure can be found here on Debian's wiki. To be absolutely safe, please make this is being done on an airgapped machine, e.g. Debian Live image without internet access.

To generate a set of master keys:

gpg --expert --full-gen-key

Follow these steps:

  • Choose (8) RSA (set your own capabilities)
  • Toggle S, E, and make sure that the key is only able to Certify
  • Choose 4096
  • Choose 0

Note: The GPG keys are set not to expire because key renewals are very irritating to me, and it doesn't add much security. It is more important to secure the master.key at the get-go, and more even more important to (separately) backup the revocation.key to ensure a compromised key can be invalidated. For more information regarding this, refer to this answer on StackExchange

To show the public key generated:

gpg -k

And to show private key:

gpg -K

# Generating Sub Keys

Next, 3 subkeys will be generated, each with their own specific function of Sign, Encrypt, and Authenticate. Repeat the following steps for each of the there keys

Access the gpg interface

gpg --expert --edit-key $KEYID

Invoke the addkey command

addkey

Follow these steps (for each of Sign, Encrypt, and Authenticate subkeys):

  • Choose (8) RSA (set your own capabilities)
  • Toggle S, E, A options accordingly to achieve 3 keys with separate functions
  • Choose 4096
  • Choose 1y

Verify the 3 keys have been correctly created

list

Save changes

save

# Backing up keys

Save the following keys to an encrypted USB flash drive, to be used ONLY on an airgapped computer.

Change directory to the USB drive or backup path

KEYID=[YOUR_KEY_ID]
mkdir $KEYID

Backup public key

gpg --armor --export > $KEYID/public.asc

Backup secret key

gpg --armor --export-secret-keys > $KEYID/secret.asc

Backup 'laptop' key

gpg --armor --export-secret-subkeys > $KEYID/laptop.asc

Backup ownertrust

gpg --armor --export-ownertrust > $KEYID/ownertrust.txt

Backup pre-generated revocation certificate

cp ~/.gnupg/openpgp-revocs.d/*.rev $KEYID/

(Optional) Generate & backup additional revocation certificates

gpg --armor --gen-revoke $KEYID > $KEYID/revoke.rev

(Optional) If you want, you may want to compress these into a file.

tar cvf $KEYID.tar $KEYID/

Saves these files securely

# Uploading public key

If you are ready, and you deem that uploading your key to a public keyserver is appropriate, you may run the following command. Do take note that any information pushed to a public SKS/PGP keyserver is strictly uneditable/unremovable.

Upload to pgp.mit.edu keyserver

gpg --keyserver hkps://pgp.mit.edu --send-key $KEYID

# Transfer keys to OpenPGP/Yubikey

This step requires first setting up the key, then transferring the keys to the yubikey. Make sure this step is also done on an airgapped machine

Install scdaemon

sudo apt update
sudo apt install scdaemon

Show card status

gpg --card-status

Import secret keys if its not currently on the airgapped machine

gpg --import secret.asc
gpg --import-ownertrust trust.asc

# Initialisation of OpenPGP Card

Setup card

gpg --edit-card

Set custom passwords

admin
passwd

1
123456
<DESIRED PASSWORD>

3
12345678
<DESIRED ADMIN PIN>

q

Fill in other information

name
<FULL NAME>

url
hkps://pgp.mit.edu

login
<LOGIN NAME>

list

q

# Transfer Signing, Encrypting, and Authentication Keys to card

Access the gpg interface

gpg --expert --edit-key $KEYID
toggle

Transfer S key

key 1
keytocard
1

Transfer E key

key 1
key 2
keytocard
1

Transfer A key

key 2
key 3
keytocard
1

Save changes

save

# Delete all keys

Once you are done, you make remove the keys and destroy the live image.

Delete secret keys

gpg --delete-secret-keys $KEYID

Delete public keys

gpg --delete-keys $KEYID

# Using OpenPGP/Yubikey on a new computer

Verify that no keys exist on the machine

gpg -k
gpg -K

Import public key from SKS/PGP Keyserver

gpg --keyserver hkps://pgp.mit.edu --recv-key $KEYID

[Optional] You can also import the key from public.asc

gpg --import public.asc

Copy key stubs to local machine

gpg --card-status

Set trust level of key

gpg --edit-key $KEYID
trust
5
Y
save

# Use OpenPGP/Yubikey to encrypt and decrypt files

To encrypt

echo 'Hello World!' > test
gpg -s -e test

To decrypt

gpg -d test.gpg

# See Also

  • https://ocramius.github.io/blog/yubikey-for-ssh-gpg-git-and-local-login/
  • https://www.inovex.de/blog/openpgp-create-a-new-gnupg-key-1/
  • https://blog.eleven-labs.com/en/openpgp-almost-perfect-key-pair-part-1/
  • https://blog.tinned-software.net/create-gnupg-key-with-sub-keys-to-sign-encrypt-authenticate/
  • https://spin.atomicobject.com/2013/11/24/secure-gpg-keys-guide/