The following article is part of Diogo Peralta Cordeiro's Logbook.

GPG Primer

Published in 2021-06-25 by Diogo Peralta Cordeiro.

Configure the GnuPG and SSH agent

Create and Manage your GPG and SSH keys

Create a Master GPG key

This key will only have the capability to certify, therefore it:

For this key, the chosen elliptic curve was Curve25519 which offers 128 bits of security (251 bits key size) and is designed for use with the Elliptic-Curve Diffie-Hellman (ECDH) key agreement scheme. It’s one of the fastest ECC curves.

This key, being the primary one, won’t have an expiry period. Whoever has it can simply extend it. Revocation certificates are better suited for this purpose.

  % gpg --expert --full-generate-key
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
  (14) Existing key from card
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) 0
Key does not expire at all
Is this correct? (y/N) y

gpg: key 0x3B8BEF6A630AB45D marked as ultimately trusted

Identify your key

In my case, I have used my real full name, my primary email address, and an empty comment. But this article proposes some relevant points of reflection.

Subkeys

I have created three subkeys, one per action. You edit your key with: gpg --expert --edit-key $KEYID, where $KEYID in my case would be 0x3B8BEF6A630AB45D. Then gpg> addkey.

Now we have a key for (C)ertify, (S)ign, and (E)ncrypt). We can gpg> save.

Authenticate subkey

This one will be created differently, as we want to use it for SSH as well.

Let’s start by creating it:

ssh-keygen -t ed25519 -C "Real name <Email address>"

It’s important to use the same passphrase and identification details as with your GPG key.

ssh-add ~/.ssh/id_ed25519

# Now here is the keygrip:
ls -Art $(gpgconf --list-dirs homedir)/private-keys-v1.d | tail -n 1 | cut -f1 -d'.'

gpg --expert --edit-key $KEYID # Your gpg key
gpg> addkey
(13) Existing key
# Enter the keygrip, disable Sign, enable Authenticate, Q, 1y
# Finish with y, y, and
gpg> save

Verify

List the generated secret keys and verify the output with gpg --list-secret-keys --keyid-format LONG.

gpg --export $KEYID | hokey lint

hokey is part of hopenpgp-tools, the output will display any problems with your key in red text. If everything is green, your key passes each of the tests.

Revocation certificate

mkdir keys ; cd keys

gpg --output revoke.asc --gen-revoke $KEYID
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.

Backup

# GPG

## Secret Keys
gpg --output mastersub.key --armor --export-secret-keys $KEYID
gpg --output sub.key --armor --export-secret-subkeys $KEYID

## Public key
gpg --armor --export $KEYID > public.asc

## Trust levels
gpg --export-ownertrust > trustlevel.txt

# SSH
cp ~/.ssh/id_ed25519 id_ed25519
cp ~/.ssh/id_ed25519.pub id_ed25519.pub

Restore backup with:

# GPG
gpg --import mastersub.key
gpg --import-ownertrust < trustlevel.txt

# SSH
cp id_ed25519 ~/.ssh/id_ed25519
cp id_ed25519.pub ~/.ssh/id_ed25519.pub

How to use GPG and SSH

Renewing your keys

When your subkeys expire, you can simply:

gpg --list-keys
gpg --edit-key (key id)
gpg> key {1..3} # 0 would be the primary key
gpg> expire
(follow prompts)
gpg> save

Now you’d export the public key and republish.

GPG Sign

Sign a file

gpg --output doc.sig --sign doc.ext

Also, to make Git sign your commits automatically, set this setting.

Verify a file’s signature

curl -sSL https://www.diogo.site/public.asc | gpg --import -
gpg --verify "doc.sig" "doc.ext"

GPG Encrypt

SSH Authenticate

To copy your ssh public key to a remote server do ssh-copy-id username@remote_host.

Signing someone’s GPG key

For the sake of web of trust, you’ll want to have your peers sign your key and vice versa.

Suppose you want to sign my key:

# Import
wget https://www.diogo.site/public.asc
gpg --import public.asc

# Sign
gpg --sign-key 3B8BEF6A630AB45D

# Export it and encrypt with my public key
gpg -a --export 3B8BEF6A630AB45D | gpg -se -r 3B8BEF6A630AB45D > ~/tmp/3B8BEF6A630AB45D.asc.gpg

# Now you email me this file

Once I receive it, I can decrypt and import:

gpg --decrypt 3B8BEF6A630AB45D.asc.gpg
gpg --import 3B8BEF6A630AB45D.asc

And now I can export it and publish it on my website.

References

I wrote this primer based on the following references, which I recommend to approach this matter with greater depth: