Generate GPG Keys With Curve Ed25519

18 minute read Published:

Table of Contents

Trust the developers, not the code hosting infrastructure. ~Linux Kernel Maintainers PGP Guide

Why GPG?

“The distinction between what is public and what is private is becoming more and more blurred with the increasing intrusiveness of the media and advances in electronic technology. While this distinction is always the outcome of continuous cultural negotiation, it continues to be critical, for where nothing is private, democracy becomes impossible.” ~ Privacy Conference, Social Research, New School University

Too often these days with technology, insecurity lurks in the shadows of complexity. Getting back to primary tools is useful for reconnection to self and to freedom of expression. Quality of life is in direct correlation to the artifacts at our disposal.

Open Source GPG/GnuPG (Gnu Privacy Guard) and it’s proprietary pal PGP (Pretty Good Privacy) can be called upon to encrypt email, passwords, files, storage tombs, logical volumes and partitions. Moreover, GPG is required to sign git commits in collaborative work situations.

“I generally sign all of my mails because I believe it’s important. More than once it helped to prevent identity theft with people using a ‘similar’ email address to mine.” ~Anonymous

My primary motivation for setting up GPG is for use with Pass: The Standard Unix Password Manager where each password or document is stored as an encrypted file. This guide will ensure that you are set up to encrypt, sign and authenticate with GPG.

Pass is awesome for storage and retrieval of passwords and account details. You can also obfuscate the directory structure and filenames of the password store with pass-tomb. Beyond pass, other password managers have their place, such as the Firefox ‘logins and passwords’ utility and bitwarden for syncing single-word passwords across web services.

Definition Of A Key

In public key cryptography, a key is actually a pair: a public key, and a private key. You use the private key to digitally sign files, and others use the public key to verify the signature. Or, others use the public key to encrypt something, for you to decrypt… subkeys can be revoked separately from master keys and also stored separately from them. Essentially, a separate key pair, but automatically associated with your main key pair. ~wiki.debian.org/Subkeys

GPG and 2FA

Two Factor Authentication provides that extra layer of security to login passwords, something the user has or is, not something the user knows. Typically this has meant a time-based one-time password (TOTP) via SMS, scanning a QR code, (better) app-based authentication (think Google Authenticator or Authy) or biometrics. However, SMS sends sensitive information over an unencrypted communications platform. Browser extensions and developer tools like webpack have also been used as attack vectors for compromising QR codes and pin numbers entered on a webpage.


Technically these methods could be called two-step authentication, because the second factor is supplied via the same method as the first factor. For example, even though the second factor may be generated by a mobile-based app, that one-time code needs to be entered into the same login page on a web site along with user’s password — meaning both the password and the one-time code can still be subverted by phishing, man-in-the-middle and credential replay attacks. ~krebonsecurity

GPG used in conjunction with a physical cryptographic card and card reader or a USB device such as a Yubikey has gained traction in recent years. If using a physical key, you may register a couple of these low-cost devices with each site in case of loss. For a flexible open source project that has brought together best practices of 2FA and GPG, see privacyIDEA Authentication System available in Gnu/Linux software repositories.

Why Ed25519?

As of 2021, many smart-devices and web-services still only support the 2048 and 4096-bit RSA cyphers. Bloated and slow, RSA is not nearly as secure as Curve Ed22519 (an algorithm based on elliptic curves). The solution is to use the more efficient ECC cypher for generating the primary certification key (offline), and use that key to generate RSA subkeys for common encryption tasks.

Besides working in the terminal, there are graphical clients for Windows, Mac and Linux. KGpg for example, will manage your keys and import friends public keys. It can generate your key if you don't have one. Mail it to your friends and ask them to do the same. To send an encrypted message; 1) Type it in the GPG editor 2) Click "encrypt" 3) Choose your friend's key and click "encrypt" again 4) The message will be encrypted, ready to be sent by email.

Subkeys

