Hacking Linux Exposed





previous article
next article
File and email encryption with GnuPG (PGP) part three
By Bri Hatch.

Summary: Encrypting and decrypting is as easy as pie, assuming you still remember your passphrase.

Last time[1] we'd created our PGP key. Let's jump in with some encryption and decryption examples.

We'll continue by using GnuPG, the Gnu Privacy Guard, from the command line. There are certainly GUI front ends for GPG, both as standalone applications and as parts of larger suites such as those integrated into email clients like Evolution. Hopefully by walking you through things on the command line you'll get a better appreciation of how it all actually works, which will make things a cinch should you turn to the dark side^W^W^W a GUI in the future.

In most cases, we'd want send files or messages to other parties. However for now we'll just be encrypting and decrypting to our own keys. Next time we'll cover how to get other people's keys and properly verify them.

So, say we have a file in which we keep all of our passwords. Not an uncommon situation - you certainly do use separate passwords for the various machines you access, and all the websites you frequent. Remembering them is a pain, but keeping them in your email inbox unencrypted is a bad idea. So let's fire up our editor and put them all in one place.

  $ umask 077
  $ mkdir passwords
  $ cd passwords
  $ $EDITOR mypasswordfile
  (create the file, exit when done.)
  $ ls -l
  -rw-------    1 xahria   gpg           209 Jan 21 11:52 mypasswordfile

So, having created the file, we're ready to encrypt it.

  $ gpg --sign --encrypt --text --armor mypasswordfile
    You need a passphrase to unlock the secret key for
    user:  "John Doe (My First PGP Key) <jdoe@example.com>"
    1024-bit DSA key, ID 26F8D783, created 2003-12-14
    Enter passphrase: (Enter passphrase here)
    You did not specify a user ID. (you may use "-r")
    Enter the user ID.  End with an empty line: John Doe
    Added 1024g/26F8D783 2003-12-14 "John Doe (My First PGP Key) <jdoe@example.com>"
    Enter the user ID.  End with an empty line: (enter)
  $ ls -la 
  -rw-------    1 xahria   gpg           209 Jan 21 11:52 mypasswordfile
  -rw-------    1 xahria   gpg          3094 Jan 21 11:54 mypasswordfile.asc

We provided gpg with a bunch of arguments, described here:

Encrypting your data takes the cleartext form and scrambles it. This scrambled version can be decrypted back to it's original form only if you are one of the people to whom the data was encrypted.

--encrypt requires that you list the person or persons who should be allowed to decrypt the data. You can have any number of recipients - the overhead of additional recipients is not very large on the resulting file size.

To be nit picky, we're not actually talking about a person but about a PGP key pair. Thus you would encrypt to a person's public key, so you need to have their public key already installed on your machine. We'll talk about that later.

For the detail curious, PGP encryption involves taking the message and encrypting it with a fast symmetric cipher like IDEA, 3DES, or blowfish using a random key. It then takes the random symmetric crypto key, and encrypts that value with the recipient's public key. Something encrypted with a public key can only be decrypted with the private key, so only the recipient can determine the symmetric crypto key that was used. If there are multiple recipients, the symmetric crypto key is provided in encrypted form to each of the recipients.

Signing is a way to take a piece of data (an encrypted or simple cleartext file) and digitally sign it. A PGP signature is simply a bit of extra data that can be used by another party to verify that the data has been signed by you, and hasn't been modified since you signed it.

From a technical standpoint, a PGP signature is generated by taking a checksum of the message (MD5, etc) and then encrypting that checksum with your private key. Private and Public keys are reciprocal -- anyone with your public key can decrypt something that was encrypted with your private key. Thus others can verify that you and only you could have signed the file. The first thing that gpg did is ask for your passphrase, since you're signing the file. (More on that in a minute)

GPG can save the resulting file in either a binary or ASCII format. Using --armor will cause it to use an ASCII-armored format, which is best to use if you want to send the file over means that may muck up binary files, for example mail or FTP. If you're just saving the file and accessing it locally, or if you plan on sending it somewhere via a means you know won't goof it up, then binary format is just fine. An ASCII armored gpg file will be bigger than it's binary counterpart due to using only printable characters.

