An introduction to GPG / PGP

7 minute read

Pretty Good Privacy is an cryptograhic standard, used for encryption, decryption, verification and signing of various medias. The application ranges from e-mails and files, to whole disk partitions and directories.

GNU Privacy Guard is an open source application of the PGP standard, with various frontends supported. It it widely used for a variety of use cases, namely verifying file integrity from the www, encrypting e-mails, and proving identities. It relies on public-key cryptography for the encryption, meaning generating a key, actually consists of a key-pair, one being secret, the other being public.

Using GPG

Generating Keys

Generate a key:

 gpg --full-generate-key

This will run your through a guided key generation, where you can choose key-type, key-size, expiration date, passphrase, and identity to attach it to.

We can now verify that we have generated a new key, by listing the keys in our keyring:

Listing Keys

gpg --list-keys
gpg --list-secret-keys

As the identities of the public/private key pair are indifferent, the commands will give the same output, apart from the pub / sec indication in front of the ID. The commands will differ in output, when you import a public key, for which you do not have the secret key. The key format can also be changed using the --keyid-format={none|short|0xshort|long|0xlong}

Fingerprints

The long key IDs can be hard to read for humans, and thus we have fingerprints, which basically splits the ID up into bits of 4, making them easier to read.

This can be used to compare fingerprints, to ensure that the public key you have, actually belongs to the person you think - by comparing fingerprints.

gpg --fingerprint

Here I can see that my publickey, has the fingerprint 79D5 CEBF BA7D 36FC B136 611A 006D 4674 33D5 A927.

Importing Keys

Importing keys can be done by specifying the key, as a local file on the computer:

gpg --import some.key

Where some.key, can be either a public or secret key.

Importing can also be done directly, reading from stdin.

curl "https://t1ng.dk/006D467433D5A927.asc" | gpg --import

Should you already have imported the key, gpg will tell you so.

Exporting Keys

Again, we will view the ID's of our keys:

gpg --list-keys

Exporting can be done either with binary keyfiles or as ascii text, with the -a / --armor flag.

gpg --export <key ID> > public.key
gpg --export --armor <key ID> > publickey.asc

The latter of the commands will give is a human-readable file, beginning with -----BEGIN PGP PUBLIC KEY BLOCK-----, whereas the first will fill up less disk-space, but be binary.

The binary file, does not have any magic number attached to it, so it will look like raw data.

file public.key
public.key: data

Exporting keys, can also be done, specifying the identity it is attached to:

gpg --export --armor Tinggaard > publickey.asc
gpg --export --armor [email protected] > publickey.asc

The two commands will give the same output.

It is also possible to export a secret key.

gpg --export-secret-key --armor <key ID>

Deleting Keys

To delete a public key, use

gpg --delete-keys <key ID>

And to delete a secret key

gpg --delete-secret-keys <key ID>

Key Servers

Before we get to the more practical use cases of gpg, it is fundamental to know about keyrings, key servers, key signing and key trust.

Your keyring is the file stored on your computer, which holds all of your keys secret. To create an easier way to share keys, keyservers are here to help. A keyserver, is a server on the web, that stores keys from everyone who is willing to push them to said server. Likewise you can pull keys down from other people, assuming their keys are on the server.

Some of the most common key servers include:

  • keys.gnupg.net
  • keyserver.ubuntu.com
  • pgp.mit.edu

To push a key to a key server

gpg --keyserver keys.gnupg.net --send-keys <key ID>

And to recieve a key

gpg --keyserver keys.gnupg.net --recv-keys <key ID>

To update keys already pulled (in case they have have expired, or new subkeys added etc.) do

gpg --keyserver keys.gnupg.net --refresh-keys

Key Signning

To sign a key, means to assign some value to it, indicating how much you trust it.

It can be done like so

gpg --sign-key <key ID>

Encryption

To encrypt a message, we need the recipients public key in our keyring, otherwise gpg does not know how to encrypt the message.

The examples below requires that you have the public key of [email protected] in your keyring, furthermore if you have not selected your amount of trust in this key, gpg will warn you.

The command below will ascii encrypt message with [email protected]'s public key, and write the output to message.asc (default).

gpg --recipient [email protected] --encrypt --armor message

It is also possible to hide the identity of the recipient, meaning that the identity of the recipient is not included in the output. Decryption still works the same way, but just having the encrypted file, it is not possible to determine if you can decrypt it, because you do not know for whom it is addressed. This is done by replacing the -r / --recipient with -R / --hidden-recipient.

Signing

To sign a file, means that you encrypt it, using your own secret key, thus everyone can decrypt it with your public key, but knowing that it can only have originated from you.

There are various options for signing, including both signing and encrypting, resulting in a file encrypted for a specific recipient, signed by you.

It is also possible to change the secret key (not using the default key) used for the signing, using the -u / --local-user parameter.

  • -s / --sign allows you to do a basic signing of a message, indicating that you are the author.
  • --clearsign signins as ascii, (no --armor needed), and includes the original message as a header - as the data is not secret anyway, because everyone can read your public key.
  • -b / --detach-sign signs a message, but does not include the message itself, meaning it needs to already be present on your computer, before the verification can take place.

To sign message, outputting message.gpg

gpg --sign message

To clearsign message, using a key, yielding message.asc

gpg --clearsign --local-user <key ID> message

To detach sign message, yielding message.sig

gpg --detach-sign message

Decryption

To decrypt a message, naturally you have to have the secret key, pairing with the public key, used for the encryption, in your keyring. Or the public key, if the message is signed.

Decrypting can be done of both encrypted, signed, as well as encrypted AND signed messages.

gpg --decrypt message.gpg
  • Using -d / --decrypt on an encrypted message, yields the unencrypted message.
  • Using -d / --decrypt on a signed message, shows the author, as well as the original message.
  • Using -d / --decrypt on an encrypted, signed message shows the unencrypted message as well as the author.

Verifying

Verifying is only done on signatures, and does not show the do the decrypted message, but only verifies who the author of the message is.

To verify the authenticy of message, using the signature message.sig.

gpg --verify message.sig

This assumes you already have message in the same directory. However verifying can also be done of .asc and .gpg files created using --clearsign or --sign, which does not require the original message to be present.

If the filename is not exactly the same as the signature, apart from the .sig ending, gpg will fail. This can however be resolved, by specifying the file to verify as a second argument.

Assuming the file to verify is original and NOT message.

gpg --verify message.sig original

Symmetric Encryption

Symmetric Encryption does not require a public/private key pair, as the same key (password) is used for encryption and decryption. Instead the recipient and you, both need to know the password.

To symmetrically encrypt message to symmetric.asc use

gpg --symmetric --armor --output symmetric.asc message

gpg will then prompt you for a password to use for the encryption.

Abbreviations

Full command Shortened
--list-keys -k
--list-secret-keys -K
--armor -a
--output -o
--encrypt -e
--decrypt -d
--recipient -r
--hidden-recipient -R
--sign -s
--detach-sign -b
--local-user -u
--verbose -v

Examples

List public keys

gpg -k

Encrypt and armor message for [email protected].

gpg -ear [email protected] message

Sign and encrypt message for [email protected], and write it to sig_enc.gpg

gpg -seau <key ID> -r [email protected] -o sig_enc.gpg message

Detach-sign and armor message and write the output to signature.sig.

gpg -bao signature.sig message

And of course the infamous manual, or simply a quick search on the web.

man gpg