Generate a PGP key

There are thousands of web pages out there which explain how to generate a PGP key, in varying levels of detail. I'm not going to go into too much detail about how to do it, but I will briefly cover a few ways here - three methods use the command line, and one uses a GUI (which, to be honest, I don't recommend - at least not for creating keys.)

Passphrases

When you create a PGP key (or subkey), you will be asked to create a passphrase. This passphrase is used to encrypt the secret key, within the keychain files on disk. Using a strong passphrase means that if somebody manages to steal a copy of the keychain files from your workstation, the passphrase is the only thing keeping them from having access to your secret keys.

In this case, you may think that it's okay to use a weak (or no) passphrase, since the secret keys will only ever exist "on disk" within a Tails Persistent Storage partition. Resist that temptation. Having a passphrase on the secret key, plus the LUKS encryption of Tails Persistent Storage, is more secure than either one by itself.

Also, when you're creating sub-keys, it is possible to give sub-keys different passphrases than the primary key. This is a BAD IDEA™️, because the interface which asks you to enter passphrases doesn't do a very good job of explaining which passphrase (primary key, or which sub-key) it's looking for.

  • Using the same passphrase for the primary key and all subkeys will save yourself a lot of confusion.

  • When this is all done and you're using the YubiKey, you won't be entering this passphrase anyway - you'll be entering a PIN code for the YubiKey.

The KEYID shell variable

In the directions below, after generating a new key, there will be a step to save the Key ID in a shell variable. It will look something like this:

KEYID="xxxxxxxx"

This is because the directions in this book, after the key is generated, will use $KEYID to represent this value. If you save the Key ID to a variable like this, you will be able to literally type $KEYID where you see it in the commands, or you may be able to copy/paste the commands as-is. (Within the same shell where you saved the KEYID value, of course.)

The KEYID variable is not used or required by GnuPG, it's just something that I do when I'm working on keys to make my own life easier. There is no requirement to use this variable, I just find it saves some typing (or copy/pasting).

Command Line - "Quick" Options

The gpg command has options to generate keys and subkeys without being prompted. These options also allow you to specify an exact expiration date and time. (These are the options I normally use.)

Unlike the "normal" options, the quick options only generate one key or subkey at a time. This can be a bit more tedious, but it also makes it possible to build a PGP key exactly the way you want it.

Primary key

The gpg --quick-gen-key command will generate a new primary key with no subkeys.

amnesia@amnesia:~$ gpg --quick-gen-key 'Sample <please@dont-spam.us>' ed25519 cert 2024-01-01
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: key 0x5A6C4588132E97A6 marked as ultimately trusted
gpg: revocation certificate stored as '/home/amnesia/.gnupg/openpgp-revocs.d/2A9E767BA8BDE849331B40645A6C4588132E97A6.rev'
public and secret key created and signed.

pub   ed25519 2023-05-23 [C] [expires: 2024-01-01]
      2A9E767BA8BDE849331B40645A6C4588132E97A6
uid                      Sample <please@dont-spam.us>

amnesia@amnesia:~$

The "Key ID" is the "Key fingerprint" value, with no spaces. Save this to a shell variable, you will need it later in the directions.

KEYID="2A9E767BA8BDE849331B40645A6C4588132E97A6"

Also note the filename where the revocation certificate was stored, you will need it when you create backup files for the new key.

Signing subkey

On most "normal" PGP keys, the primary key has both [SC] flags, which means it can be used both for signing messages and certifying other PGP keys.

The command above used cert as the "usage" argument, so this primary key only has the [C] flag. This is because we are specifically creating a different subkey for signing messages, so we don't have to store the primary key on the YubiKey.

There are other advantages to creating a key this way, namely that if the signing key is compromised, we can revoke just that subkey and add a new one, without having to generate a whole new PGP key.

amnesia@amnesia:~$ gpg --quick-add-key $KEYID ed25519 sign 2024-01-01
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.
amnesia@amnesia:~$

As noted above, you should use the same passphrase here that you used for the primary key.

Encryption subkey

Then add the encryption subkey. Note that ed25519 keys cannot be used for encryption, so I'm using rsa4096 instead.

amnesia@amnesia:~$ gpg --quick-add-key $KEYID ed25519 encr 2024-01-01
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.
amnesia@amnesia:~$

As noted above, you should use the same passphrase here that you used for the primary key.

Command Line - Prompt for Everything

This command will prompt you for ALL options.

The only limitation is, you can't give it an explicit expiration date and time. You have to set the expiration date as "now plus something",

Example:

amnesia@amnesia:~$ gpg --full-gen-key
gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: keybox '/home/amnesia/.gnupg/pubring.kbx' created
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1

⚠️ The DSA algorithm is deprecated.

