# Manually creating a GPG Public Key

I want to manually create a GPG public key that can be imported into GPG, i.e. I want to create a file with a Public-Key Packet, a User ID Packet and a Signature Packet (for an example see here). I already managed to correctly create a Public-Key Packet with a User ID Packet and a Signature Packet, except for the hash/signature of the Signature Packet.

I tried to hash data as described in RFC 4880, however the description there is rather imprecise. For example it does not state what exactly constitutes a public key body (is it only n or also the public exponent e?) or if "tags" are to be hashed as well. With tags I mean fixed data preceding certain elements of a packet (e.g. for the public exponent e the tag is 00 11; see here).

Unfortunately the GPG source code and its resulting binary are also not very helpful for understanding what data exactly is hashed. I am currently tracing the export function (i.e. gpg --export) but I can't find the function that is used to hash the data for the Signature Packet (interestingly enough, neither the hash_public_key() function in g10/keyid.c nor the make_keysig_packet() function in g10/sign.c seem to be used for that).

Does anyone know what exactly is hashed and can exemplify it?

• i found the solution, i will post it shortly – D.O. Jul 7 '20 at 14:42

Based on the example given in the question (see here) the following (hex-encoded) bytes would be hashed:

From the Public-Key Packet

Ciphertype Byte: 99

Key Length: 01 0d

Version: 04

CreatedAt: 5e f4 a2 c6

Algorithm: 01

n (with tag): 08 00 a8 14 6d b3 75 12 72 33 1e 92 54 c5 43 f6 44 d2 22 5d 4d 9b 0c b8 5d 60 60 8b f0 39 08 1e 31 29 e2 f5 4c 83 e0 71 b7 22 e3 f8 78 9b c4 a2 c1 aa 70 72 3a eb c5 1e ec d1 65 9b 58 50 20 f4 d0 36 db 79 c8 24 6a bd 43 3f 08 28 6c 35 b2 16 30 6b 14 4c 94 74 5a fa 85 5a 05 8d 06 3b 94 29 f1 98 71 f4 04 48 9b 84 ef b9 94 65 eb 9c 0a 97 b6 d2 46 13 64 42 57 13 ea 08 48 62 5f 24 ea f3 d5 f5 2b 72 b6 96 e0 af ac 4b 68 41 af fc 64 cd 55 a1 75 05 33 ed 0b 78 a2 6c d4 33 d5 db 6a 72 78 78 9c ae 45 74 08 d2 40 72 30 4d f2 62 ea 29 6e d9 e8 5d 12 cf a0 7a e6 60 44 29 06 75 4f d0 71 c8 9f 35 8a 45 52 45 20 04 7a 79 cc 54 8e ba 10 1b ae f0 9e 24 68 56 98 18 10 2b f5 95 c1 5a 50 57 5a 47 6f e5 61 44 f7 2f 86 fe 8c 54 a1 4d a8 13 68 e6 e2 b4 57 aa 2f fa c5 06 fc 13 47 98 23 c7

e (with tag): 00 11 01 00 01


From the User ID Packet

Ciphertype Byte: b4

Length: 00 00 00 1c

UserID: 47 50 47 20 54 65 73 74 20 4b 65 79 20 3c 74 65 73 74 40 74 65 73 74 2e 63 6f 6d 3e


From the Signature Packet

Version: 04

Signature Type: 13

Public Key Algorithm: 01

Hash Algorithm: 0a

Hashed Data Count: 00 38

Undefined Subpacket Length: 16

Undefined Subpacket Type: 21

Undefined Subpacket Data: 04 43 3f bc 55 ab 6d 09 17 21 13 18 3a 79 1a 5a be 3e 62 44 95

Creation Time Subpacket Length: 05

Creation Time Subpacket Type: 02

Creation Time Subpacket Data: 5e f4 a2 c6

Key Flags Subpacket Length: 02

Key Flags Subpacket Type: 1b

