Image of the glider from the Game of Life by John Conway
Skip to content

GnuPG Up And Close

Every GNU/Linux distribution ships with GnuPG by default. While they all don't ship with the same GUI frontend, they do ship with the the same CLI backend. So, we'll be interfacing with that throughout this informational session. I'm not presenting this as anything necessarily useful. Rather, I hope you find it informational/educational, and learn a little bit with how GnuPG works "under the hood". So, let's have some fun. First, a list of the "standard" algorithms that ship with GnuPG on a GNU/Linux system. This is completely based on the type of main public and private keys as well as any subkeys that you've generated. You can see a list of supported cipher, digest and compression algorithms by invoking the gpg binary and passing "--version" as an option. For example, here is the output from my Debian GNU/Linux unstable laptop:

$ gpg -v --version
gpg (GnuPG) 1.4.9
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: ~/.gnupg
Supported algorithms:
Cipher: 3DES (S2), CAST5 (S3), BLOWFISH (S4), AES (S7), AES192 (S8), 
        AES256 (S9), TWOFISH (S10)
Hash: MD5 (H1), SHA1 (H2), RIPEMD160 (H3), SHA256 (H8), SHA384 (H9), 
      SHA512 (H10), SHA224 (H11)
Compression: Uncompressed (Z0), ZIP (Z1), ZLIB (Z2), BZIP2 (Z3)

So, for ciphers, I support 3DES, CAST5, BLOWFISH, AES, AES192, AES256 and BLOWFISH. For digest hashes, I support MD5, SHA1, RIPEMD160, SHA224, SHA256, SHA384 and SHA512. Lastly, for compression algorithms, I support uncompressed, ZIP, ZLIB and BZIP2. Your output my vary slightly one way or the other. For example, you may not see the full suite of SHA algorithms. This can be obtained by generating an RSA subkey for signing only. Other ciphers might include IDEA, CAMELLIA128, CAMELLIA192 and CAMELLIA256, and you could have TIGER and WHIRLPOOL as possible supported hashes.

With all these algorithms, how do you know which to use and when? Fortunately, GnuPG takes care of that for you automatically. However, you can tell it what you would to prefer to use for each, if you like. You can set these in your ~/.gnupg/gpg.conf file. The options you are looking to set are "default-preference-list", "personal-cipher-preferences", "personal-digest-preferences" and "personal-compress-preferences". For myself, here is what I have set in my gpg.conf:

default-preference-list 3DES CAST5 BLOWFISH AES AES192 AES256 TWOFISH MD5 SHA1 RIPEMD160 SHA224 SHA256 SHA384 SHA512 Uncompressed ZIP ZLIB BZIP2
personal-cipher-preferences TWOFISH AES256 AES192 AES BLOWFISH CAST5 3DES
personal-digest-preferences SHA512 SHA384 SHA256 SHA224 SHA1 RIPEMD160 MD5
personal-compress-preferences BZIP2 ZLIB ZIP Uncompressed

Now, when we printed out the verbose version, we saw in parenthesis S2, S3, H8, H9, Z1, Z2 and so on. We can use these instead of the name in our gpg.conf if we so wish. I prefer the name, as I can't recall the key to the algorithm, and it's easier to read. So, in my case, I list out everything that I want for a default list of preferences, then I choose the order of which to pick from when encrypting, signing and compressing. So, for encryption, I have set TWOFISH as my first choice, with AES256 as my second choice, then AES192 as my third, and so forth. I've done the same with my preferred digest hashing algorithm choosing SHA512 first, then SHA384 second, and so on, and the same with compression.

Why set the preference? For starters, if you're like me, you sign all your email by default. You probably want your signature to withstand the test of time as long as possible. Given the strength of today's hardware, why not choose the strongest encryption and hash algorithms? But on a more practical note, if you're encrypting data to yourself, this would tell GnuPG to use TWOFISH as the encryption algorithm. This means that if you want to decrypt it at a later date, maybe on another computer, you'll need to make sure TWOFISH is compiled into GnuPG. How would you know what was used? We'll cover that in a bit.

However, what about encrypting to someone else other than yourself? How do these preferences come into play? Well, you can also set preferences in your public key. The purpose of this, is when people grab a copy of your key, and they want to encrypt something to you, GnuPG will negotiate the first preferred algorithm that is common between the two end points (the one doing the encrypting and the one receiving the encrypted data).

For example, let's suppose Alice has a GnuPG keypair as does Bob. In Alice's public key, which Bob has a legitimate copy of, she has set a cipher preference order of: TWOFISH BLOWFISH AES CAST5 and 3DES. Bob wants to encrypt data to Alice. Because he has a copy of her public key, he can do this. The question here is, which algorithm will be chosen for the encryption? Well, Alice prefers TWOFISH as a first pick. If Bob has compiled TWOFISH support in his copy of GnuPG, then it will be used. Suppose he doesn't have TWOFISH support. Then the next preferred algorithm is BLOWFISH, because it's Alice's second pick. Let's say Bob does support it, then BLOWFISH is the algorithm used for encrypting the data to Alice. When Alice receives the encrypted data, she'll use the BLOWFISH algorithm along with her private key to decrypt the data. Should she wish to reply, her copy of GnuPG will pull out the preferences from Bob's public key, and go through the same process looking for the first preferred algorithm by Bob that is supported by both parties. The "SSL handshake" works much in this same manner.

