Notes on GPG keys creation using GnuPG 2.2

Fri 27 October 2017

While issuing my last public GPG key I took some notes for future personal reference. I then decided to publish them here as many of the existing docs are outdated and not fully compatible with recent GnuPG versions.


Please be careful while following the instructions below. I took notes while doing the procedure myself and later put them together. They are verified, but they still may contain mistakes. Always verify the result of your commands.

In case of any error, just remember you can still revert to your old gpg setup by restoring the backup. This is true until you publish your new keys on public keyservers. Once messed-up keys are sent to a keyserver, your only option is to publicly revoke them. Hence, use caution.

It's up to you to secure your own setup and keys generation procedure. Some use ramdisks or more complex setups to export and store temporary files, others shred(1) data on disk... there is no limit to the paranoia you may apply. I won't cover these techniques here.

Generating the new keys

Please ensure you are using GnuPG version 2.2 (at least?).

I decided to have an off-line master key and two subkeys for everyday use. To be future-proof, I used 4096 bit RSA for the primary key and 3072 bit for the two RSA subkeys (one sign only and one encrypt only). New elliptic curves algorithms seems good, but currently it seems they are not well supported as RSA is. Please see the references below for more details and insights.

Let's first backup the existing GnuPG setup. Then tell gpg you want to use SHA256 from now on.

$ umask 077
$ cd
$ tar -cf gpg-backup.tar .gnupg/
$ echo 'cert-digest-algo SHA256' >> ~/.gnupg/gpg.conf

Now, generate the primary key. I don't like the recent, simplified, --gen-key, so I used --full-gen-key.

$ gpg2 --full-gen-key

Then extract the new key ID (called $MASTER_KEY_ID from now on), edit such key with:

$ gpg2 --edit-key $MASTER_KEY_ID

and proceed to:

  • add secondary keys (using addkey) - one sign only and one encrypt only;
  • possibly add more UIDs (with adduid), if you have many;
  • set your primary uid (uid $uidnumber, then primary)
  • trust them;
  • sign the new key with your old, existing key;
  • save and exit.

Check that everything is all right:

$ gpg2 --list-keys $MASTER_KEY_ID

Backup the new keyring and remove the primary secret key

We can now proceed to backup the whole current GnuPG setup, and remove the secret part of the primary key from the PC. Mount an USB memory (let's assume in ~/usb_path) and issue:

$ cp -a ~/.gnupg ~/usb_path/gnupg-home-with-secret-key

Don't remove the USB pen for now, we'll use it again later.

To actually delete the secret part of the master key, we first need to extract the keygrip of such key:

$ KEYGRIP=$(gpg2 --with-keygrip --list-key $MASTER_KEY_ID | grep -m1 'Keygrip =' | awk '{print $3}')
$ rm .gnupg/private-keys-v1.d/$KEYGRIP.key

Done. Let's check the result.

$ gpg2 --list-secret-keys $MASTER_KEY_ID

You should see a sharp (#) in the first line of the output, indicating the secret part of the key is missing from the keyring. This is what we want.

Here is an example output:

samael@frogstar:~$ gpg2 --list-secret-keys $MASTER_KEY_ID
sec#  rsa4096 2017-09-28 [SC]
uid           [ultimate] Samuele S. Catusian (samael) <>
uid           [ultimate] Samuele S. Catusian (Cooperativa Secondo Principio) <>
uid           [ultimate] Samuele S. Catusian (Valis Engineering) <>
uid           [ultimate] Samuele S. Catusian (ISF-Pisa) <>
ssb   rsa3072 2017-09-28 [S]
ssb   rsa3072 2017-09-28 [E]


Now re-issue the same command using the GnuPG setup you previously backed-up on the USB pen, by specifing --homedir:.

$ gpg --homedir ~/usb_path/gnupg-home-with-secret-key --list-secret-keys $MASTER_KEY_ID

The output should be tha same as the previous command, but there must be no sharp on the first line.

If everything went good, unmount the USB pen, make at least a backup of it and store them in different safe places.

Change the password for subkeys

It's a good idea to have a different password for the subkeys. If it gets compromised, you can just use the primary key (which uses another passphrase) to revoke the affected subkeys and issue new ones (still preserving all the signatures!).

Let's change the password for the subkeys then:

$ gpg2 --edit-key $MASTER_KEY_ID passwd

Using the master secret key

What if you need to use your secret key?

Pick up your USB pen, mount it, and just remember to use the --homedir command.

Here is an example:

$ mount /dev/sdb1 ~/usb_path
$ gpg --homedir ~/usb_path/gnupg-home-with-secret-key --list-secret-keys
$ ...
$ umount ~/usb_path

Transition statement

If you have an old key you would probably want people who have signed it to also sign your new key.

For the sake of that you need to write a transition statement (here is the one I wrote), specifying the two key fingerprints, then sign it with both old and new keys:

$ vim transition-statement
$ gpg2 --clearsign -u $gpg_old_key -u $gpg_new_key transition-statement
$ gpg2 --verify transition-statement.asc

Now upload it somewhere and send it to all your signers. And remember to offer them a beer to encourage them to sign your keys again. :)

Print your secret key

It's always good to store a printed copy of the secret part of the primary key in a safe place. It may seem overly paranoid, but it's an extra safety that can save headaches, and paperkey(1) with an OCR come in really handy.

Install paperkey, mount the USB key with the secret primary key, then:

$ gpg2 --homedir ~/usb_path/gnupg-home-with-secret-key --export-secret-keys $MASTER_KEY_ID > ~/backup.secret
$ paperkey -v --output secret.txt --secret-key ~/backup.secret
$ a2ps -2 --no-header -o secret.txt
$ lp
$ rm secret.{ps,txt} backup.secret     # or use shred(1) if you're paranoid

Print QR codes of the secret key

I know there are many different software devoted to this, but they all seem a bit too handcrafted and they need too many dependencies for my taste. I deem it a trivial task and OTOH I fear they won't be alive as long as I want my keys to last, so I'd want to keep it simple.

I tried to put together the few commands needed for such job, but some steps turned out to be tricky and I eventually gave up.
First consideration is, the secret is too big in size for a single QR image, so it must be splitted. Not a big deal.
But then I didn't manage to restore the whole secret key from scanned QRs. I tried with different printers, scanners and webcams, several resolution settings, without luck. Then I decided it's not worth wasting more time.

Probably combining paperkey (which does a pretty good job in stripping unnecessary bits from the secret key), split and qrencode, smaller QR images can be generated. Then they should be easier to scan and recostruct. Someone also told me to try with a smartphone camera app, which seems to be a lot smarter with QR codes than scanners and PC webcams.

I don't have time to try further, thus I'm saving here the commands I used to generate QRs, just in case one day I'll decide to try again, or someone else will.

$ gpg2 --homedir ~/usb_path/gnupg-home-with-secret-key -a --export-secret-keys $MASTER_KEY_ID > gpg-armored-secret-keys
$ split -d -C 2500 gpg-armored-secret-keys gpg-armored-secret-keys-splitted-
$ for split in gpg-armored-secret-keys-splitted-* ; do cat $split | qrencode -o ${split}-qr.png ; done

If someone manages to restore the whole secret key just using zbarimg or zbarcam, please let me know how you did it!