It is still being used, however it's being "phased out" and should not be used when creating new keys, unless you have a specific need to interact with systems using older versions of GnuPG or other PGP software.

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 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 Wed 22 May 2024 01:06:28 PM UTC
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.

Real name: Fake Name
Email address: please@dont-spam.us
Comment: sample
You selected this USER-ID:
    "Fake Name (sample) <please@dont-spam.us>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
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.

When it finishes generating the primary key, it will pop up a window asking for a passphrase.

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.

When it finishes generating the encryption subkey, it will pop up another window asking for a passphrase. As noted above, you should use the same passphrase here that you used for the primary key.

gpg: /home/amnesia/.gnupg/trustdb.gpg: trustdb created
gpg: key 5C0FA82B7673184B marked as ultimately trusted
gpg: directory '/home/amnesia/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/amnesia/.gnupg/openpgp-revocs.d/48C991CBCFFE74BC9216C57D5C0FA82B7673184B.rev'
public and secret key created and signed.

pub   rsa4096 2023-05-23 [SC] [expires: 2024-05-22]
      48C991CBCFFE74BC9216C57D5C0FA82B7673184B
uid                      Fake Name (sample) <please@dont-spam.us>
sub   rsa4096 2023-05-23 [E] [expires: 2024-05-22]

amnesia@amnesia:~$

This command's output already includes the full Key ID as a single value. This makes it easier to save the Key ID to a shell variable.

KEYID="48C991CBCFFE74BC9216C57D5C0FA82B7673184B"

Also make a note of the filename where the revocation certificate was stored, you will need it when you create backup files for the new key.

Command Line - Super Simple

This only prompts you for your name and email, then uses default values for the encryption algorithms, key sizes, and expiration date.

There's nothing really wrong with keys generated this way, I just prefer to have more control over the properties of the key itself.

gpg --gen-key

At the moment (2023-05-22, Tails 5.13) the default values are:

  • Primary key: RSA-3072 with [SC] flags
  • Subkey: RSA-3072 with [E] flag
  • Both keys expire "two years from now"

Save the Key ID to a shell variable.

KEYID="5619B048F0714513369541C3386766684B12A817"

Also note the filename where the revocation certificate was stored, you will need it when you create backup files for the new key.

Kleopatra

Tails comes with a very basic PGP keyring manager called Kleopatra. It can perform many of the basic operations, but it's ... limited. In particular, it doesn't offer a way to add subkeys after a key is created.

I strongly recommend using the command line to create a key pair, but if you really want to use it, you will find it on the menu here:

⇒ Applications → Accessories → Kleopatra

Menu

When you run Kleopatra, it will show you a list of the keys in your keyring. Tails starts off with several PGP keys used by the Tails project itself. You should not delete these.

Generate a new key

⇒ File → New Key Pair... (Ctrl+N)

Choose Format

  • Create a personal OpenPGP key pair

Enter Details

  • Enter your name and email

  • If you click the "Advanced Settings" button

    • You can choose the algorithm and (for RSA) key size. Default is RSA-3072.

      ⚠️ The DSA algorithm is deprecated.

      Do not use it when creating new keys.

    • You can choose the key's capabilities. Default is "everything other than authentication", which is fine.

      ⚠️ Do not turn on "Authentication" here.

      If you do this, the generated key will have the [A] flag on the primary key, which is ... less than ideal? You don't want to use the primary key for anything other than certifying other keys if you can help it.

      Also, the next page in this book shows you how to add an authentication subkey.

    • You can manually choose the expiration date. Default is "two years from now".

    • Click "OK"

  • Click "Next >".

Review Parameters

  • This will show you a brief summary of the key you're about to create.

  • If you turn on the "Show all details" checkbox, it will show you more details.

  • Click "Create"

Enter a passphrase for the key, and enter the same passphrase again to verify that you've typed it correctly.

Once it finishes generating the key, it will show a window with the new key's fingerprint, and offer buttons to make a backup (of just the secret key), send the public key via email, or upload the public key to a key server.

Created

Highlight and copy the KEYID value from this window, and then in a command line window, create a KEYID shell variable.

KEYID="xxxxxxxx"

Back in Kleopatra, click "Finish" when you're finished.

List the key

amnesia@amnesia:~$ gpg -k $KEYID
pub   ed25519 2023-05-23 [C] [expires: 2024-01-01]
      2A9E767BA8BDE849331B40645A6C4588132E97A6
uid           [ultimate] Sample <please@dont-spam.us>
sub   ed25519 2023-05-23 [S] [expires: 2024-01-01]
      76581737ABBD19552BFC7D8D91EF268465FA9390
sub   rsa4096 2023-05-23 [E] [expires: 2024-01-01]
      57DAE100A563EDF02E3C71EAB17819416F1A3202

amnesia@amnesia:~$