GnuPG supports having multiple encryption subkeys on a keyring for the purpose of authentication, encryption and signing. If one algorithm is unsupported (e.g. the older GnuPG version 1.4 doesn’t support ECC), it can fall back to another subkey with a supported algorithm. The original key is secreted away on an encrypted volume, with a interminably long passphrase. The subkeys will subsequently be protected by a second easier-to-type passphrase for everyday use.

The master key is dusted off every once in a while to:

  • alter the expiry dates of existing subkeys
  • create other subkeys as needed
  • possibly unencrypt a special file
  • access your revocation certificate (in case of a compromised key).

Even though the master key is now safe from being leaked or stolen, the subkeys are still in your home directory. If the passphrase is discovered, the perpetrator could decrypt your communication or fake your signatures. It’s worth repeating though that any key is useless without the passphrase that protects it.


The passphrase is the secret sauce that flavors the three-course-meal of encryption.

Formulating A Memorable, High-Entropy Passphrase

For creative ideas look to diceware or xkcdpass. Install xkcdpass and run the following command several times for inspiration. You’ll have fun!

$ xkcdpass --count=5 --acrostic='acronym'

Preliminaries

Make sure you’re using gpg v2

gpg2 --version | head -n1

and if you should happen to have both installed on your system

alias gpg=gpg2

Make backups of your existing GnuPG files ($HOME/.gnupg). Keep them safe. If something goes wrong during the following steps, you may need this to return to a known/good place.

umask 077; tar -cf $HOME/gnupg-backup.tar -C $HOME .gnupg

Note: umask 077 results in restrictive permissions for the backup.

Personally, I generated my keypair offline with Tails OS installed on a USB stick (See index below). This affords extra security features that some will consider nice to have. The master key need never be exposed to an internet-connected computer.

The Critical Path

  • Create a master key to certify subkeys; one subkey per capability.
  • Long expiry date for the master key; 50 years or your life expectancy.
  • Short validity for subkey: 2-5 years to ensure that package signing, certificates and related processes stay up-to-date and don’t get stale (expiration date can be changed later).
  • Generate a revocation certification, securely held in case a key becomes compromised.
  • Move the private key and revocation certificate and make backups.

The Steps

Expand for details
amnesia@amnesia:~$ gpg --full-gen-key --expert
gpg (GnuPG) 2.2.12; Copyright (C) 2018 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.

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)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
Your selection? 11

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Sign Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? s

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? q
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
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) 50y
Key expires at Tue 15 Apr 2070 0429 AM UTC
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: John Smith
Email address: jsmith@kmail.com
Comment:
You selected this USER-ID:
    "John Smith <jsmith@kmail.com>"

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.
gpg: key 0xC0A36B17811FFED4 marked as ultimately trusted
gpg: revocation certificate stored as '/home/amnesia/.gnupg/openpgp-revocs.d/C5246A0ADE20E283A90E382CC0A36B17811FFED4.rev'
public and secret key created and signed.

pub   ed25519/0xC0A36B17811FFED4 2020-04-27 [C] [expires: 2070-04-15]
      Key fingerprint = C524 6A0A DE20 E283 A90E  382C C0A3 6B17 811F FED4
uid                              John Smith <jsmith@kmail.com>

amnesia@amnesia:~$ gpg --expert --edit-key 0xC0A36B17811FFED4
gpg (GnuPG) 2.2.12; Copyright (C) 2018 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.

Secret key is available.

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2025-04-12
sec  ed25519/0xC0A36B17811FFED4
     created: 2020-04-27  expires: 2070-04-15  usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). John Smith <jsmith@kmail.com>


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? 11

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? q
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
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) 3y
Key expires at Thu 27 Apr 2023 0438 AM UTC
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  ed25519/0xC0A36B17811FFED4
     created: 2020-04-27  expires: 2070-04-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x28C194EDFDB41226
     created: 2020-04-27  expires: 2023-04-27  usage: E
ssb  ed25519/0xDB4C9A99430E61E6
     created: 2020-04-27  expires: 2023-04-27  usage: S
