Working with GPG

The GNU Privacy Guard (GnuPG) is a free open source implementation of the OpenPGP standard. There is a good chance you already have the command line tool (gpg) installed, if not packages can be found on the GnuPG download page.

Symmetric encryption

A very simple way to encrypt data is with symmetric encryption, this can be done with the -c or --symmetric options:

$ echo 'secret data' > somefile.txt
$ gpg -c somefile.txt
Enter passphrase:
Repeat passphrase:

After a passphrase has been entered and verified GnuPG will encrypt the file and write the cipher text to an new file ending in .gpg:

$ file somefile.txt.gpg
somefile.txt.gpg: GPG symmetrically encrypted data (CAST5 cipher)

The data can then be decrypted with the same passphrase:

$ gpg somefile.txt.gpg
gpg: CAST5 encrypted data
Enter passphrase:
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected
$ cat somefile.txt
secret data

Asymmetric encryption

Generating a new key pair

If you want to use asymmetric encryption, the first thing you will need to do is generate a new key pair. This can be done with the --gen-key option:

$ gpg --gen-key
gpg (GnuPG) 1.4.19; Copyright (C) 2015 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.

When running the command you will be prompted for they kind of key(s) you want to create. For most people RSA should be fine (this is the algorithm recommended by RFC 4880):

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)
Your selection?

You will also be prompted for how long the key should be, by default 2048 should be fine. A rationale for this can be found on the GnuPG FAQ:

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits

You when then need to specify how long the key should be valid for:

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)

The user ID associated with the key:

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Example User
Email address: user@example.com
Comment:
You selected this USER-ID:
    "Example User <user@example.com>"

And finally a passphrase to encrypt the private key. There is no limit on passphrase length, and from a security perspective it's worth using a long passphrase, as it's the only protection you have if you're private key file is compromised:

You need a Passphrase to protect your secret key.

Enter passphrase:

If everything goes correctly your keys should now be saved to ~/.gnupg/:

$ ls -1 ~/.gnupg/
gpg.conf
pubring.gpg
pubring.gpg~
random_seed
secring.gpg
trustdb.gpg

You can also verify keys have been generated using the --list-keys option:

$ gpg --list-keys
/home/user/.gnupg/pubring.gpg
---------------------------------- 
pub   2048R/5B5D90CE 2017-08-10
uid                  Example User <user@example.com>
sub   2048R/8CE63902 2017-08-10

Revocation certificate

Although not strictly necessary, it's a good idea to pre-generate a revocation certificate. In the event that you're key pair is either lost or compromised the revocation certificate can be published to invalidate your public key. This can be done with a command similar to the following:

gpg --output revoke_key.asc --gen-revoke "Example User <user@example.com>"

Note: the generated certificate should be stored offline, not with your private key!

Exporting your public key

The --export option can be used to export your public key:

$ gpg --armor --export "Example User <user@example.com>"
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

mQENBFmMqM8BCADjLWp4UV0EUehp7S5lu2IEgupNsqgOvMognV0qu/8LIv7DVuMB
gOHjSgdHs6c4pdaO9OrK6idI26Wt3fH6JSDOJGL+V1qA8lXDTfO/7eOaFOC4NXEl
l3YUfEN+IXOoaHrjZa0V/+kINHVoHh6xqD2ISdZnS1g+N9wnnrbmRj4VIMbEzUvS
uEiCqihHgNbVslIv+Vp6OiWxs8HevNPEg94bbG/3nXlgn/hVx73wgY9MdNW8IIaO
//yuf2Jy6Gw61G8knlS6/VDLR4qSB+8vhwz55DXv4XDWtbZCmcyBed/YJ369TkG2
Tqk/0glThPN/gkC2RkKn+yc/6y5aCMIK+VaXABEBAAG0H0V4YW1wbGUgVXNlciA8
dXNlckBleGFtcGxlLmNvbT6JATgEEwECACIFAlmMqM8CGwMGCwkIBwMCBhUIAgkK
CwQWAgMBAh4BAheAAAoJEJ2xRpNbXZDO9Z0H/2ShTcTX9n+980xfAlD1S58DnoAI
vg9ihH+BuKq01102ToEmO9SEXWoLW7OaLUmewt+1nOTTcN45QqskT/qGNrb30TrA
fwbAeQ+5X1dUgKoPPFp5k/gRBAYN0QCVc1QQUEsqES/fHGZMQIsJGGtxqsiCECsQ
aQ/z52uIEFvVQ2FJFp/jvHNB0/wiaYToS/Sy+o5D4E4v+95wegZMtOactCOGwM98
DE/mdN9Oy9R7jonO4bYQPCMLAHufEsHcvpkXy9xFLg7O7RBpSteQSrL+qQP6kKIG
YimKkJlyYFzT9V069ndjkB3fYLECg73KKAQysUWGn4aZh21vPxcYSuLrKN+5AQ0E
WYyozwEIAOK17Vpm4AEWdtBgkNbLbX8LsI8pCMpC01UIfLEYoZc6POVXKU38VMTe
G28sBxu3wZmx3HtFyq4zMae4ju4kR5N7B3sMcjYtJ104+5TB44KjZ7eznDlZL0d3
flBZ1NC4iFhJMskkBlJywJ/CtOOmNvyc5EP6xGrejrqVjraFKO65dz46yN2sNL/D
FWeFUCieFf+F/jZe7SnCil6bnvBgn1WIQvSMeBTUQ31naVRXXsGu1lhWysPLJZke
SZmyQid+0hX9PVOAe/avV1SjOb2qz8fFhEHUXVatPYEVhJ1/JlIci7CjAnM9coFB
fp2N4T/omX9WpKytH7dcGy7upw1CABsAEQEAAYkBHwQYAQIACQUCWYyozwIbDAAK
CRCdsUaTW12QzsbyB/0fOWhYtUK7kzORGDcN55XO2NyGrcQAseLMs+sCm5/9UYTA
K3REhDQiw8dfYpmsyev5wRA+AGcwm+20Qtqd4ioFK7IOwHv7qaNhM1NmvCGjPqHH
zeTqSB3w2RioV4BQejAhP8Ni8vTLOAVLPEWuiHjFblU1cav/HsYDaMSRvB1ARbmq
Ll3k0j0/07zrzmJJsuHkchAdvIWWjU4n0X1iSNvyaja7OqbMue9qZ+lP2n7bISfM
jY2boP890FT/2cRlnSz53Wk7zZBXGg/kcPOdzZkNnVZ8C9+c99W7jtVp6CC3oQH9
Y3q/rcuuOmT7hVJKf0Icyt94ejxC/lb1isDR3OzZ
=mJc7
-----END PGP PUBLIC KEY BLOCK-----

