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
- 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

Version: BCPG v1.39


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.)

Ps. As for "hash context", other places where the term is used, particularly section, 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 particular, in various parts of the RFC, it is recommended that several hashes be computed in parallel by maintaining multiple hash contexts (i.e. hash object instances).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.