[ultimate] (1). John Smith <jsmith@kmail.com>

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? Q
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) 3y
Key expires at Thu 27 Apr 2023 0406 AM UTC
Is this correct? (y/N) y
Really create? (y/N) y
[master passphrase requested]
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  ed25519/0xC0A36B17811FFED4
     created: 2020-04-27  expires: 2070-04-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x28C194EDFDB41226
     created: 2020-04-27  expires: 2023-04-27  usage: E
[ultimate] (1). John Smith <jsmith@kmail.com>


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? 11

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? s

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions:

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? a

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Authenticate

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? q
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
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) 3y
Key expires at Thu 27 Apr 2023 0527 AM UTC
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  ed25519/0xC0A36B17811FFED4
     created: 2020-04-27  expires: 2070-04-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x28C194EDFDB41226
     created: 2020-04-27  expires: 2023-04-27  usage: E
ssb  ed25519/0xDB4C9A99430E61E6
     created: 2020-04-27  expires: 2023-04-27  usage: S
ssb  ed25519/0xCE658A723ED3DA27
     created: 2020-04-27  expires: 2023-04-27  usage: A
[ultimate] (1). John Smith <jsmith@kmail.com>

gpg> save

amnesia@amnesia:~$ gpg --output GPG-0xC0A36B17811FFED4.asc --gen-revoke 0xC0A36B17811FFED4

sec  ed25519/0xC0A36B17811FFED4 2020-04-27 John Smith <jsmith@kmail.com>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 0
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

Password Protect Secret Key

If you followed the steps, you are ready to encrypt the private/master key. Run the following command:

$ gpg2 --export-secret-key "your@email-address" -a | gpg2 --cipher-algorithm=AES128 --output secret-key.gpg -a --symmetric

You’ll get prompted for a passphrase and then secret-key.gpg will be created. This will export all necessary information to restore the secrets keys including the trust database information to secret-key.gpg. This is an additional step, in fact you could just backup the $HOME/.gnupg directory to a couple of encrypted tombs, USBs or partitions.

Optional: Store On Paper

For the ultimate archivist, there’s paperkey It reduces the size of the file by just crunching the secret part.

I’m personally wary of placing my master key next or near to a network printer, even if it’s been encrypted. ¯\(-,-)

Find the fingerprint of your key by doing:

$ gpg -K --with-keygrip

To make a paperkey backup, run the following command, replacing [fpr] with the full fingerprint of your key:

$ gpg2 --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt

Make Backups

Backup your secret-key.gpg and revocation certificate (GPG-0xC0A36B17811FFED4.asc in the above example) In fact, just backup ~/.gnupg. You will have to delete these two files local working ~/.gnupg directory. Set up a LUKS-encrypted volume or two where you can store backups. I used gnome-disks (conveniently packaged with Tails). Also look at tomb as an alternative safe storage method.

Remove Secret Key Keygrip

Obtain YOURMASTERKEYID by running

$ gpg -K --with-keygrip

The first line will resemble:

sec  ed25519/0xC0A36B17811FFED4 2021-03-13 [SC] [expires: 2065-04-12]
      Key fingerprint = 8F66 5A48 FC76 847E CCA5  9AAC 2FED 88C2 B6E3 04C5

