Using PGP keys with perl-rsa

Heres a description of how to use Mark Shoulson <>'s (check directory listing for latest version) utility to extract your public and private keys from PGP, so that you can use them with perl-rsa. There is a detached signature file for the pgpacket utility also, so you can check it hasn't been tampered with since he wrote it.

You just give pgpacket a PGP file and it tells you what's in it.

Obtaining your public key

So once you have obtained the pgpacket (unsing the link above), you will be able to do this to extract your public exponent and RSA modulus:
% pubring.pgp

And it will decode the entire contents of your public key ring in
human readable form.

However there are typically lots of public keys in your
public key ring, so either grep for the entry you want, or extract
the public key you want to a file first:

% pgp -kx <user> <file>
% <file>
The output should look something like this (newer version of pgpacket may have slightly different format, but E and N are what you are looking for):
Packet Type:    Public Key Packet
Length: 141
Version Byte:   2
Key Created:    8 Jun 1993  09:34:57
Valid forever
Algorithm:      1 (RSA)
N:      99D61071378EE2C0C8C9C4B7786B203DEDF2D6E526F24F7E83F3E0F960FB66B9CB81C04E89D70689A4866F21AD1BB5BA6AEE51469E5B59B121BA6F3F8D776B627253BA5DC9FCA8155A565B9893F695D83A0496EB977EE4659EE20E0F2EB49B2593C11487B377CC5D767C79FB985B464D4AE94A5F45E42E3B29C8B89D556A4A67
E:      13
There will be others pieces of information after that, a user-id packet, maybe some signatures, etc. Btw that really is my public key, spot the last 8 hex digits of the RSA modulus N: 556A4A67, ie my key-id, as you might use to look me up on a keyserver: 0x556A4A67. That is all the key-id is, it is the last 8 LSBytes of your RSA modulus.

Obtaining your Secret Key

The method applies to your secret key. However there is a complication, PGP won't give your secret key up so easily. You must first use PGP to decrypt your secret key and save it plain text form.

Security Warning

You ought to be careful about doing this, having your secret key on your disk in plain text format is a bad idea from a security point of view. The best thing to do if you wish to use this method is to generate a PGP key especially for playing with perl-rsa, that way you do not risk playing with the plaintext version of your real PGP secret key. If you want to do it to your real PGP key, well you have been warned, and be aware that file systems are not always very secure, and even on laptops, the file system is only as secure as your physical security, ie a lot less secure than having your PGP key encrypted.

Getting the key

So once you've generated your key for test purposes, or whatever. When PGP asks you for a passphrase to encrypt your freshly generated test key with, just press ENTER twice, when you do this PGP does not encrypt your secret key.

(If you already encrypted it, you can have PGP unencrypt it by changing your passphrase with the pgp -ke option. Just change your passphrase to be a blank passphrase, ie just press ENTER twice when asked for your new passphrase)

Once you have done that, extract your secret key into a file, or just blast the whole keyring through pgpacket, and go search for your key in the output.

To see your entire secret key ring (won't be too big, unless you've got a whole load of test keys lying around like me):

% secring.pgp
or to get just the seckey you are after in a file, and then view that only:
% pgp -kx <user> <file> secring.pgp
% <file>
The field you will be looking for is the D field, N will be the same number as in your public key. PGP keeps P and Q, and U around also for efficiency reasons, but all you need for perl-rsa is E, N and D.
Packet Type:    Secret Key Packet
Length: 192
Version Byte:   3
Key Created:    25 Jun 1995  20:47:16
Valid forever
Algorithm:      1 (RSA)
N:      CF7C85AAA6BBEA6A928AA4AFDE623260533606FE88BE78914242A0148EAD3D11AAC9B3287715690FA9E2F2C85A5AD16B
E:      11
Protection Algorithm:   0 (None)
D:      0C348055551A1CD917ADCD73C1C98A7E23032D968083ACBD24F99DED5809B7F20C867AB224C7500A2CF30301419E90F1
P:      D9BEAD898AAB1AEE84D7E1740C63D293D30689FE7F2CA16B
Q:      F3F075C82B5CEB105103ABDFF97545CEDAB935B47FA69001
U:      4104F5EE44267FAAB8BDFF62F020E9B28E94CEC78152AA24
Checksum:       40C3
That example secret key (I'm hardly gonna show you mine) is the 384 bit BlackNet key which Paul Leyland and friends factored a while back.

In case you were curious, here's a brief explanation of how these numbers are related.

N = P x Q,
(M^E)^D = M (mod N) and (M^D)^E = M (mod N) for all M st 0 <= M < N
P < Q and P x U = 1 (mod Q)

Trying it out

We'll use the 384 bit BlackNet key, as determined above, the relevant numbers are public exponent (E), RSA modulus (N), and private exponent (D).

So lets try encrypting the message 'hello world' with the black net key and perl-rsa:

n = CF7C85AAA6BBEA6A928AA4AFDE623260533606FE88BE7891

e = 11

d = 0C348055551A1CD917ADCD73C1C98A7E23032D968083ACBD

So encrypt:

% cat > msg
hello world
% rsa -k=[e] -n=[n] < msg > msg.rsa

Where [e] and [n] are the keys above, ie paste this into your shell:

% rsa -k=11 -n=CF7C85AAA6BBEA6A928AA4AFDE623260533606FE88BE78914242A0148EAD3D11AAC9B3287715690FA9E2F2C85A5AD16B < msg > msg.rsa

and decrypt:

% rsa -d -k=[d] -n=[n] < msg.rsa 
ie paste this into your shell.
% rsa -d -k=0C348055551A1CD917ADCD73C1C98A7E23032D968083ACBD24F99DED5809B7F20C867AB224C7500A2CF30301419E90F1 -n=CF7C85AAA6BBEA6A928AA4AFDE623260533606FE88BE78914242A0148EAD3D11AAC9B3287715690FA9E2F2C85A5AD16B < msg.rsa
(Encrypt will be faster than decrypt because we are using a small public exponent (hex 11 = 17) where as the secret exponent (d) is a big number, it'll take 30 seconds or so to decrypt).

So we have just demoed encrypt and decrypt with the blacknet key, which Paul Leyland broke with a 1000 or so MIP years of compute. The security lesson to extract from Paul's demo breaking is this: don't use small keys! You should be using minimum 1024, perhaps even 2048, both of which PGP copes with easily.

Comments, html bugs to me (Adam Back) at <>