Structure of gpg keys
By Jonas Plum on
Creating a new nice pgp key I first needed to examine the exact structure of a pgp key.
I used the batch mode of gpg (gpg --status-fd 1 --no-tty --batch --gen-key) to create the key 0x4B9E3333 with the settings:
Key-Type: default
Subkey-Type: default
Name-Real: Cugu
Name-Email: cugu@cugu.eu
Expire-Date: 2020-05-04
Passphrase: password
%pubring foo.pub
%secring foo.sec
%commit
A nice feature here, is that the short name Cugu is allowed, while in command line mode at least five letters are mandatory.
The created public gpg key consists of five single packets.
Public Key Packet #
The first packet contains the public key information as well as creation date. The created key is an RSA key so the public key is the e which is 0x10001 (=65537) in this case. The 2048 bit (256 byte) long n is the modulus for the RSA operation.
The owner of the secret key has the secret RSA exponent d. To sign a message the owner can calculate md mod n = c. Using this public key everyone can afterwards calculate ce mod n = m1 and validate that m1 = m.
99
=======
01 0D 269 length
04 Version 4
53946f6e Creation Date Timestamp
01 RSA
0800 2048
bfde487046d4d5b5460a4682a21ea8b874675a67ffe5a3a9685d45f02a8ad420
b08389f200c6e3cae3b113ef81150ef4bacd15f7c496ee5aca41b18d440d8449
bb791131b3c25ee54c9b10394b4740d70402a9d9316f5ddb9aa741b512b81099
837b46a7f04d11feaa5b69ed630e8c7a94f6c7754f62634ec1663b00aac3c957
23798c69abb619be691e0c990d93e83da2c4d2269ebe1fdece5a517c83c0b567
1e9c4da6010d3b74baada0289b64f24bd6398a6ae652d4b4745ab908955ff04d
a3f87c5ee087bacef35f6f4507f9becdb16425e4d94ae633168ace98e0eb3110
ebd9ce358bc07eb20f411b52cb4334cfdd46ee6d6da8f0f10f83e4ff329a4a41
RSA n
0011 Padding?
010001 RSA e
User ID Packet #
This second packet contains the data that should be bound to the public key from above.
b4
=======
13 Length 19
43756775203c6375677540637567752e65 Cugu <cugu@cugu.eu>
753e
Signature Packet #
This packet binds the User ID Packet to the public key. The content of all the subpackets can be gathered by using pgpdump or reading RFC4880.
The key flags sub packet indicates, that this key can just be used for signing and certification. openpgp shows sc in this case. A capital letter shows, that a sub key is capable of other functions (e.g. capital E -> sub key can be used for encryption)
The most interesting part here is sig(i). i is build by a combination of a lot of information:
- The complete Public Key Packet (e.g. 0x99010D...010001)
- The user ID Packet, where the length is encoded in 4 byte. (e.g. in our case: 0xb40000001343756775203c6375677540637567752e65753e)
- Data from this Signature Packet starting including version till the end of the hashed subpackets (e.g. 0x0413010a...021780)
- A trailer starting with 0x04FF and a 4 byte length of the data from the Signature Packet
All this information is concatenated and hashed. This hash is afterwards appended to a combination of 0x1f followed by many 0xff a single 0x00 and a specification of the used hash (e.g. i=0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440 + hash)
The value 0x3051300d060960864801650304020305000440 for our hash is specified in RFC4880 5.2.2.
All this values (i=0x1f...) is signed: id mod n = sig(i)
89
=======
013d Length 317
04 Version
13 Positive certification of a User ID and Public-Key packet.
01 RSA
0a SHA512
00 27 Length hashed Subpackets 15
05 Length 5
02 Subpacket Type (2 = Signature Creation Time)
53946f6e Timestamp
02 Length 2
1b Subpacket Type (27 = Key Flags)
03
05 Length 5
09 Subpacket (Type 9 = Key Expiration Time)
0b1b7832 Timestamp Offset (186349618 + Creation Time)
05 Length 5
0b Subpacket (Type 11 = Preferred Symmetric Algorithms)
09080703
05 Length 5
15 Subpacket (Type 21 = Preferred Hash Algorithms)
0a09080b
05 Length 5
16 Subpacket (Type 22 = Preferred Compression Algorithms)
02030100
02 Length 2
1e Subpacket (Type 30 = Features)
01 Modification Detection
02 Length 2
17 Subpacket (Type 23 = Key Server Preferences)
80 0x80 = No-modify
00 0a Length unhased Subpackets 10
09 Length 9
10 Subpacket (Type 16 = Issuer)
48c1 f448 4b9e 3333
last 4 blocks of the fingerprint
c678 last 2 byte of the hash over m
0800 2048
816a53faf1135895ad8890c165a32a1d1166e5df41fa43713f02fafdbc55f4f1
848038f55f778550acb76ebab3d6323604342445f7224406edab06c93f46c246
b109b4b18a1ccc71fda28e3f1059d866c2e389f9ab589e76be11e5ef737e1178
f5675425d5f5c4246a04e76d5dc9dc6b93550f0766a57298ed463a9fc6e8bba8
3287f3b5c33eebefbf358e32936e0a316be86d56ac96391e796b8eac7091e215
6a7eae9082369775901c86fcb1ca6c74d8c345d9db6c299923a86d97287209f9
9bedf83b599e561fff370877dd1a7c6fecd632b2d984e7b1c27fbfc80e3a59e2
217b0708b161192e194c204506aed50b20485da514dc29df2128f8ac42fe2458
sig(i)
Public Subkey Packet #
This subkey can be used for encryption. Otherwise this and the following signature packet are built the same way as above.
b9
=======
010d 269 length
04 Version 4
53946f6e Timestamp
01 RSA
0800 2048
aa19801ed96301caaef25633b87eedcecfb31a7363fd798264b1f9fa307728ed
b50f086404930ecbf03f13d807e181ade29268589eba63c459b6e90388d40169
29a63d6e06c4f87289aef3269cd5ba9d31bce6f364ea97513611a84e97a85f32
6b77114e0c4ec3c5249f91fd48783713d0825ef99db56e846562189844454722
67cd4e64d43fa2a305267c0482b968ec00e8cea00b6464ef6e4117095036779a
4b713ec1ad04580b4fcebb66ed8afc3a0e6c315f6790a0c6f2277ae8a017fe9e
67b036cc786d85718cc1d0670dc1c7d688369eb10934e1b3245a183ab70e3068
80cb3f91c8fd389c5e7f46bfd1e3fb70def93900bfbe2cb59faaa1df311d253f
512 bit
0011 Padding?
010001 RSA e
Signature Packet #
89
=======
0125 293 Length
04 Version 4
18 Subkey Binding Signature
01 RSA
0a SHA512
00 0f Length hashed Subpackets 15
05 Length 5
02 Subpacket Type 2 = Signature Creation Time
53946f6e Timestamp
02 Length 2
1b Subpacket Type 27 = Key Flags
0c 1100
05 Length 5
09 Subpacket (Type 9 = Key Expiration Time)
0b1b7832 Timestamp Offset (186349618 + Creation Time)
00 0a Length unhased Subpackets 10
09 Length 9
10 Subpacket (Type 16 = Issuer)
48c1f4484b9e3333
Last 4 Blocks FP
c16e diff
0800 2048
a9b0401874d80f839c407b50e5dcb5ee51e5aafc95933fee013631620a61e69d
63be81e79f35b57cb4cf372ea7bdaa23e9593e18a747101229849cd59517bd75
e8d2965ccf517420906fb649e6f885f927bcabd9f925b80a31d165b12776260f
711ed37d10262d1c103b42fd0baead95529d6c2f10cae24d353dc1e9aa2336ce
9457c4d484eed4416ec1a23a734ca41d146fc79229757a5b7a61f2ac5600cd4c
f800aa118e77dbd32d20c774021dd70f2efb90f00218593e3b00fe97ecbdfc05
633fee7c75bb27aa44d76d9c8c047e7bb1c1d07212c668639bbab1ed9c1288f9
b914da5f600baaa22e911338205c58b2bc1d3282ff54e7801eb8889284686eb3