Pages

GnuPG – RSA key-pair mini-Howto with stronger digests

(Note: This was originally posted on my previous blog, but I’ve noticed that it’s being linked to, so I’ve reposted it here)

I’m not a mathematician (or a cryptographer) so I’m happy to take this post‘s word for it about a recent attack against SHA-1 (short PDF here). The post goes into detail about changing the preferred digests on a key, and is well worth a read.

The post also talks about using 2048-bit RSA keys, instead of the DSA/Elgamal default (which has a maximum size of 1024 bits). It goes into detail about how to migrate to an RSA key – if you’re going to migrate, I definitely recommend reading it.

However, I thought it would be nice to write a (very) quick guide on generating RSA private keys with GnuPG, as there are a few extra steps involved – but nothing complicated!

Preparation

The first thing mentioned in the post on Debian Administration is to set a couple of GnuPG config options to ensure that any digests generated by you are using the stronger SHA256, rather than SHA-1. Doing this is simple:-

cat >>~/.gnupg/gpg.conf <<EOF
personal-digest-preferences SHA256
cert-digest-algo SHA256
EOF

We’re now ready to generate our key.

Generate our first key

To start with, start the key generation as normal:-

[andys@sirius ~]$ gpg --gen-key
Please select what kind of key you want:
   (1) DSA and Elgamal (default)
   (2) DSA (sign only)
   (5) RSA (sign only)

(1) is the default, and generates a DSA key with an Elgamal subkey for encrypting. But for our RSA key, we need to choose (5).

Next, we’re asked for our key length. This is between 1024 and 4096 bits. The default is 2048, but for mine I’ve chosen 4096. A good overview of keys and key sizes can be found on pgp.net here.

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits

The next question is about how long you want the key to be valid. Again, this is personal preference, and in this instance I’ve chosen ‘0’ for ‘never expires':-

Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

Next up is your user ID, which consists of your name, e-mail address and a comment. I tend to leave the comment field blank, but it’s there if you want it:-

You need a user ID to identify your key; the software constructs the
user ID from the Real Name, Comment and E-mail Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Andy Smith
E-mail address: andy.smith@netprojects.org.uk
Comment: [Return]
You selected this USER-ID:
    "Andy Smith <andy.smith@netprojects.org.uk>"
Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit?

Select ‘O’ to continue.

You need a Passphrase to protect your secret key.

You’re now being prompted to set a passphrase on the key. This can be as strong or as weak as you like, but considering the importance of your private key it’s best to secure it with a strong passphrase.

After supplying a passphrase, the actual key will be generated. RSA keys require quite a bit of entropy (‘randomness’), and you’ll probably get a warning like this:-

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 284 more bytes)

A good way to generate entropy is to create lots of I/O traffic (keyboard, mouse, network, disk, etc.). I found using cat(1) on files and redirecting the output to /dev/null worked quite well, especially if you use a block device of some sort (for example, I did cat /dev/sdb >/dev/null, where /dev/sdb was a 1GB USB key).

Eventually – hopefully after not too much of a wait – gpg will report that it has completed generating the key, and you’ll have output a bit like this:-

gpg: key A0E6B93E marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
pub   4096R/A0E6B93E 2009-05-08
 Key fingerprint = B2C5 59E3 E685 757A 45CD  7760 5BF3 1276 A0E6 B93E
uid                  Andy Smith <andy.smith@netprojects.org.uk>
Note that this key cannot be used for encryption.  You may want to use
the command "--edit-key" to generate a subkey for this purpose.

The key ID is now given, which in this case is A0E6B93E. We can also see (on the line that starts with ‘pub’) that the key is 4096 bits in size, and is an RSA key (denoted by the ‘R’). Sharp-eyed readers may have noticed that the key ID is actually the last 8 bytes[1] of the key’s fingerprint – this is because the key ID is just a shorter way of expressing the key fingerprint, and in itself isn’t guaranteed (or indeed intended) to be unique.

Also important is the last two lines, which point out that our brand spanking new key can’t be used to encrypt anything just yet.

Adding encryption

So without further ado, let’s create a subkey that lets us do encryption with our key:-

[andys@sirius ~]$ gpg --edit-key A0E6B93E
<...version information...>
Secret key is available.

pub  4096R/A0E6B93E  created: 2009-05-08  expires: never
  usage: SC
 trust: ultimate      validity: ultimate
[ultimate] (1). Andy Smith <andy.smith@netprojects.org.uk>

Command>

Unsuprisingly, ‘addkey’ is the command we want to generate a subkey, so that’s what we’ll run. Upon hitting enter, you’ll be prompted for the passphrase you set on your key earlier. Once given, you’ll be presented with a menu like this:-

Please select what kind of key you want:
 (2) DSA (sign only)
 (4) Elgamal (encrypt only)
 (5) RSA (sign only)
 (6) RSA (encrypt only)
Your selection?

Since it’s to complement our existing RSA key – which can already be used for signing – (6) is the option we want. Picking it brings us to a familiar prompt, wherein we’re asked for a key size:-

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096

The subkey’s size doesn’t have to match that of the parent key, but in this case I’ve gone for the same size, so 4096 it is. After picking a size, you’ll again be asked how long you want the key to be valid for. I’ve gone for 0 again, but again it doesn’t have to match that of the parent key. There is a slight difference, in that you’ll be prompted twice, just to make sure that you want to create the subkey:-

Really create? (y/N) y

