GPG Keys With Curve Ed25519

17 minute read Published:


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

My primary motivation for setting up GPG is to use it with Pass: The Standard Unix Password Manager. Each password is stored as an encrypted file in a git repository. I have to say, it has been awesome to use pass for storage and retrieval of passwords, especially those I need beyond the Firefox ‘Logins and Passwords’ utility. This guide will ensure that you are ready to start encrypting with your own signature GPG keyring.

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

But first, some background info…

Open Source GPG/GnuPG (Gnu Privacy Guard) and it’s proprietary pal PGP (Pretty Good Privacy) can be called upon to encrypt everything from email, passwords, single files, storage partitions as well as replacing ssh-keys (more on that in a follow-up tutorial).

“I generally sign (encrypt) 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

In addition, GPG has gained traction as a way to up your game for 2FA (two factor authentication) when used in conjunction with a physical cryptographic card and card reader or a USB device such as a Yubikey.

2FA 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 sent 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


As of 2020, most smart-devices and web-services still only support the 2048 and 4096-bit RSA cyphers. This is not ideal; RSA is not nearly as secure, is bloated and slow compared to Curve Ed22519 (algorithm based on elliptic curves).

The best approach is to use the more efficient ECC cypher for generating your primary certification key (offline), then to use that key to generate an RSA subkey for common encryption tasks.

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.

Though I prefer entering commands in the terminal, there are graphical clients for Windows, Mac and Linux.

With KGpg for example, follow the dialog to generate your key, mail it to your friends and ask them to do the same and import their public keys. Finally, to send an encrypted message, type it in the GPG editor, then click "encrypt". Choose your friend's key and click "encrypt" again. The message will be encrypted, ready to be sent by email.

GnuPG supports having multiple encryption subkeys on a keyring: if one algorithm is unsupported (e.g. the older GnuPG version 1.4 doesn’t support ECC), it will fall back to a supported algorithm. The subkeys, one each for authentication, encryption and signing, will be protected by a second, pseudo passphrase (something easier to type) for everyday use, while the original key is secreted away on an encrypted volume, probably with a unconscionably strong password.

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.

This may not the best solution for everyone; the key is there in perpetuity and what checks are there that it was placed there by the owner? 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.

I’ll be keeping things simple (“as simple as possible”); generating keys (offline with Tails OS), storing the secret part on a LUKS-encrypted disk with an interminably long passhrase.

The private key is locked away for safe-keeping. It is generally only required when you want to edit the keys ie. create other (temporary) subkeys, unencrypt a special file, alter the expiry dates of your subkeys or access your revocation certificate (used in case of a compromised key). The secret key is useless without the passphrase that protects it.

The passphrase is the secret sauce that flavors the three-course-meal of encryption. Never divulge it to anyone except perhaps in your final will and testament.

An optional step is to use the Tails Os to generate the keys securely offline. Once generated, operations carried out with your master key need never be connected to a network. Tails OS on a USB stick can serve as a complete portable operating system in your pocket.


If using Tails: prepare your USB (plenty of guides online). To boot from Tails, you change the boot order in your computer’s BIOS. Just after startup with your Tails USB plugged in, press either <ESC>, <F2> or <F12> to enter the BIOS settings in order to change the boot order. Find the boot options in the menu and drag the USB to the top of the list. <F10> to save and exit your preferences.

A portable USB is useful when out and about, at a Public Library for instance. Many USB distros have the option to load the entire operating system into the ram of the host machine.

You can set up a LUKS-encrypted volume in the startup wizard. Tails comes with gnome-disks installed, useful for creating encrypted partitions on a couple of other USB devices to store your ~/.gnupg backups. Your PC will now boot from Tails whenever the USB is plugged in.

Objectives and Steps:

  • Create a master key to certify subkeys; one subkey per capability.
  • Long expiry for master. Short validity for subkey (can change expiration date later).
  • Generate a revocation certification and store it separately in case a key becomes compromised
  • Make backups of the private key.

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

Think long-term for your master key: 50 years or your life expectancy. Keep your subkeys 2-5 years to ensure that package signing, certificates and related processes stay up-to-date and don’t get stale.

The steps are outlined below.
Expand to show/hide
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!

Backups

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 will result in restrictive permissions for the backup.) 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.

Remove private key and revocation cert from your laptop

If you have generated the keys on your laptop and are using GnuPG 2.1 or later, all you have to do is to delete the file $HOME/.gnupg/private-keys-v1.d/KEYGRIP.key, where KEYGRIP is the “keygrip” of the master key which can be found by running

$ gpg2 --with-keygrip --list-key YOURMASTERKEYID

This command lists one keygrip pair for the master key, one for each subkey, and one for the revokation certificate. Make sure the secret key material is missing which should mark the missing material with a sec# instead of just sec by running:

$ gpg2 --list-secret-keys

Even though the master key is now safe from being leaked or stolen, the subkeys are still in your home directory. Anyone who manages to get their hands on those will be able to decrypt your communication or fake your signatures (if they know the passphrase). Furthermore, 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). For the uber paranoid, wait for systemd-homed (should be included in the next systemd release) and configure it to encrypt your /home partition on (even on suspend) and/or let it handle your LUKS headers with access tied to a YubiKey or similar physical device.

Protecting your secret key

You can encrypt the private key using a password manager or with by running 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. You can store this key safely (even keep a printed copy). No one will be able to decrypt it unless they guess or discover the passphrase you picked.

Alternative ways of storing your secret key such as Paperkey, but I am wary of placing my master key next or near to a network printer even if it’s encrypted (shrugs).

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

Add faux passphase for your laptop keyring

Change the passphrase protecting the subkeys once you have removed the secret:

$ gpg2 --edit-key YOURMASTERKEYID passwd

This way if your everyday passphrase is compromised, the private master key will remain safe on the backup, It is protected by the original passphrase. Incidentally, for ideas on creating a memorable, high-entropy passphrase, look to a program like diceware or xkcdpass. Pro tip: run this command several times for inspiration

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

Export Public Key

This command will export an ascii armored version of the public key to a file that you can share with others:

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

Publish your public key to a keyserver

(if you choose to) This is the version of your key that you will email to friends and colleagues

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

Mount your key from the 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] 'Alice Engineer <allie@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] 'Alice Engineer <alice@example.org>'

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

Resources

https://phab.enlightenment.org/w/gnupg/

https://github.com/lfit/itpol/blob/master/protecting-code-integrity.md.


comments powered by Disqus