Open source software security

GPG for Encryption and Digital Signing

30 November -0001
by Justin C. Klein Keane
November 25, 2007

GPG, the GNU version of PGP, is available for pretty much any platform. This free, open source encryption package can be used in a surprising number of ways. The program's utility and versatility make it a favorite among many security professionals.

Many people have a difficult time understanding how GPG (or PGP) works. The purpose of this article is to demonstrate how to generate a key pair and how to encrypt and decrypt files on a filesystem. Once you have GPG installed you can also use it to power email encryption plug in tools like Enigmail for Thunderbird.

You can download the Windows version of GPG from (). Most Linux distributions come with packages that include GPG or GNUPG. Once you have the program installed you're ready to go. On a Windows machine you may need to add the installation directory to your PATH variable.

To encrypt a file you first need to set up an identity. Doing this creates a public/private key pair which is used in encryption and decryption. To see if you have any identities set up you can use:

C:\Temp>gpg --list-keys
C:/Documents and Settings/jukeane/Application Data/gnupg\pubring.gpg
--------------------------------------------------------------------
pub   1024D/29B2D91C 2007-05-10
uid                  Justin C. Klein Keane (http://www.MadIrish.net) <justin@madirish.net>

As you can see I already have a key pair set up, but for the purposes of this article I'm going to go ahead and set up a new key pair to demonstrate how it is done. To begin use the command 'gpg --gen-key' and enter the data as you are prompted like so:

C:\Temp>gpg --gen-key
gpg (GnuPG) 1.4.7; Copyright (C) 2006 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.

Please select what kind of key you want:
   (1) DSA and Elgamal (default)
   (2) DSA (sign only)
   (5) RSA (sign only)
Your selection? 1
DSA keypair will have 1024 bits.
ELG-E keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 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) 1
Key expires at 11/27/07 13:56:58
Is this correct? (y/N) y

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: Tester Testing Key
Email address: test@madirish.net
Comment: This is just a key for testing
You selected this USER-ID:
    "Tester Testing Key (This is just a key for testing) <test@madirish.net>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

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.
+++++.++++++++++++++++++++.++++++++++..++++++++++.+++++..+++++.+++++.+++++.+++++
+++++++++++++++.++++++++++++++++++++.+++++++++++++++++++++++++>++++++++++.......
.............+++++
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 5EDCDE9A marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   4  signed:   7  trust: 0-, 0q, 0n, 0m, 0f, 4u
gpg: depth: 1  valid:   7  signed:   0  trust: 0-, 0q, 0n, 0m, 7f, 0u
gpg: next trustdb check due at 2007-11-27
pub   1024D/5EDCDE9A 2007-11-26 [expires: 2007-11-27]
      Key fingerprint = 8705 34D5 7B72 57C3 8E12  9061 B2C4 A0DF 5EDC DE9A
uid                  Tester Testing Key (This is just a key for testing) <test@madirish.net>
sub   2048g/2BB0FBFF 2007-11-26 [expires: 2007-11-27]

Note that I'm using a completely bogus e-mail address. It is important to use the correct e-mail address since the email address becomes the key for encryption and decryption. It is also important to note that I used a passphrase when creating this key. This passphrase is an important safeguard that we'll explore later on.

Now that we have our key pair let's create a bogus file that we'll encrypt and then decrypt.

C:\Temp>echo "Hello World!" > test.txt

C:\Temp>dir

 Directory of C:\Temp

11/26/2007  02:03 PM    <DIR>          .
11/26/2007  02:03 PM    <DIR>          ..
11/26/2007  02:03 PM                17 test.txt
               1 File(s)             17 bytes
 

Now we have a simple text file. The first thing we want to do is encrypt the file. To do this we need to tell GPG which identity (or key pair) to use. The encryption process uses the public key (a key pair contains two keys, a public key and a private key). This is specified by listing the "recipient" when we do the encryption. This is handy. If someone else had given us their public key we could encrypt a file with the other person listed as a recipient and then only that person would be able to decrypt the file. Let's start simple though and use the test key pair as the recipient:

