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

  1. shahryar ghazi | June 9, 2009 at 5:25 am | Permalink

    thanks for sharing

  2. KevDog | June 22, 2009 at 9:57 pm | Permalink

    Great info. However I think you should explain that the value set for default-preference-list is actually only used in the creation for new keys -- it sets the defaults for any new keys created with the gpg --gen-key command. The topic of key creation was really covered in this blog, so I think to reference this command without explaining its use is a little misleading.

    Beyond that the blog was really good.

    I think however gpg recently changed the way they decide on what cipher and hash to use. I think actually the personal-cipher-preference and personal-hash-preference are given priority over the recipients preferences embedded in their keys. (Please note I believe the old style way was to give priority to the preferences contained in the keys and then cross-reference the priorities with personal preferences when available.) Also note this process is much more complicated than described above, particularly if you are sending mail for example to 3 recipients each with different algorithms specified in their keys. You may actually want to discuss how this conundrum is handled since I find it interesting (however it might bore many users).

  3. TSn | July 1, 2009 at 6:43 am | Permalink

    Thank you for sharing! Even as a beginner in GnuPG this tutorial helped me much more than others.

  4. maryanna | August 18, 2009 at 12:39 pm | Permalink

    FYI, not everyone that visits your site is concerned with the "best" experience, so you might want to offer a way to get past that extremely annoying popup with the download links. I happened to be at work, where there are policies regarding which versions are used, when I got to your site from a search on gpg. I took the time to get to another environment to comment because I really wanted to see the information, but was quite irritated by not being able to get past the admonishing message while using IE. Not to mention that there might be folks interested in the content that are using, GASP!, text-based browsers. Oh, and, P.S.: this was generated using Chrome 2.0.172 on WinXP, not Safari 530.5 on Mac OS X.

  5. Aaron | August 18, 2009 at 1:02 pm | Permalink

    @maryanna I don't have any popups for any browser that comes to my site. Check the source, and you'll find that the only JavaScript running on my site is for community polls in posts (no popups), UserAgent string detection for comments (no popups) and StatCounter for tracking visitors (again, no popups). If you're using IE, and getting popups, I'm afraid you might have a virus or some other form of malware that is hijacking your browser. Maybe you could provide a screenshot of the popup message you're experiencing while browsing my site? I can't produce it with IE 7 or IE 8. Unfortunately, I don't have access to an IE 6 install.

    Further, while I strive for standards as much as possible with this site, I make no guarantees that it will work in any browser, including text-based. However, just pulling up links2 in my terminal, and browsing the site, it seems to render rather well, and is quite readable and navigational.

    Lastly, Chrome is using the rendering agent from Safari, namely KHTML. The UserAgent string identifies itself as Safari running on a Macintosh, not Google Chrome running on Windows. If this bothers you, I would suggest getting in touch with the Google Chrome development team, and submit a feature request for getting the UserAgent string changed.

  6. maryanna | August 19, 2009 at 1:42 pm | Permalink

    Aaron, now that I've actually been able to peruse the site, I can see it is very well done and quite informative. Also, your prompt and thorough response to my comment is appreciated.

    I didn't consider the virus/malware possibility and didn't have the time for more than a cursory glance at the source at the point when it occurred.

    This popup is new to me, and it only appears on your site (thus far), although I've heard that Silverlight sites produce similar notifications. You'd think Microsoft wouldn't link to everyone else's browsers, though, if they were the source. The screenshot is available, since it is IE 6 we're running, just tell me where you want it sent.

    Thank you for the details on Chrome, I'll credit you when I send the request.

  7. Matt | May 7, 2010 at 10:17 pm | Permalink

    Thanks for this post. It's been helpful. However, I cannot determine why SHA1 is used when I clear-sign a file even though SHA1 is listed last in my preferences. What's even stranger is that when I send a signed email, SHA512 is used as expected. What am I missing? My pasted my preferences below. Thanks!

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

    Cipher: TWOFISH, AES256, AES192, AES, BLOWFISH, 3DES
    Digest: SHA512, SHA384, SHA256, SHA224, SHA1
    Compression: BZIP2, ZLIB, ZIP, Uncompressed
    Features: MDC, Keyserver no-modify

  8. hhhobbit | May 25, 2010 at 11:36 pm | Permalink

    Matt: Precisely what do you mean by a clear-sign of a file? Do you mean the --clearsign or a --detach-sign (-b)? I am assuming the first. In cases where GnuPG can not determine who the recipient is (use of the clear-sign without using either --recipient or --default-recipient) it defaults to the lowest common denominator. When the recipient is known (you are specifying the recipient key) then it follows their list of preferences until it finds one your software can do. Example. I do detached sigs on the files distributed on my web-site. I don't know who is going to use those detached sig files in advance. Here is my digest list (and at one time I had SHA1 first to avoid problems but I REALLY did not like it!):

    SHA512, SHA384, SHA256, SHA1

    Okay, let me sign the gpg2.1 man page (formatted so I can find things):
    I actually have scripts to do a lot of this so here is the actual command in the script:

    ${GPG} --default-key ${KEYID} --output ${FILE}.sig --detach-sign $FILE

    Here are the scripts:

    The scripts saves on typing. Okay, what HASH did I use? Since the default is I am using MY key I don't care what somebody else can handle (nobody has complained but in reality for a long time I have had it as SHA1 first just to avoid the complaints):

    $ gpg2 -v --verify gpg2.1.sig
    gpg: assuming signed data in `gpg2.1'
    gpg: Signature made Wed 26 May 2010 06:15:36 AM UTC using RSA key ID 954D820D
    gpg: using PGP trust model
    gpg: Good signature from "Henry Hertz Hobbit "
    gpg: aka "Henry Hertz Hobbit "
    gpg: aka "Henry Hertz Hobbit "
    gpg: binary signature, digest algorithm SHA512

    It is done this way in the example you gave because when you are signing a message sent to you it follows what you asked for. You want SHA-512 first so that is what it gave you. You can over-ride it with an explicit --digest-algo but I would not do it because it violates the OpenPGP standard. Give the actual command you use to clear-sign a file and people (others, not me) will better be able to help you. I assume you already answered this for yourself by now.

  9. Anonymous | November 21, 2012 at 10:29 am | Permalink

    So helpful, thank you.

Post a Comment

Your email is never published nor shared.