Learning to trust: a gpg primer

I’ve had brief encounters with gpg in the past, but never enough to warrant grokking the different types of things you can do with it. However, Stripe uses gpg enough internally that I figured it was time to actually learn how this thing worked.

The crypto concepts overall aren’t that new - you have a public/private keypair, that you can use to encrypt or sign messages to others. The main point of interest with gpg is how its validation works, or how you determine that a key really belongs to a person.

In essence, gpg allows you to trust a given key’s owner at different levels, which reflect how willing you are to trust the signatures on other keys this person creates. It has no bearing on how much you trust signed or encrypted documents made by this person:

  • unknown - no idea how much trust you have in this person
  • none - don’t trust this person to sign keys at all
  • marginal - mostly trust this person to sign keys
  • full - completely trust this person to sign keys, their signature is as good as your own

gpg then allows you specify who a key must be signed by in order for it to be considered validated (i.e. it actually belongs to the person it purports to be owned by). By default, to be validated it must be:

  • signed by you,
  • signed by someone you fully trust, or
  • signed by at least three marginally trusted keys

It must also be less than five degrees of separation from your key. It’s also possible to tweak the settings on how far a key can be from you, or how many keys (both marginal and fully trusted) must sign it, based on your level of paranoia.

Below, I’ve included snippets for the things I most commonly want to do with gpg, grouped by the sort of thing I’m trying to achieve.

Signatures

gpg supports both inline signatures - the sort with a header, some plain text, then a jumble of signature data below, and detached signatures - where someone attaches a signature file in addition to the plaintext.

# Clear-signing a message inline
gpg --clearsign

# Verifying a clear-signed inline message
gpg --verify

# Clear-signing a message, with a detached signature
gpg --detach-sig --output doc.sig doc

# Verifying a clear-signed message, with a detached signature
gpg --verify doc.sig doc

Encryption

# Encrypting a message
gpg --encrypt --recipient first@example.com --recipient second@example.com --output doc.gpg doc

# Decrypting, and verifying, a message
gpg --decrypt --output doc doc.gpg

Creating a keypair

I’ve summarised the process of creating a keypair below, though the gpg manual page page for this is very helpful if you’re looking for more detail.

# To create a new keypair (the default options are probably what you want)
gpg --gen-key

# You should then create a revocation certificate, so that if the key is compromised it can
# be revoked
gpg --output revoke.asc --gen-revoke keyID

Note that gpg will automatically self-sign your new keypair, so that the public key is protected from tampering.

Signing a key

Once you’ve verified that a given key belongs to a given person, and that the person is who they say they are, you can sign their key with your own. This allows people who trust you to check other people’s identities, to trust this person’s.

You should not sign a key unless you are certain that the owner is who they say they are, and that the fingerprint of your copy of the key is the same as the owner’s.

# To edit the key
gpg --edit-key keyID

# This launches an 'interpreter', indicated by >
# First, get the key's fingerprint, and check that it matches the owner's
> fpr

# Then, you can sign the key
> sign

# And check that your signature is now listed on it
> check

Trusting an owner

If you trust a given key owner to sign keys, you can set the level of trust you have in their key.

# Start by editing their key in your own keyring
gpg --edit-key keyID

# Then, you can assign a level of trust using the trust command
> trust

Keyservers

Signing a key isn’t useful unless other people know that you have signed it. To do this, you can upload the new copy of the key, now with your signature on it, to a keyserver. This allows others to download the new copy of the key.

# To upload a key to a keyserver
gpg --keyserver keyserver.com --send-key keyID

# To download a key from a keyserver
gpg --keyserver keyserver.com --recv-key keyID

Manually distributing keys

If you don’t want to use a keyserver, you can also manually distribute keys by exporting them from gpg.

# To export an ASCII-armored (ascii encoded) public key
gpg --armor --export keyID --output key.gpg

# To import an ASCII-armored public key
gpg --import key.gpg