Now it’s time once more to play the entropy game. Use whatever you found worked for you earlier, and eventually you’ll see something like this:-

pub  4096R/A0E6B93E  created: 2009-05-08  expires: never
  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/5D0CCD64  created: 2009-05-08  expires: never
  usage: E
[ultimate] (1). Andy Smith <andy.smith@netprojects.org.uk>

As you can see, I now have a subkey with a fingerprint ending in 5D0CCD64, which can be used for encryption – denoted by the ‘E’ at the end of the line. Also noted is that the key is ‘ultimately trusted’ by me, because it’s been added as a subkey to my key.

Changing the digest settings

As per the post linked to at the beginning, we can change the digest (or ‘hash’) that we prefer to receive signed data in. Without going into too much detail (you should read the post!), we can change these preferences:-

Command> setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES
  CAST5 ZLIB BZIP2 ZIP Uncompressed

Our preferences are confirmed back to us, and we’re asked to accept them:-

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

Confirming our changes

Since we’re now finished, we need to save the key to confirm our subkey:-

Command> save
[andys@sirius ~]$ _

At this point, the key can now be used for signing and encryption. You can do other things, such as add a small photo to the key using the ‘addphoto’ command, but two things you should do are to publish the key to a keyserver, and to generate a revocation certificate.

Publishing your new key

I won’t dwell too much on details, but in brief keyservers are exactly what they sound like – they serve keys out to users. Submitting your key to a keyserver allows other people to search for and download your public key from a keyserver. This saves you having to send a copy to everybody who wants it, for one.

Submitting is simple:-

[andys@sirius ~]$ gpg --keyserver keys.gnupg.net --send-key A0E6B93E
gpg: sending key A0E6B93E to hkp server keys.gnupg.net

Providing there are no errors, your key has been submitted to the keyserver at keys.gnupg.net.

Revocation

There’s a few reasons why you may no longer wish to use a key. It might have been compromised by a 3rd party, or it might simply be that you’ve forgotten the password. That’s why it’s a good idea imperative that you generate a revocation certificate and store it somewhere safe and inaccessible to everyone but you! A revocation certificate allows the holder of the certificate to revoke your key, and ideally the holder will be you and only you.

To generate a revocation certificate:-

[andys@sirius ~]$ gpg --gen-revoke A0E6B93E >A0E6B93E-rev.asc

This then gives us:-

sec  4096R/A0E6B93E 2009-05-08 Andy Smith <andy.smith@netprojects.org.uk>
Create a revocation certificate for this key? (y/N) y

After answering in the affirmative, you’ll be prompted for a reason why you want to revoke the key. In my case, I’m going to choose (3), as the key was created for the purposes of this demonstration, but as you can see there are a number of other options to choose from:-

Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 3

You can now enter a description, which is fairly obvious:-

Enter an optional description; end it with an empty line:
> Demonstration
> [Return]
Reason for revocation: Key is no longer used
Demonstration
Is this okay? (y/N) y

Answer yes, and you’ll again be prompted for your passphrase:-

You need a passphrase to unlock the secret key for
user: "Andy Smith <andy.smith@netprojects.org.uk>"
4096-bit RSA key, ID A0E6B93E, created 2009-05-08
ASCII armoured output forced.
Revocation certificate created.
Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print
system of your machine might store the data and make it available to
others!

At this point, you now have a revocation certificate in A0E6B93E-rev.asc. If you want to revoke this key now (which we do), then import it. It’s important to note that you don’t import the revocation certificate until you actually want to revoke the key. Anyway, here’s how:-

[andys@sirius ~]$ gpg --import <A0E6B93E-rev.asc

You won’t be asked to confirm this action, and you’ll immediately see the following:-

gpg: key A0E6B93E: "Andy Smith <andy.smith@netprojects.org.uk>" revocation certificate imported
gpg: Total number processed: 1
gpg:    new key revocations: 1
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u

This indicates that the key has now been revoked, which we can check by typing:-

[andys@sirius ~]$ gpg -k A0E6B93E
pub   4096R/A0E6B93E 2009-05-08 [revoked: 2009-05-08]
uid                  Andy Smith <andy.smith@netprojects.org.uk>

All that remains is for us to repeat the process we used earlier to submit our key to the keyserver, which this time will send the revoked version of the key:-

[andys@sirius ~]$ gpg --keyserver keys.gnupg.net --send-key A0E6B93E
gpg: sending key A0E6B93E to hkp server keys.gnupg.net

Our key will now appear to be revoked to anyone who looks for it.

Summary

That should just about cover the basics of generating an public/private RSA key pair with GnuPG. There’s a lot more that can be done with it, and having a good read about cryptography in general will help you get your head around some of the fruitier bits.

  • [1] – Thanks to Tero Pesonen who correctly pointed out that I’d originally put 8 bits when of course it’s the last 8 bytes.[2] Cheers Tero!
  • [2] – Thanks also to Tom, who pointed out that both myself and Tero were wrong – it’s the last 4 bytes. I might give up now ;-)

    Further reading

    Thanks to Daniel Kahn Gillmor for his article ‘HOWTO prep for migration off of SHA-1 in OpenPGP‘, which details the digest steps above and was the inspiration for this article. Thanks also to Martin Krafft for his post ‘The need for a GPG revocation certificate‘.

  • 8 comments to GnuPG – RSA key-pair mini-Howto with stronger digests

    Leave a Reply

      

      

      

    You can use these HTML tags

    <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>