In the above example YOURMASTERKEYID is C0A36B17811FFED4 (extracted from `sec ed25519/0xC0A36B17811FFED4 …)

The KEYGRIPS are identified by running:

$ gpg --with-keygrip --list-key YOURMASTERKEYID

Remove the relevant keygrip in $HOME/.gnupg/private-keys-v1.d/KEYGRIP.key for master and that of the revocation certificate if it exists.

You’ll know the master/secret key material is gone, if when you run:

$ gpg2 --list-secret-keys

The legend at the left of your master key will show sec# instead of sec if you have followed the steps correctly.

Create A Shorter Passphrase For The Subkeys

Once the secret has been removed, run:

$ gpg2 --edit-key YOURMASTERKEYID passwd

If your everyday passphrase is compromised you can revoke and recreate another set of subkeys; the private master remains protected by the original passphrase.

Existing Security Vulnerabilities

Each time a GnuPG operation is performed, the keys are loaded into system memory and can be stolen from there by sufficiently advanced malware (think Meltdown and Spectre). Even if stored on a LUKS encrypted disk, while the password-encrypted volume is unlocked and mounted, the operating system is able to access the private key contents. For the uber paranoid, configure systemd-homedit to encrypt your /home partition (even on suspend) and/or let it handle your LUKS headers with access tied to a YubiKey or similar physical device.

Export Public Key

This command will export an ascii-armored version of the public key to a file you can share with others online and upload to git servers such as Github, Gitlab, Gitea, or (decentralized) Radicle:

$ gpg2 --output public.pgp --armor --export username@email

Mount Key From Backup

When you need to use the master keys, mount the encrypted USB drive, and set the GNUPGHOME environment variable:

export GNUPGHOME=/media/something
$ gpg2 -K

or use the –homedir command-line argument:

$ gpg2 --homedir=/media/something -K

The latter command should now list your private key with sec and not sec#.

Add Relevant Identities

If you have multiple relevant email addresses (personal, work, open-source project, etc), you can add them to your master key. You don’t need to do this for any addresses that you don’t expect to use with PGP. The command is (put the full key fingerprint instead of [fpr]):

$ gpg2 --quick-add-uid [fpr] 'Bob Builder <bobb@example.net>'

You can review the UIDs you’ve already added using:

$ gpg2 --list-key [fpr] | grep ^uid

Pick the primary UID

GnuPG will make the latest UID you add as your primary UID, so if that is different from what you want, you should fix it back:

$ gpg2 --quick-set-primary-uid [fpr] 'Bob Builder <bobb@example.org>'

Optional: Publish Public Key To Keyserver

Many people choose to share their public key on a key-server. Your key is then discoverable by peers, helps to build a solid reputation and your work can be authenticated as your own. You still have to be mindful. The key is there in perpetuity and what checks are there that it was placed there by the owner? This version of your key can be emailed to friends and colleagues:

 $ gpg2 --keyserver hkp://pool.sks-keyservers.net --send-key YOURMASTERKEYID

Some people recommend keybase.io for distribution. However, that method tracks participation in various social and technical communities which may not be desirable for some use cases. For maximum flexibility, you can place your public key on a website that you control to be discoverable by peers and co-workers. The technically adept could try out the webkey discovery service.

Optional: Keyserver Cron Job

If you use a keyserver, you may want to set up a cron job to keep up-to-date with your co-workers keys. To generate the public key output suitable to paste in, just run:

$ gpg2 --export --armor [fpr]

Set up a refresh cronjob You will need to regularly refresh your keyring in order to get the latest changes on other people’s public keys. You can set up a cronjob to do that:

$ crontab -e

Add the following on a new line:

@daily /usr/bin/gpg2 --refresh >/dev/null 2>&1

Index

A Operating System on a USB thumb drive means you can carry your own computing environment to any computer at school, work or at the Library and doesn’t affect the host system in any way. Many portable Linux distributions can run within the ram of the host machine, only writing back files you want saved to the USB stick. There are several specialized distros; Sparky, Crunchbang++ or Linux Lite for example. Tails is a distro with an emphasis on security. Installing it, while slightly more involved, is very straightforward due to excellent documentation. Once installed, to boot from a USB, change the boot order in the host machine’s BIOS to boot from the USB whenever it is plugged in. As the computer boots up and with the USB plugged in, press either <ESC>, <F2> or <F12> to enter the BIOS settings. Find the boot options in the menu and drag your USB to the top of the list. <F10> to save your preferences and exit.

Resources

https://phab.enlightenment.org/w/gnupg/ https://github.com/lfit/itpol/blob/master/protecting-code-integrity.md.
https://unix.stackexchange.com/questions/481939/how-to-export-a-gpg-private-key-and-public-key-to-a-file

https://wiki.debian.org/Subkeys

comments powered by Disqus