# OpenPGP Signature Packet hashed data

RFC 4880 describes the version 4 signature packet, tag 2, as

- One-octet signature type.
- One-octet public-key algorithm.
- One-octet hash algorithm.
- Two-octet scalar octet count for following hashed subpacket data.
Note that this is the length in octets of all of the hashed
subpackets; a pointer incremented by this number will skip over
the hashed subpackets.
- Hashed subpacket data set (zero or more subpackets).
- Two-octet scalar octet count for the following unhashed subpacket
data. Note that this is the length in octets of all of the
unhashed subpackets; a pointer incremented by this number will
skip over the unhashed subpackets.
- Unhashed subpacket data set (zero or more subpackets).
- Two-octet field holding the left 16 bits of the signed hash
value.
- One or more multiprecision integers comprising the signature.


and i assume that the second to last line means just take the string of the hashed subpacket and hash it with the hash algorithm and take its first 2 bytes. however, no matter what i do, i cannot seem to get it.

I generated this fake key a long time ago

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BCPG v1.39

GRLsCCbE6vOOh7XQVZGzLEBy9WNzZ9m+EbCfSVAYkjS6FhLws6hG6irrnS+b3JBf
gFJ8vNGF9Z7bhx+7y7NBk0IMyWkGnUkcnav73t5FQUI2faEBN4c/yAGJZwCgjcB7
3akWk9XVWvTCsiMXxpyvkukEALXsvB6cOoFEtQq9cQHjP63fBlvD94dhhMiM0cH6
hW9JotxdK+cxFGG9ZIWgoN2PWbMJka/H4W5EL6tS+YiNAR7I1Ozkt6X16GjnQUzZ
MlSpleK+KiKVN2anRaPEoOIinHrE3ZXd6QlJ/4+OJn4IVWmSEaJpFf4QNgvEu4rh
7GT/M38F+TrpBobag1O3buE99fOLyws4Tbc+sZMdHxoiGZDAIRNQS2rv475E6ktj
bUBhYWEuY29tPohGBBMRAgAGBQJOQdIfAAoJEDBSJUXPd92GRSQAoItbtbToOg7a
/hcg2sA/aBEQNwuxAKCGR69vmSoCWoBP5waPk0UsjM3BSbjMBE5B0h8QAgCUlP7A
lfO4XuKGVCs4NvyBpd0KA0m0wjndOHRNSIz44x24vLfTO0GrueWjPMqRRLHO8zLJ
S/BXO/BHo6ypjN87Af0VPV1hcq20MEW2iujh3hBwthNwBWhtKdPXOndJGZaB7lsh
LJuWv9z6WyDNXj/SBEiV1gnPm0ELeg8Syhy5pCjMAf9QHehP2eCFqfEwTAnaOlA6
CU+rYHKPZaI9NUwCA7qD2d93/l08/+ZtFvejZW1RWrJ8qfLDRtlPgRzigoF/CXbR
iEYEGBECAAYFAk5B0h8ACgkQMFIlRc933YZRrACfUnWTjHHN+QsEEoJrwRvFmvzj
bR4An24pTpeeN+I6R59O/sdmYsAhjULX
=sStS
-----END PGP PUBLIC KEY BLOCK-----


From pgpdump.net, i see that the left 2 bytes of the hash (SHA 1) value is 45 24 for the first signature packet and 51 ac for the second one. i am getting 52 f0 for both. obviously, im not including some information, but what is it? the hashed subpackets are identical, and all of the data before the hashed data are the same as well except they are different types of signature packets (0x13 / 0x18). i have been unable to get either of the correct hash values even when i add/take characters from the data packet. the key im generating is exactly the same as the key shown here except for the hash values.

what is the data that i should be hashing??

the key example up there is made up of packet 6 + packet 13 + packet 2 + packet 14 + packet 2. i have tried all sorts of combinations of packet 6, packet 13, and packet 2 (from version number to hashed data inclusive), but still cannot find the string that hashes to the correct values

EDIT: From Ilmari Karonen's suggestion that i read section 5.2.4, i still cannot get the answer

i have been using:

a = entire public key packet, header and all
b = entire user id packet, header and all
c = signature packet '\x04' ... '\x1f' (version ... end of hashed subpacket)


and hashing in all sorts of different ways. Depending on what hash context and data (for the user id: is it just the user info, or is it the entire packet? either way i try does not work) mean, the correct method can be anything, which i still cannot find.

how are the hashes of the body and two trailers combined? is that what hash context defines?

-

I believe the answer can be found in section 5.2.4, "Computing Signatures". According to that section, what you actually need to hash is the concatenation of:

• the key packet (with an old-style packet header with a two-byte length — but your sample key packet has that header type already),
• for the first (certification) signature, the constant byte 0xB4, a four-byte number giving the length of the user ID packet body, and the user ID packet body itself,
• for the second (subkey binding) signature, the subkey packet (using the same type of header as for the key packet above),
• a "trailer" consisting of the beginning of the signature packet body, from the version number field to the end of the hashed subpacket data, and
• a final six-byte trailer consisting of the bytes 0x04 and 0xFF, and a four-byte big-endian number giving the length of the "trailer" string from the previous string.

I haven't checked if that will actually produce the correct hashes for your packet, but I believe it should.

Note that I've simplified the description somewhat; you should actually read section 5.2.4 of the RFC carefully to figure out just what goes into the hash under various circumstances, since it appears to depend on many things.

EDIT: While simplifying, I accidentally left out some pretty major parts. :( I've added them in now, hopefully this time I've got everything that's needed. Alas, I can't really check it now either, and probably won't have much chance of participating here during this week.

(Oh, and yes, I agree, that all looks like an awful mess. I assume there are reasons for all the quirks, and that it probably looks easier to read in source code form, but that doesn't make it any less messy.)

-
What does it mean when it says hash context? –  calccrypto Jun 3 '12 at 1:52
Other places where the term "hash context" is used, particularly section 3.7.1.1, suggest that it basically means an object or data structure that contains the internal state of the hash function and supports methods for providing further input and for finalizing the hash and returning the output. (Most cryptographic hash implementations provide such an API.) In various parts of the RFC, it is recommended that several hashes be computed in parallel by maintaining multiple hash contexts. –  Ilmari Karonen Jun 3 '12 at 15:59
so when it says hash into the hash context, it means just update the instance of the hash algorithm? that is equivalent to just concatenating the strings, and it doesnt work –  calccrypto Jun 3 '12 at 19:01
i got it!!!! thanks! –  calccrypto Jun 3 '12 at 19:44
@calccrypto: Ps. I realized that I missed some parts of the hash input when reading the RFC myself. I've updated my answer, hopefully all the parts of the input are there now. Alas, I probably won't be able to fix any possibly remaining mistakes before next week or later. –  Ilmari Karonen Jun 3 '12 at 20:03
show 1 more comment