Digest hashing works much the same way, but slightly different. Because the recipient doesn't matter with signed data, then rather than looking to public keys for the digest algorithm preference, you turn to your gpg.conf file, if listed, and use that there. If the recipient, or recipients have a copy of your public key, and the same digest algorithm compiled into their copy of GnuPG, they can verify your signature. If either is missing, the public key, or the algorithm, the signature will fail, and GnuPG will explain the problem. This process is the same for compression algorithms.

So, we've made the preferences in our gpg.conf, but how do we set them in the public key, so we can distribute this to others? Well, in this case, we need to edit our key. From the terminal (I've snipped out the noise, focusing only on what's important):

$ gpg --edit-key KEYID
gpg (GnuPG) 1.4.9; Copyright (C) 2008 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.

Secret key is available.
[ ... SNIP ... ]


We are now sitting at a command prompt that we can use to pass commands in an interactive fashion. I should mention that all this can be done non-interactively. Checking out the gpg manual will provide the list of options for making this possible. Typing "help" will give us the list of commands that we can pass:

Command> help
[... SNIP ...]
pref        list preferences (expert)
showpref    list preferences (verbose)
setpref     set preference list for the selected user IDs
[... SNIP ...]

The commands that we are interested in "pref" and "setpref". Passing "pref" might give us something like the following:

Command> pref
[ultimate] (1). Aaron <>
     S10 S9 S8 S7 S4 S3 S2 H10 H9 H8 H11 H2 H3 H1 Z3 Z2 Z1 Z0 [mdc] [no-ks-modify]

See those algorithm codes we saw at the beginning of this tutorial? They are listed in the preferred order that we wish to have each algorithm. In my case, I have all my encryption algorithms lists, from strong to weak, then hashing from strong to weak, then compression from most tight to no compression. What if I wanted to set a different order, or maybe not include some preferences: Using "setpref" makes this possible:

Command> setpref S10 S9 S8 S7 H10 H9 H8 H2 H3 Z2 Z1 Z3 Z0
Set preference list to:
     Cipher: TWOFISH, AES256, AES192, AES, 3DES
     Digest: SHA512, SHA384, SHA256, SHA1, RIPEMD160
     Compression: ZLIB, ZIP, BZIP2, Uncompressed
     Features: MDC, Keyserver no-modify
Really update the preferences? (y/N)

Typing "y" will of course make the setting in your key. At this point, you'll be asked to enter your private key passphrase successfully before continuing. At that point, it will be statically set in your public key, and you can send your key off to the keyservers and emailed to your family and friends, so they can immediately start taking advantage of the new preferences. Type "quit" to leave the prompt.

Now, let's say you have some signed and encrypted data, and you're curious of the algorithms used when creating the cipher text. This can be done by passing the "--list-packets" option to gpg to see the data packets. We'll need to turn on verbosity as well. For example, the output of a file I sent to a friend using the Mutt email client (emphasis mine):

gpg -v --list-packets file.txt
gpg: armor header: Version: GnuPG v2.0.11 (GNU/Linux)
[... SNIP ...]
gpg: AES256 encrypted data
:compressed packet: algo=3
:onepass_sig packet: keyid CE7911B7FC04088F
	version 3, sigclass 0x01, digest 8, pubkey 1, last=1
:literal data packet:
	mode t (74), created 1244484492, name="mutt-helios-1000-24974-13",
	raw data: unknown length

Here, I can easily see that AES256 was used for the encryption algorithm, but what's this compressed "algo=3" and "onepass_sig packet digest 8" stuff? Well, in order to understand those, we need to turn to RFC 4880. This RFC describes the OpenPGP message format and the standards used. Browse your way down to section 9, and you'll see what "algo=3" means for compression and "digest 8" is for signatures. It appears, according to that RFC, that BZIP2 was used for compression and SHA256 was used for the hashing algorithm. So, in this case, Christer and myself preferred those settings higher than the others, and my GnuPG acknowledged those preferences and did the encrypting, signing and compressing as told. We can see these by "editing" his key:

$ gpg --edit-key christer
[... SNIP ...]
Command> pref
[  full  ] (1). Christer <>
     S9 S8 S7 S3 S2 H2 H8 H3 Z2 Z3 Z1 [mdc] [no-ks-modify]
[... SNIP ...]

Command> quit

Christer places AES256 has his first preferred encryption algorithm. Because I also support this algorithm, this is used for the encryption. SHA1 is his preferred digest hashing algorithm with SHA256 as his second preferred, but remember that for the signature and compression, these preferences are found in my gpg.conf instead. I prefer SHA512 as my first preference, but he doesn't list it as suported (according to his public key), so I move down to SHA384. Again, he doesn't list it, so I try SHA256. He lists it, so it's used. Lastly, BZIP2 as the compression algorithm, and he lists it, thus it's chosen. Thus, the results we got. Make sense?

I hope this has been informative. It's been great discovering the details of how these algorithms were chosen, and it's been fun playing with all sorts of encrypted emails and files to get to the guts of the GunPG process. If I've misrepresented any data here, or you have questions, please let me know.

{ 9 } Comments