(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 DemonstrationIs 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-08ASCII 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.

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‘.
- The comp.security.pgp FAQ – http://www.pgp.net/pgpnet/pgp-faq/
- HOWTO prep for migration off of SHA-1 in OpenPGP (Daniel Kahn Gillmor / Debian Administration)
- The need for a GPG revocation certificate (Martin Krafft)
- Pretty Good Privacy (Wikipedia)
Thank you for an excellent article. I have been searching for two days for something to help me understand how to implement good and usable security keys. This article did it for me.
Tim
Andy-
Thanks for posting this handy article – just what I needed. Nitpick: some examples were truncated in my Chrome+Linux environment. E.g “Command> setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 Z”
Keep up the good work,
-Tyler
Hi Tyler,
I’ve just noticed that they are on mine, too. I reposted it from my old site, and I must have missed out a few lines when checking they all fitted in. I’ll update it later on today!
Cheers for the tip and for the feedback
Funny how [1] is just as wrong even with the correction. It is 8 hexadecimal digits, hence the last 32 bits or four bytes!
Just noticed this on Debian box but I moved over to my Ubuntu box and it looks as things may have finally changed with gpg 1.4.10:
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Is it possible to remove 3Des cipher option, or to verify that it wasn’t used for encryption ?
3DES is required by the OpenPGP standard, so it must be present.
[…] This post was mentioned on Twitter by OpenPGP Bot, Gabriele Farinelli. Gabriele Farinelli said: bits | andy smith's blog » GnuPG – RSA key-pair mini-Howto with stronger digests: http://bit.ly/gcbdfV […]