Mick picks up where he left off with GnuPG and gets even more paranoid with signing and verifying keys.
Last month I introduced the GNU Privacy Guard, a free but underutilized implementation of the OpenPGP encryption standards. GnuPG is, as you may know, extremely useful for encrypting and decrypting electronic files, especially e-mail, and for creating and verifying digital signatures.
But alas, by the time I was done explaining the basics of public key cryptography and the Web of Trust, not to mention doing my best to frighten you into signing each other's keys and checking unknown keys for validity, all there was room for in the way of practical examples was some compiling/installing advice and a little tutorial on verifying digitally signed files.
Well, this month is the payoff for the more technically inclined. Let's pick up right where we left off!
Before you encrypt, decrypt or sign anything, you need to build your own public and private keyrings; let's start by generating a GnuPG key pair. This is one of the more interactive gpg functions: the command syntax is simply gpg --gen-key, which triggers a question-and-answer session prior to your keys actually being generated. Listing 1 shows a sample key-generation session (user input in boldface). As you can see, you need to decide several things when generating a key: key type, key length, expiration date and the e-mail address (identity) you wish to associate with the key.
For a general-purpose key pair, choose DSA/ElGamal (option #1). This actually gives you two sets of keys: a DSA key pair that will be used by gpg for signing/verifying and an ElGamal pair that gpg will use for encrypting/decrypting. Don't worry that this will double the amount of keys you need to keep straight: the DSA and ElGamal keys are stored as a single file, as are the two public keys.
If you want to generate a signing-only key pair, choose DSA only (option #2). If you want an encryption-only key pair, choose ElGamal only (option #3).
I recommend against creating a dual-purpose ElGamal key pair, however (option #4). In Applied Cryptography, Bruce Schneier describes a simple attack that can work against schemata that use the same key pair used for both signing and encrypting. This “chosen plaintext” attack is quite literally a textbook example of the danger of using the same key material for both encryption and digital signatures.
Key size is of the utmost importance. The smallest key size supported by GnuPG is 768 bits, but 1,024 is recommended as having the best balance of security and performance. (A longer key is more secure but takes longer to compute and to use; a shorter key is faster to compute and use but is less secure.) Note that when you choose a combined DSA/ElGamal key pair, the DSA key length automatically is set to 1,024 bits, and the key length you're prompted for actually applies to the ElGamal key.
Next you need to think about how long you want this key pair to remain in circulation. On the one hand, if your key never expires, you never have to go to the trouble of generating new key pairs. The disadvantage of this is that if you forget the private key's passphrase and haven't created and kept a revocation certificate (which I'll explain shortly), it will be very difficult to remove the key from any keyservers it's listed on.
On the other hand, if your key expires after some period of time, then you need never worry about obsolete keys sitting around on public keyservers indefinitely: if your e-mail address changes, you decide that your key's length is no longer adequate, or if someone obtains a copy of your private key, you can rest assured that even if for some reason you can't revoke your old key it will die of old age. The only disadvantage of finite-lifetime keys is having to generate, distribute and get people to use your new keys periodically.
I used to use only non-aging keys but have become convinced that the pros of expiration dates outweigh the cons. Therefore, I recommend that you set your key to expire after no more than 18 or 24 months. For me, one year is too short (tempis fugit!), but I doubt that a key much older than a year and a half or two years can stand up to the inevitable advances in computing power and/or factoring technology (i.e., public-key cracking methods) that will have occurred over its lifetime.
Next you need to specify a name, e-mail address and also an optional comment. Note that you can associate additional e-mail addresses with your key later by using gpg's --edit-key flag and issuing an adduid and/or an addkey command.
The last thing you need to think about in generating your key is a good passphrase. And I do mean passphrase: it can and should contain spaces. The longer it is, the more secure it is. You should also incorporate some combination of numbers, mixed case (e.g., bOTTLE rockeT) and punctuation. Lately, I've taken to generating my passphrases with dice and a word list. See diceware.com for a handy procedure for doing this yourself.
Whatever you do, don't choose a short, predictable or otherwise guessable passphrase. It doesn't have to look like “B1&SSja-sd0c as-d$%@KFSAAs-,ssd w0a-00sdp23m”, nor should it look like “My lame passphrase”. It's okay to write your passphrase on a small card you keep in your wallet if doing so makes it easier for you to use hard-to-guess passphrases. (Just be careful never to leave it sitting around and to always put it away when you're done with it!)
After you've generated your key, you should immediately create a revocation certificate. This is a string of text that you can send to a keyserver if and when you need to revoke your key.
Of course, you can create a revocation certificate at any point. The reason it makes sense to create one now is that it's not uncommon for even very knowledgeable and careful people to forget their passphrase. You need your passphrase to create a revocation certificate, but not to use one you created earlier.
That's why it's a good idea to create a revocation certificate now and save it in a safe place (you can even print it out and save it in “meatspace”--revocation certificates aren't very long). Just be sure to set its file permissions to be as strict as your private key's (e.g., not group- or world-readable or writable). The ramifications of someone sending the certificate to a keyserver without your permission aren't as scary as if someone can actually use your private key, but at the very least a prematurely revoked key could inconvenience you.
To generate a revocation certificate, enter this command:
gpg --output rev_cert_filename.asc --gen-revoke keyname
where rev_cert_filename.asc is the filename you'd like the certificate to have (just make sure it ends in .asc) and keyname is the key's ID number (e.g., 0586AF78) or part of your identity (“Smooth JoJo” would be enough to identify our example key).
GnuPG stores its files in a subdirectory of your home directory called .gnupg. Any private keys you have are stored in a file called secring.gpg; public keys are stored in pubring.gpg. By default, secring.gpg is readable only by you; leave it that way. It's extremely important that you protect this file. By all means, back it up to a floppy or CD-ROM, but keep your backup in a safe place. If anyone obtains a copy of your secret keyring, they may be able to guess or brute-force-crack the passphrase of your private key and effectively steal your identity (or at least be able to decrypt your stuff).
Both pubring.gpg and secring.gpg are binary data files. To add, delete or change keys on either keyring, you need to use various flags with the gpg command.
For example, you're going to want to distribute your public key to your friends, right? So let's extract that key from your public keyring into a text file (see Sidebar “Armored ASCII vs. Binary GPG Files”). To print your public key to the screen, from whence it can be copied and pasted as needed, you need simply enter:
gpg --armor --export
the output of which will look something like Listing 2.
I took the liberty of simplifying a bit here; if you don't specify a user ID, gpg will dump the public portion of your default key pair. If you only have one private key, then that key pair is your default key and that pair's public key will be dumped.
If, on the other hand, you wish to dump some other public key, you need to specify a user ID. Continuing our example using Mr. Figplucker, to display JoJo's public key we enter:
gpg --armor --export jojo
As you can see, gpg is fairly intelligent when trying to determine which key you want to work with. In fact, it works a lot like grep: if you give a snippet of your e-mail address or some other text as your key identifier, gpg will match the first key whose user ID contains the string. In managing my own keyrings, in which I have several private-public key pairs and therefore numerous user IDs containing my name, I find it easiest to provide gpg with the entire e-mail-address portion of the key I wish to work with at any given time, e.g., gpg --armor --export firstname.lastname@example.org.
By the way, if you want to print a key to a file rather than to the screen, specify a filename with the --output option. To write JoJo's public key to the file jojo_pub.asc, the command would look like this:
gpg --armor --output jojo_pub.asc --export jojo
Have you backed up your new keys yet? You may consider exporting your entire key pair, including your private key, but I recommend against doing this. You're much better off simply copying the keyring files pubring.gpg and secring.gpg from ~/.gnupg to a safe place. But if for some reason you do need to export your entire key pair, it's the same as exporting a public key except that you use the --export-secret-keys command rather than --export.
Your friend Dan Sparty has just e-mailed you a copy of his new public key, in the form of a file called danskey.asc. Here's how you import it to your public keyring:
gpg --import ./danskey.asc
But wait a minute. Internet e-mail isn't a very secure medium. How do you know Dan's key wasn't tampered with in transit, or that it even was Dan that sent it in the first place?
By checking its fingerprint, that's how. Every gpg key has a secure hash called a fingerprint that is unique to each key (pair) but is short enough to be read over the phone, written on a postcard, etc. If you call Dan on the phone and ask him to read you the fingerprint of his new key, it should match the output from the following command (executed on your system after importing his key):
gpg --fingerprint dan
Note that as with the --export command, you can specify just part of the key as long as that part is unique to the key you wish to fingerprint. The output will look something like this:
pub 1024D/C9F34866 2001-07-27 Dan Sparty (Party Down!) <email@example.com> Key fingerprint = D084 F92C EC62 8955 98E2 58FB 178A 2673 D1F3 6866 sub 1024g/C5569A5B 2001-07-27 [expires: 2001-08-10]Alternatively (let's say it's only noon and you don't want to wake Dan up), if Hugh has this fingerprint in his e-mail signature and has furthermore made postings to Usenet or on public e-mail lists, you can simply find one of these messages and compare that signature. This illustrates an important aspect of key fingerprints: the more places your public key and/or its fingerprint is archived, the harder it is for someone to pretend to be you.
Now that you know this is really Dan's new key and not a forgery, you can do Dan and the world a favor by publicly and cryptographically vouching for its veracity. In other words, you can sign it with your private key. To do so, you run gpg with the command --edit-key. This, like --gen-key, triggers an interactive session. Listing 3 shows a key-editing session in which the user signs a key with their own default key.
Did you notice the final save command? This saves any changes you've made to the key (in this case, the signature you created for it) and exits the key-editing session. If we now list the key with the command gpg --list-sigs dan we'll see:
jojo@linux:~ > gpg --list-sigs dan pub 1024D/B9E0868B 2001-07-27 Dan Sparty (Party On!) <firstname.lastname@example.org> sig B9E0868B 2001-07-27 Dan Sparty (Party On!) <email@example.com> sig C1C34866 2001-07-27 John J. Figplucker (Smooth JoJo) <firstname.lastname@example.org> sub 1024g/A0B78448 2001-07-27 [expires: 2001-08-26] sig B9E0868B 2001-07-27 Dan Sparty (Party On!) <email@example.com>
In addition to Dan's own signatures (when you generate a key it's automatically self-signed) you can now see JoJo's. Now, all that remains is for JoJo to export his new signed version of Dan's public key:
gpg --output dan_jojosig.asc --export danJoJo then needs to send this file to Dan via e-mail or some other convenient means (remember, it's a public key, so confidentiality isn't an issue), and Dan needs to import the signed key back into his own public keyring:
gpg --import ./dan_jojosig.ascImporting may seem counterintuitive: Dan's actually updating his public key, not importing a new one. But trust me, that's what he needs to do in order to join the proud ranks of gpg users who actually have bothered to get their friends to vouch for their keys.
Now that Dan's got a superelite signed key, he's ready to post it to a keyserver so other people can start sending him encrypted messages (and adding their signatures to his key). To do so he can issue the command:
gpg --keyserver pgp.mit.edu --send-keys firstname.lastname@example.org
The option --keyserver is used to specify the name or IP address of a PGP/GPG keyserver. Alternatively you could add to ~/.gnupg/options a line like this:
keyserver pgp.mit.eduBut, note that doing so will cause gpg to download new keys automatically from the keyserver if it encounters an unknown key when verifying signatures.
Remember last month when I verified a detached signature file for a software package? The first time I tried to verify the signature with the gpgv command, I received an error message since the key used to create the signature wasn't present in my public keyring.
The solution was to query for, and download, the key from the keyserver pgp.mit.edu; this would have happened automatically if a keyserver had been set in my options file. It's up to you to decide whether this is a feature or an annoyance, and whether therefore to make it the default behavior. (The command-line option --no-auto-key-retrieve will override auto-key-retrieval.)
And now, at long last, JoJo's ready to start encrypting everything in sight. Suppose JoJo wants to send an encrypted e-mail to Dan. The most common way for him to do this is to compose his message with the text editor or word processor of his choice and save it to disk. JoJo writes a letter with vi and saves it as dan0729.txt. Then he encrypts it with the command:
gpg --output dan0729.txt.asc --encrypt --recipient email@example.com dan0729.txt
Finally, he sends the file dan0729.txt.asc as an e-mail attachment or even listed in the body of an e-mail message (JoJo's got an “armor” line in his options file).
Note that if JoJo encrypts without passing gpg the --armor flag and he doesn't have an armor line in his options file, he should call the encrypted file dan0729.txt.gpg instead since it will be saved in the gpg binary format. Also, it will only be transmittable as an attachment. Remember, Armored ASCII is much more versatile. The gpg binary format may be preferable if file size matters because it tends to produce less output than Armored ASCII.
When Dan receives this file, he should save it to disk and decrypt it with the command:
gpg --output dan0729.txt --decrypt dan0729.txt.asc
Unlike encrypting, you don't need to specify a key when decrypting. gpg automatically determines which key to try to decrypt it with. Similarly, it doesn't matter whether the file Dan tries to decrypt is in gpg binary or Armored ASCII format; gpg will determine which format the file is in automatically, after prompting Dan for a passphrase. If Dan doesn't type his passhprase correctly, gpg won't decrypt the file.
Signing and verifying is very similar to decrypting and encrypting things. Suppose JoJo writes a nonconfidential but important letter to Dan that he wants Dan to be able to verify the validity of but doesn't need to actually encrypt. To sign his file beercontract.txt, JoJo would enter the command:
gpg --output beercontract_signed.txt --clearsign beercontract.txt
This will add a signature header and footer to the file and save it as beercontract_signed.txt. It's important that the output file be named differently than the input file, or the original file will be replaced with a signature for an empty file. You should use the clear-text method of signing when you want to be able to copy-and-paste your signed message into or out of e-mail, or otherwise treat it as plaintext.
The alternative is, you guessed it, to create a binary signature. There are two types of these. To create a binary signature that contains the original document and the signature in one compressed binary file, use the --sign command instead of --clearsign. To create a much smaller binary file containing a signature but not the file it references, use the --detach-sig command. Both --sign and --detach-sig should be preceded by an --output directive.
When Dan receives JoJo's beer contract, he can verify the signature appended to it by saving the file to disk, say as bcs.asc, and entering the command:
gpg --verify bcs.asc
Remember, if Dan doesn't have JoJo's public key in his keyring, gpg will return an error. If Dan does have JoJo's public key and the signature checks out, gpg will return something like the following:
gpg: Signature made Fri 27 Jul 2001 04:46:46 PM CDT using DSA key ID C1C34866 gpg: Good signature from "John J. Figplucker (Smooth JoJo) <firstname.lastname@example.org>"Then and only then will Dan know for sure that the contract he just received was signed by the bearer of JoJo's private key. Could JoJo have had a spear pointed at his tuckis? We don't know. Could JoJo have left his passphrase scrawled on the bottom of his keyboard, to be used by his office mates for impersonation pranks? Again, we really don't know. But if we trust JoJo to use and protect his key properly, we can be fairly sure that he did indeed create this valid signature.
I hope you're not too overwhelmed by all these options, flags and commands (Welcome to UNIX!). This has really been more of a survey than anything else; there's much I haven't covered. But I do believe that gpg is an important and useful tool. So much so that a number of people are working on more user-friendly front ends for it. The official GnuPG GUI is called the GNU Privacy Assistant (GPA), and while it's still a work-in-progress, it looks very promising indeed. It uses the GIMP toolkit, and is, unsurprisingly, nice to look at indeed.
Other GUIs under various stages of development include Seahorse and GnomePGP for the GNOME desktop; Geheimnis for KDE; TkPGP (written in Tk and therefore relatively windowmanager-agnostic); and a variety of wrappers, plugins and enhancements to popular mail user agents (or MUAs, aka e-mail clients). See the “Frontends” section of the GnuPG home page for links to these and other tools.
Thus endeth our two-month tutorial on basic GnuPG use. This is one tool that many, many more of us should be using than presently do. So please, go forth and encrypt. Specifically, encrypt using keys that have been signed and verified by people you know.
By the way, I'll be off next month working on a book on Linux security for O'Reilly & Associates. Fear not, however; an able substitute will be found to handle the column while I'm gone, and I'll be back the month after that. Cheers!