Last week at eurocrypt, a small group of researchers announced a fairly serious attack against the SHA-1 digest algorithm, which is used in many cryptosystems, including OpenPGP. The general consensus is that we should be moving in an orderly fashion toward the theater exits, deprecating SHA-1 where possible with an eye toward abandoning it soon (one point of reference: US gov't federal agencies have been directed to cease all reliance on SHA-1 by the end of 2010, and this directive was issued before the latest results).

Since debian relies heavily on OpenPGP and other cryptographic infrastructure, i'll be blogging about how debian users can responsibly and carefully migrate toward better digests. This post focuses on some first steps for users of gpg.

The good news is that gpg and gpg2 both support digest algorithms from the stronger SHA-2 family: SHA512, SHA384, SHA256, and SHA224.

By using these stronger digest algorithms some of your signatures may be un-readable by users of older software. However, gpg and PGP (a proprietary implementation) have both had support for at least SHA256 for well over 5 years. Debian's gnupg packages have supported the full SHA-2 family since sarge.

However, many existing signatures were made over the SHA-1 digest algorithm, which means that abandoning it immediately would cause serious problems. For example, we need to be able to rely on old signatures until a reasonably-fleshed out Web of Trust based on stronger digests is in place. So we need to collectively start the transition now.

So what can you do to help facilitate the move away from SHA-1? I suggest three steps that current gpg users can do today:

The first two are simple, quick, and painless actions. You'll be done with them in minutes! The third is tougher, and while you can start it today, key transitions take a little bit of time to complete. Read on for a HOWTO!
Start making data signatures and web-of-trust certifications using stronger digests
The simplest thing that you can do is to start making signatures using stronger digests by default. Add two lines to the end of your GnuPG configuration:
echo >>~/.gnupg/gpg.conf <

This will cover most messages sent out, including clearsigned messages
that are sent to mailing lists, and signatures over debian packages.

Indicate that you prefer stronger digests when receiving signed messages privately
Your preferences for the types of digest you wish to receive will be published to the public keyservers, so people who send you signed messages will know that you can (and prefer to) accept messages signed by stronger digests. The example assumes that your OpenPGP key ID is $KEYID:
testy@foo:~ $ 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.

pub  2048R/8A4EA1C3  created: 2009-05-06  expires: 2010-05-06  usage: SC  
                     trust: ultimate      validity: ultimate
[ultimate] (1). Test User (DO NOT USE) <test@example.org>

Command> showpref

[ultimate] (1). Test User (DO NOT USE) 
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA1, SHA256, RIPEMD160
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify

Command> setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
Set preference list to:
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Really update the preferences? (y/N) y

You need a passphrase to unlock the secret key for
user: "Test User (DO NOT USE) <test@example.org>"
2048-bit RSA key, ID 8A4EA1C3, created 2009-05-06

                  
pub  2048R/8A4EA1C3  created: 2009-05-06  expires: 2010-05-06  usage: SC  
                     trust: ultimate      validity: ultimate
[ultimate] (1). Test User (DO NOT USE) <test@example.org>

Command> save
test@foo:~ $ gpg --keyserver keys.gnupg.net --send-key $KEYID
gpg: sending key 8A4EA1C3 to hkp server keys.gnupg.net
test@foo:~ $ 
The key here is the setpref line:
setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
Note that we're setting digest, cipher, and compression preferences all at once here. Note also that gpg displays the implied 3DES cipher and SHA1 digest at the end of your stated preferences even though you did not ask for them. This is because RFC 4880 requires implementations to support these two algorithms, and gpg is subtly informing you that people might end up using them anyway, even though you aren't asking for them.

Note also the publication of the updated preferences to the public keyservers at the end there!

Replace your 1024-bit DSA keys with 2048-bit RSA keys or larger
The Digital Signature Algorithm, in its original form, only allowed maximum 1024-bit asymmetric keys, and the signature process itself signs a 160-bit hash, initially officially specified as SHA-1. This means that 1024-bit DSA keys should be phased out as well.

So if you have a 1024-bit DSA key (this is the vast majority of DDs: 1675 out of 2243 keys in /usr/share/keyrings/debian-keyring.gpg are DSA-1024), you should consider creating a new key and starting the migration process.

Also, if you are responsible for a DSA-1024 OpenPGP key for a debian team, role, or archive, please consider something similar to the process below for the debian-related key as well. I'm happy to note that the Debian Archive Automatic Signing Key (5.0/lenny) <ftpmaster@debian.org> is 4096-bit RSA, but unfortunately most of our other important infrastructural keys are still 1024-bit DSA.

A reasonable migration process over the course of 3 months might be:

  1. (day 0) Create a new key, using RSA 2048 at least (gpg appears to be about to change the default key generation to RSA 2048 shortly, if you need more justification). Be sure to configure ~/.gnupg/gpg.conf before creating the new key, and set up strong digest preferences (see above) immediately after key creation. Send the new key to the public keyservers. Generate a revocation certificate too, and store it in a safe place!
  2. (day 0) Sign your new key with your old one (not the other way around!), and publish the signature. Write up a transition statement (here's an example from an earlier key transition), clearsign it with both keys (old and new), and publish it in a stable place.
  3. (day 0) Write up or print out the User IDs and fingerprint of your new key on paper to hand out to people.
  4. (day 0 through day 90) Collect certifications binding the new key to your User ID to re-establish your connection to the Web of Trust. Some reasonable ways to do this effectively are
    • local keysigning parties (e.g. in NYC this coming Friday, 2009-05-08),
    • debconf (less than 90 days away!), and
    • contacting known and trusted friends, pointing them to the transition statement and asking them to reissue their certifications.
  5. (day 0 through day 90) Review the set of public certifications you've made (keys you've signed) with your old key. For keys you believe to still be active (maybe you want to check with the key owner), issue a new certification with your new key. If you get a request for new keysignings, use your new key during this period.
  6. (well before day 90) Ensure that your new key is in available everywhere you need it to be (like the debian keyring). Use your new key in those contexts and make sure it is accepted and acceptable.
  7. (day 90) Publish your stored revocation certificate for your old key. You had a revocation certificate for the old key already, right? If not, generate a new one, and publish it.
I welcome comments and suggestions about anything i've missed or screwed up here. The steps above do not complete the removal of SHA-1, but (if most of us take similar action soon) they lay the groundwork for an orderly and non-disruptive removal of SHA-1 in the future. The sooner this groundwork is in place, the less susceptible our infrastructure is to compromise by reasonably-well-funded organizations.