C:\Temp>gpg -e -r test test.txt

C:\Temp>dir
 Volume in drive C has no label.

 Directory of C:\Temp

11/26/2007  02:08 PM    <DIR>          .
11/26/2007  02:08 PM    <DIR>          ..
11/26/2007  02:03 PM                17 test.txt
11/26/2007  02:08 PM               615 test.txt.gpg
               2 File(s)            632 bytes

As you can see the new cipher text file test.txt.gpg was created. If we look at the contents of this file we can see they're gibberish:

C:\Temp>type test.txt.gpg
???/u++v?k[](?LpW(Y-S%)?T1 @+OV+*F+k(O+n+9+umtE].!Qa;+6?
B_++?P+?+yEXP,G?.*a++e*GifU+T+_+u<_2s|__=?,uls+vlc)?
^?aL+a  v2=8M??+@+eJ-N+?{g"@+e+-nm+?F8-F?e\?p?jX?+
B?=#?mF(?dI?Jp"S+|S7??+Qft^P,+QXOvO"fK6e-)q++(8?R++
A?-y++??-$d>

Now, to recover the original version we have to posses the private key for the corresponding public key used to encrypt this file. For instance, if we encrypted the file using a public key that our friend John had given us, we wouldn't be able to decrypt the file unless we could somehow get a hold of John's secret key. For the keypair we just generated we have both the public and the private key though, so the decryption shouldn't be a problem. First we'll remove the file, then decrypt the cipher text using the '-d' flag in GPG:

C:\Temp>del test.txt

C:\Temp>gpg -d test.txt.gpg

You need a passphrase to unlock the secret key for
user: "Tester Testing Key (This is just a key for testing) <test@madirish.net>"
2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26 (main key ID 5EDCDE9A)

Enter passphrase: 

gpg: encrypted with 2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26
      "Tester Testing Key (This is just a key for testing) <test@madirish.net>"
"Hello World!"

Note that I had to enter the passphrase in order to decrypt the file, even though I have the secret key. You'll also notice that the file contents just printed out on the screen, which may or may not be useful. We can use the '-o' flag (for output) to output the decrypted cipher text into a new file:

C:\Temp>gpg -o test.txt -d test.txt.gpg

You need a passphrase to unlock the secret key for
user: "Tester Testing Key (This is just a key for testing) <test@madirish.net>"
2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26 (main key ID 5EDCDE9A)

gpg: encrypted with 2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26
      "Tester Testing Key (This is just a key for testing) <test@madirish.net>"

C:\Temp>dir
 Volume in drive C has no label.

 Directory of C:\Temp

11/26/2007  02:15 PM    <DIR>          .
11/26/2007  02:15 PM    <DIR>          ..
11/26/2007  02:15 PM                17 test.txt
11/26/2007  02:08 PM               615 test.txt.gpg
               2 File(s)            632 bytes

Now you know how to encrypt and decrypt a file. Let's say we want our friend John to encrypt a file for us though. Perhaps he has a secret sales report that he needs to email us, and we don't want that information being sent in clear test. What we have to do in this case is "export" our public key and get it to John. To do this use:

C:\Temp>gpg -a -o test.pub.key --export test

C:\Temp>type test.pub.key
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.7 (MingW32)

mQGiBEdLFvoRBAC3A3NUa7jmKgmZzkYHE1hbkOUD3y0ofmX768ctc0fdiTxkFmeZ
gL3Ds9/s3uSTCWx20LuCSi9FiUqvPExcI/dFE4OCbmkRmQgK7qD9PPod+sUqVBqJ
OnCKOJtMGAkCOeg+AomD9nhmMoZSDBmW7Ej2jN4IR1cxOqJ+rMehqfCLnwCgtMvw
9MbRMjMnsTUdqqh43BEqkbcD/1L57RRVcFzBoE2ZS/G5fW+HDFyXiTCKsFbi2IsO
Suh23AoJDc08FD2ZrbKrCVZfmncxMjdSp2qQOwKZ0kujO5fJehmbefSp8/PFwhAp
8MiqDBrbEAhUhiJy7spr3XRhCoALQAK6ZPR0lsRRjgNKxxuWkf9QfxImh3jZ12u7
bUvHA/4+vtmJ3WPRpjzSRwiaCJ7YKqqLV6e23le6ZXd1QsoF8EfesYxTBsQqSGRx
DnZaRywXWtGZqzR3XzBjP48E7onUMK7WEMqMbOZSBijK0lCAU5bJYn+9k0Q+/iSX
jLjerGOywzKbiIiezG6ofmTFeMGGaSF2ERFHZRnSCwp+SjdNMLRHVGVzdGVyIFRl
c3RpbmcgS2V5IChUaGlzIGlzIGp1c3QgYSBrZXkgZm9yIHRlc3RpbmcpIDx0ZXN0
QG1hZGlyaXNoLm5ldD6IZgQTEQIAJgUCR0sW+gIbAwUJAAFRgAYLCQgHAwIEFQII
AwQWAgMBAh4BAheAAAoJELLEoN9e3N6aqE4Anirj03I0y4iJ4MdTp7PtVMBMAag+
AJ0fg1ad3B7Wgde9uG0G5zGWYzBDzbkCDQRHSxb6EAgAjw2KHID/YJ7nKxljeg/P
Qr0Qamp/SVsCai1UbqDh39K6Ylq4mX8zGw05R5M51TKwazGpuDkeEwwj1O4xaMYE
9UkWfXRmFATOkMKNW5qvdWv/d7Gjjzj2nTSDMsm39pwX55oreuLjnyXkAiIJLqib
KAAIwffDze/R4PXPCDos/8OL0M5fvPcCmtOaHgcFwnJRJTXotMVKqJlUw+EGVEO3
UaEF+++N+jHYc/A1wgHl1MtccpQupok6AHwdYlhzWzU3FK5Y2fXH3RNuTwd+3rf6
3mCyr4ScE9qTiVrW9MvesnxlOqXvterFD/nUew/87ZDFx36kAEwrmB4pQBzu8fcl
zwADBQf/Z392pOqFP+7+dRO7SWpU0KewS6gbVQjh+6gQ5+Vr4bAoPExjPBDmr3Wk
1PL5uqfop65h4gI4YZXz33OxbVEDbOqnvf+Ws6VRenlAOlJKN/LZcHdqZkP3tH2g
MTDiK5sOXQZ9FfexeoyoSAoGo+5+YtPPWU1mr7IxB5lzldvrJh10Az3OjWhVnGe0
SCLKtYJrrN3xkvfqrEDMc+hBE+VK/LfoNnYPydPaxWM8a/Cha+n8pQ7V5iDu8FU6
K2N3+dyUXmUDho2kMekaxNT69nWnVuHNhPZxN2HdFS7OgozI9vnixbNBqqUYxjHn
BI+936/vEDiGI4h99OcWdZJPEXwslohPBBgRAgAPBQJHSxb6AhsMBQkAAVGAAAoJ
ELLEoN9e3N6atCgAn0b0rSIzJexiE6LHaElZmPChj4MfAJ9oiZG9n+Gv4Ifcne1z
p69s6HLxWg==
=uFbB
-----END PGP PUBLIC KEY BLOCK-----

Now, we can cut and paste this key block into the body of an e-mail and send it to John in the clear. The reason we can do this is because with the public key someone can *only* encrypt data that only we can decrypt. PGP encryption relies on a trap door function, meaning it is one way. Once someone encrypts something with a public key, the only way they can decrypt it is with the right private key and passphrase. John receives our public key, copy and pastes it into a text file named test.pub.key then imports it using:

C:\Temp>gpg --import test.pub.key
gpg: key 5EDCDE9A: "Tester Testing Key (This is just a key for testing) <test@madirish.net>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1

Now John can encrypt data and send it to us and only we can read it. This does however, bring up an interesting question. How do we know that documents we get from John were actually produced by John? Maybe someone else got a copy of our public key and is impersonating John.

GPG addresses this concern with the idea of digital signatures. A signature is produced by creating a hash, which is a small number generated based on the contents of a file. Each has is unique, so if a file changed, the hash wouldn't match. MD5 is one popular hashing algorithm. You could create a hash of a file, then compare the hash and the file. If the file or hash ever change then this comparison will fail. Digital signing works in much the same way except that after a hash of the file is produced this hash is modified with the private key of the signer. After this happens, anyone with the signer's public key can verify the digital signature. This will show two things - that the person who signed the file had the private key and passphrase of the key, and that the file has not been altered since it was signed. To demonstrate how this works we'll use our original test file with the text "Hello World!" in it:

C:\Temp>gpg -s test.txt

You need a passphrase to unlock the secret key for
user: "Tester Testing Key (This is just a key for testing) <test@madirish.net>"
2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26 (main key ID 5EDCDE9A)

Enter passphrase:

File `test.txt.gpg' exists. Overwrite? (y/N) N
Enter new filename: test.gpg.signed.txt
C:\Temp>gpg -b test.txt

You need a passphrase to unlock the secret key for
2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26 (main key ID 5EDCDE9A)

Enter passphrase:

C:\Temp>dir
 Volume in drive C has no label.

 Directory of C:\Temp

11/26/2007  02:38 PM    <DIR>          .
11/26/2007  02:38 PM    <DIR>          ..
11/26/2007  02:35 PM                15 test.txt
11/26/2007  02:38 PM                65 test.txt.sig
               2 File(s)             80 bytes
               2 Dir(s)   4,951,506,944 bytes free

C:\Temp>gpg --verify test.txt.sig test.txt
gpg: Signature made 11/26/07 14:38:09 using DSA key ID 2BB0FBFF
gpg: Good signature from "Tester Testing Key (This is just a key for testing) <test@madirish.net>"

Now, let's see what happens when I change the file a little bit.

C:\Temp>echo I'm a new line >> test.txt

C:\Temp>type test.txt
Hello World!
I'm a new line

C:\Temp>gpg --verify test.txt.sig test.txt
gpg: Signature made 11/26/07 14:38:09 using DSA key ID 2BB0FBFF
gpg: BAD signature from "Tester Testing Key (This is just a key for testing) <test@madirish.net>"

As you can see we can now verify that the file has been altered in some fashion. We can combine both digital signing and encryption in one fell swoop by first signing a file, then encrypting it. This way we have one encrypted file that contains cipher text, but that we can verify after decryption. I'm going to demonstrate this by encrypting a file for the test user but sign that file with my own GPG key:

C:\Temp>gpg -se -r test test.txt

You need a passphrase to unlock the secret key for
user: "Justin Klein Keane <jukeane@sas.upenn.edu>"
1024-bit DSA key, ID 6DB28E54, created 2006-06-02

C:\Temp>del test.txt

C:\Temp>dir
 Volume in drive C has no label.

 Directory of C:\Temp

11/26/2007  02:42 PM    <DIR>          .
11/26/2007  02:42 PM    <DIR>          ..
11/26/2007  02:42 PM               706 test.txt.gpg
               1 File(s)            706 bytes
               2 Dir(s)   4,951,502,848 bytes free

C:\Temp>gpg -d test.txt.gpg

You need a passphrase to unlock the secret key for
user: "Tester Testing Key (This is just a key for testing) <test@madirish.net>"
2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26 (main key ID 5EDCDE9A)

gpg: encrypted with 2048-bit ELG-E key, ID 2BB0FBFF, created 2007-11-26
      "Tester Testing Key (This is just a key for testing) <test@madirish.net>"
Hello World!
I'm a new line
gpg: Signature made 11/26/07 14:42:00 using DSA key ID 6DB28E54
gpg: Good signature from "Justin Klein Keane <jukeane@sas.upenn.edu>"

You can see I can decrypt this file *and* verify that it has not been tampered with or altered in any way.

There are many other uses of PGP but I hope this tutorial is enough to introduce you to the more common uses. GPG offers a powerful, yet simple, encryption tool that almost anyone can use. There are numerous graphical add-on's to GPG but understanding the command line use if very helpful as well.

For more information on GPG visit the official website at http://www.gnupg.org/.