Note: --armor is used to base64 encode the public key.

Your public key can be used by anybody to encrypt data, which you can then decrypt with the corresponding private key. There are a few different ways to distribute your public key:

  • Hand over the key in person
  • Publish the key on your website
  • Publish the key on a key distribution site such as keyserver.pgp.com

Importing public keys

To send encrypted messages to someone you first need to get a copy of their public key. The --import option can then be used to import the key:

$ gpg --import alice_example.com.key
gpg: key 4264D469: public key "Alice <alice@example.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

Encrypting and decrypting messages

Once you have a public key, you can use the --encrypt option to encrypt data:

$ echo 'secret message' > message.txt
$ gpg --output message.gpg --encrypt --recipient alice@example.com message.txt
$ file message.gpg
message.gpg: PGP RSA encrypted session key - keyid: 3E6EA063 270B658 RSA (Encrypt or Sign) 2048b .

The --decrypt option can then be used to decrypt the message with the corresponding private key:

$ gpg --output message.txt --decrypt message.gpg

You need a passphrase to unlock the secret key for
user: "Alice <alice@example.com>"
2048-bit RSA key, ID 58B67002, created 2017-08-11 (main key ID 4264D469)

gpg: encrypted with 2048-bit RSA key, ID 58B67002, created 2017-08-11
      "Alice <alice@example.com>"

$ cat message.txt
secret message

Signing messages and verifying the author

As well as encrypting messages and data, it's also useful to be able to verify a message was sent from the person you expect. This can be done by signing a file with the --sign option:

$ cat message.txt
This is Alice...

$ echo 'This is Alice...' > message.txt

$ gpg --armor --output message.txt.sig --sign message.txt

You need a passphrase to unlock the secret key for
user: "Alice <alice@example.com>"
2048-bit RSA key, ID 4264D469, created 2017-08-11

$ file message.txt.sig
message.txt.sig: PGP message Compressed Data (old)

The signed message can then be verified using the --verify option:

$ gpg --verify message.txt.sig
gpg: Signature made Fri, Aug 11, 2017  5:54:36 PM GMTDT using RSA key ID 4264D469
gpg: Good signature from "Alice <alice@example.com>"
Primary key fingerprint: D401 7604 FC42 9C4A C5A0  FD4D E94D B885 4264 D469

If the --verify option is omitted GnuPG will also extract the message after verifying the signature:

$ gpg message.txt.sig
gpg: Signature made Fri, Aug 11, 2017  5:54:36 PM GMTDT using RSA key ID 4264D469
gpg: Good signature from "Alice <alice@example.com>"
Primary key fingerprint: D401 7604 FC42 9C4A C5A0  FD4D E94D B885 4264 D469

$ cat message.txt
This is Alice...

Clear-text signatures

For plain text such as emails, it's often easier using the --clearsign option. If this option is used the message can easily be read, without first having to extract the message from the signed file:

$ gpg --clearsign message.txt

You need a passphrase to unlock the secret key for
user: "Example User <user@example.com>"
2048-bit RSA key, ID 5B5D90CE, created 2017-08-10

$ cat message.txt.asc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This message is signed, but can be read without the gpg command
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBAgAGBQJZjeeIAAoJEJ2xRpNbXZDODFUH/0eak3QYUNUoa8/OL32gfhhH
NZIT+82QXCXlXeE0Xilpjd7l4M9mZ6DbJaArwmjQVhp+XgHMELEo9gLChQF14Spi
MT7W7TJGEVWqqaugH4HmhP+Pt3t+HsrnX7jzsPN/XMIdcGn/Skg9gy5HHL8bRwrb
hykGcoUDE4GjQxF+BAL7K6xvA4SVvqLwVFhhg5ovuamR5SFnTFr+g8UBvDLCskOR
sJiGN7x/cHndd5yWdgZ0Q0iIyEUIwMsN5T0Yl5GiSt5lko8rFooMEcaUacDgewrF
VX+eiqsUeKwrXvRE4HhIuZTKh8bfbnqdhX4xZ5G/UOUIEgTZuZ7Ji2n1sgzclic=
=8yu8
-----END PGP SIGNATURE-----

Using a separate signature

Alternatively the --detacted option can be used to create the signature in a separate file:

$ gpg --armor --detach-sign data

You need a passphrase to unlock the secret key for
user: "Example User <user@example.com>"
2048-bit RSA key, ID 5B5D90CE, created 2017-08-10

$ ls -lh data data.asc
-rw-r--r-- 1 user 197121 10M Aug 11 18:16 data
-rw-r--r-- 1 user 197121 473 Aug 11 18:23 data.asc

This is particularly useful for large files such as ISOs.

Further reading

If you need more GnuPG information the GnuPG documentation is a good place to start.