If you use --armor, the resulting encrypted file will be named with a .asc extension. If you don't armor it, it will be named with a .gpg extension. Other versions of PGP software may prefer a .pgp extension, so you may need to rename .gpg files in those cases.

Using --text tells GPG that the file is ASCII text. When the file is decrypted on the other end, end-of-line sequences (CR/LF vs CR, etc) will be automatically converted, which is convenient.

GPG asked for the list of recipients - it needed that to know to which public keys it should encrypt the file. Since we didn't specify any on the command line, it asked. If you wanted to automate this better, you could put it on the command line any of the following ways:

  $ gpg -seat --recipient 26F8D783 mypasswordfile
  $ gpg -seat --recipient "John Doe" mypasswordfile
  $ gpg -seat --recipient jdoe@example.com mypasswordfile

In the first example, we explicitly listed the KeyID (26F8D783) of the recipient. In the other two examples, we provided something uniq from the key's owner, in this case the name and the email address respectively. As long as only one key is found that matches the data you provide, it will have no problems choosing it. When it doubt, use the keyid.

Also, note that I used the shorthand versions of sign/encrypt/armor/text by bundling their one-letter command-line counterparts into -seat. Most GPG options can be bundled into memorable words - fiddle around and have fun.

The shorthand version of --recipient is -r, in case you're curious.

So, having encrypted our password file, how can we view it?

  # Decrypt mypasswordfile.asc, save the unencrypted version
  # in 'mypasswordfile'
  $ gpg mypasswordfile.asc
  # Decrypt mypasswordfile.asc, save the unencrypted version
  # in 'unencrypted'
  $ gpg -o unencrypted mypasswordfile.asc
  # Decrypt mypasswordfile.asc, send the unencrypted version
  # to standard output, pipe it to the pager 'less'
  $ gpg -o - mypasswordfile.asc | less
  # Same as above
  # Decrypt mypasswordfile.asc, send the unencrypted version
  # to standard output, pipe it to the pager 'less'
  $ gpg --decrypt mypasswordfile.asc | less

For example:

  # Decrypt to stdout
  $ gpg --decrypt mypasswordfile.asc | grep my_isp.net
    You need a passphrase to unlock the secret key for
    user: "John Doe (My First PGP Key) <jdoe@example.com>"
    1024-bit ELG-E key, ID D5D3BDA6, created 2003-12-14 (main key ID D5D3BDA6)
    Enter passphrase: (passphrase)
  my_isp.net user="lainee" password="i8aX_1rR" access="ssh"
    gpg: Signature made Mon Feb  9 10:22:09 2004 PST using DSA key ID D5D3BDA6
    gpg: Good signature from "John Doe (My First PGP Key) <jdoe@example.com>"

Note how it first asked you for the passphrase to decrypt the file, then showed you the actual file contents (which we ran through grep) and then indicated that the file was signed by John Doe, and the signature was good, in other words no one had modified the file at all since he signed it. If you want less output when decrypting, you can supply the --quiet or -q option.

Next time we'll show you how key management works for PGP so you can know to whom you are talking, or encrypt to other parties.


[1] And I think I've achieved a new personal record for time between articles...

Bri Hatch is Chief Hacker at Onsight, Inc and author of Hacking Linux Exposed and Building Linux VPNs. His twins have been born! Xahria Rhealyn and Lainee Alandra were born on Jan 21, 2004, at 36 weeks. Both are doing well, and we're slowly adjusting to being awake 24 hours a day feeding hungry mounths and cleaning up ... well ... you probably don't want to know all the messy details. Condolances and lasagna can be sent to our address, which can be easily found via whois. Bri can be reached at bri@hackinglinuxexposed.com.

Copyright Bri Hatch, 2004

This is the February 19, 2004 issue of the Linux Security: Tips, Tricks, and Hackery newsletter. If you wish to subscribe, visit http://lists.onsight.com/ or send email to Linux_Security-request@lists.onsight.com.

previous article
next article