Key Flags Subpacket Data: 2f

Preferred Symmetric Algorithms Subpacket Length: 05

Preferred Symmetric Algorithms Subpacket Type: 0b

Preferred Symmetric Algorithms Subpacket Data: 09 08 07 02

Preferred Hash Algorithms Subpacket Length: 06

Preferred Hash Algorithms Subpacket Type: 15

Preferred Hash Algorithms Subpacket Data: 0a 09 08 0b 02

Preferred Compression Algorithms Subpacket Length: 04

Preferred Compression Algorithms Subpacket Type: 16

Preferred Compression Algorithms Subpacket Data: 02 03 01

Features Subpacket Length: 02

Features Subpacket Type: 1e

Features Subpacket Data: 01

Key Server Preferences Subpacket Length: 02

Key Server Preferences Subpacket Type: 17

Key Server Preferences Subpacket Data: 80


Other Data

Trailer: 04 ff

Big-Endian Count of Hashed Signature Packet Data: 00 00 00 3e


Full Byte Array (i.e. a concatenation of the bytes in 'From the Public-Key Packet', 'From the User ID Packet', 'From the Signature Packet', and 'Other Data'):

99 01 0d 04 5e f4 a2 c6 01 08 00 a8 14 6d b3 75 12 72 33 1e 92 54 c5 43 f6 44 d2 22 5d 4d 9b 0c b8 5d 60 60 8b f0 39 08 1e 31 29 e2 f5 4c 83 e0 71 b7 22 e3 f8 78 9b c4 a2 c1 aa 70 72 3a eb c5 1e ec d1 65 9b 58 50 20 f4 d0 36 db 79 c8 24 6a bd 43 3f 08 28 6c 35 b2 16 30 6b 14 4c 94 74 5a fa 85 5a 05 8d 06 3b 94 29 f1 98 71 f4 04 48 9b 84 ef b9 94 65 eb 9c 0a 97 b6 d2 46 13 64 42 57 13 ea 08 48 62 5f 24 ea f3 d5 f5 2b 72 b6 96 e0 af ac 4b 68 41 af fc 64 cd 55 a1 75 05 33 ed 0b 78 a2 6c d4 33 d5 db 6a 72 78 78 9c ae 45 74 08 d2 40 72 30 4d f2 62 ea 29 6e d9 e8 5d 12 cf a0 7a e6 60 44 29 06 75 4f d0 71 c8 9f 35 8a 45 52 45 20 04 7a 79 cc 54 8e ba 10 1b ae f0 9e 24 68 56 98 18 10 2b f5 95 c1 5a 50 57 5a 47 6f e5 61 44 f7 2f 86 fe 8c 54 a1 4d a8 13 68 e6 e2 b4 57 aa 2f fa c5 06 fc 13 47 98 23 c7 00 11 01 00 01 b4 00 00 00 1c 47 50 47 20 54 65 73 74 20 4b 65 79 20 3c 74 65 73 74 40 74 65 73 74 2e 63 6f 6d 3e 04 13 01 0a 00 38 16 21 04 43 3f bc 55 ab 6d 09 17 21 13 18 3a 79 1a 5a be 3e 62 44 95 05 02 5e f4 a2 c6 02 1b 2f 05 0b 09 08 07 02 06 15 0a 09 08 0b 02 04 16 02 03 01 02 1e 01 02 17 80 04 ff 00 00 00 3e


Resulting Hash

2f 9b ad fd 89 90 e9 34 f3 15 c6 9c c5 8e 45 12 47 29 fe ab e6 18 a2 e2 71 fb bf e1 9e 20 10 8a 86 ea d9 dd 5b 87 58 87 45 85 98 2a 68 14 e9 e2 ef 9e b6 07 12 1d 9b 7c 15 8f 58 79 c2 92 c5 e9


The two first bytes of the generated hash are shown in the signedHashValuePrefix of the used example (which was generated with the GPG CLI).