1

I realize (using --clearsign) that GnuPG is using SHA256 as the hashing algorithm for signing, but I would like to be able to see the actual SHA256 hash in the signature somewhere. Is there a way with -vv or --list-packets or perhaps with xxd or something like that to show the actual SHA256 hash that is signed?

Also, if I wanted to verify that hash by hand, how would I do it?

  1. GZip cleartext message
  2. Hash the gzip stream with SHA256

Thoughts?

2
  • (1) GPG doesn't necessarily use SHA256 to sign; it depends on the options you specify or configure or the version you use (2) GPG doesn't gzip or otherwise compress when signing; for encryption by default it compresses (but not with gzip) because compression after encryption doesn't work, but after signature does. Commented Feb 11, 2019 at 16:35
  • @dave_thompson_085, True, I mention SHA256 since I know for a fact that in my config it is what is used. I've thumbed through the spec and I'm beginning to think that the whole hash is not in the sig, just the first 16 bits of the hash. The whole hash is signed of course.
    – Dan
    Commented Feb 11, 2019 at 20:25

1 Answer 1

3

I realize (using --clearsign) that GnuPG is using SHA256 as the hashing algorithm for signing, but I would like to be able to see the actual SHA256 hash in the signature somewhere. Is there a way with -vv or --list-packets or perhaps with xxd or something like that to show the actual SHA256 hash that is signed?

Yes, you can make GPG display the signed hash when you create the signature by including the option --debug 1024 when you enter the command to sign. This will write debugging data to STDOUT - look for a line containing the text SETHASH. This will be followed by the hash algorithm ID (8 for SHA256) a space, then the full hash.

You won't be able to see this information with --list-packets because the signature itself only includes the left 16 bits of the hash in the unhashed data portion. As per the OpenPGP specification (RFC-4880) the body of a signature packet is organized as follows:

  1. One-octet version number.
  2. One-octet signature type.
  3. One-octet public-key algorithm.
  4. One-octet hash algorithm.
  5. Two-octet scalar octet count for following hashed subpacket data.
  6. Hashed subpacket data set (zero or more subpackets).
  7. Two-octet scalar octet count for the following unhashed subpacket data.
  8. Unhashed subpacket data set (zero or more subpackets).
  9. Two-octet field holding the left 16 bits of the signed hash value.
  10. One or more multiprecision integers comprising the signature. This portion is algorithm specific.

Also, if I wanted to verify that hash by hand, how would I do it?

The hash is done over a concatenation of the following:

  • (a) The data being signed. In the case of clearsigned text, any line endings are canonicalized with <CR><LF> (0x0d 0x0a).
  • (b) The signature data starting at the version number and ending with the last octet of hashed subpackets (items 1 thru 6 in the list above).
  • (c) An extra trailer which for version 4 signatures consists of the octets 0x04, 0xFF followed by a four-octet big endian number that is the count of octets in (b) from the signature data.

Demonstration with examples

First lets create some text to sign:

$ printf "foo\nbar" > foobar

Now sign it with the debug option:

$ gpg --debug 1024 --digest-algo SHA256 -a --clearsign foobar

In the debug output the hash can be found on this line

gpg: DBG: chan_3 -> SETHASH 8 1A601BF0156447669150C0B06CEDFB24D0A08A55E1E9556ACB49F4918016BC45

Calculating the hash

The generated cleartext signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

foo
bar
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEE5orKzV6pxnr3CiiWM9QrW9OS6+IFAmBv9ZsACgkQM9QrW9OS
6+IaYA/7BqcQI9ENIUGyHtxrePuP59uRzUrXGv1to6EOZPMOq9vl3Bd2rDjmplPN
N0A3egYOWD5Wx3G3ccZzGI0xzNHJEPBPcEnJ5ZOFNlpRrEq+r8r6lP+2Rr+ATa2O
goUX+jWw7yy1DZFaQZVV24dDRdszpxNFusA1l4aMipkSTgfzwrNe/Pm0tgI+YTX3
f/7ccBLpnqw55BGtzvO1dTiz5qXN6UV1eiJgKy/mtfgjiNZRpZUt7BMpV3/m6G2f
xz6rQEdKPW4ILql/mcCaVqrpHSJtNIdCh4Hoabztyt2G8xEBkMX+TkVRQ64NWpc2
RepaS0WTqGUtF/qA0OiBzsE1OOkYA0i1SbrAD4DC+MPh1V6UBI0qK5Obc0Lfj7Gt
oIXpm08OEhdQwr4Q1sDM1IlC7UPRKxv/LZp92/thy7RN3fDl9HCbPJInPGJKevBp
7yqpfkflg5RUIy6LEYqHd/YQi8pnWnwXiMinS/koe33IuJYv/kJrhcSy7wApQ7kS
xqVgGjRm1I5S8D01z0zCeBa7I/sFS+gswmuynjdKJE7W4G65ymehpLLi++J+W+MZ
NX+chJZU3DP2ZZmGqI6qyl0SB6ELE2dRF4vD+6xIm+FIzVrsR3I8eTiCzZiHoSYI
KA7zxKizS9yYxnNQW2DkAMPeNVUnlaA9j8KsWYks+UKTnpvm8Rc=
=oG3T
-----END PGP SIGNATURE-----

Canonicalize signed text: 66 6F 6F 0D 0A 62 61 72

Inspect signature octets:

89 02 33 04 01 01 08 00 1D 16 21 04 E6 8A CA CD 5E A9 C6 7A F7 0A 28 96 33 D4 2B 5B D3 92 EB E2 05 02 60 6F F5 9B 00 0A 09 10 33 D4 2B 5B D3 92 EB E2 1A 60 0F FB 06 A7 10 23 D1 0D 21 41 B2 1E DC 6B 78 FB 8F E7 DB 91 CD 4A D7 1A FD 6D A3 A1 0E 64 F3 0E AB DB E5 DC 17 76 AC 38 E6 A6 53 CD 37 40 37 7A 06 0E 58 3E 56 C7 71 B7 71 C6 73 18 8D 31 CC D1 C9 10 F0 4F 70 49 C9 E5 93 85 36 5A 51 AC 4A BE AF CA FA 94 FF B6 46 BF 80 4D AD 8E 82 85 17 FA 35 B0 EF 2C B5 0D 91 5A 41 95 55 DB 87 43 45 DB 33 A7 13 45 BA C0 35 97 86 8C 8A 99 12 4E 07 F3 C2 B3 5E FC F9 B4 B6 02 3E 61 35 F7 7F FE DC 70 12 E9 9E AC 39 E4 11 AD CE F3 B5 75 38 B3 E6 A5 CD E9 45 75 7A 22 60 2B 2F E6 B5 F8 23 88 D6 51 A5 95 2D EC 13 29 57 7F E6 E8 6D 9F C7 3E AB 40 47 4A 3D 6E 08 2E A9 7F 99 C0 9A 56 AA E9 1D 22 6D 34 87 42 87 81 E8 69 BC ED CA DD 86 F3 11 01 90 C5 FE 4E 45 51 43 AE 0D 5A 97 36 45 EA 5A 4B 45 93 A8 65 2D 17 FA 80 D0 E8 81 CE C1 35 38 E9 18 03 48 B5 49 BA C0 0F 80 C2 F8 C3 E1 D5 5E 94 04 8D 2A 2B 93 9B 73 42 DF 8F B1 AD A0 85 E9 9B 4F 0E 12 17 50 C2 BE 10 D6 C0 CC D4 89 42 ED 43 D1 2B 1B FF 2D 9A 7D DB FB 61 CB B4 4D DD F0 E5 F4 70 9B 3C 92 27 3C 62 4A 7A F0 69 EF 2A A9 7E 47 E5 83 94 54 23 2E 8B 11 8A 87 77 F6 10 8B CA 67 5A 7C 17 88 C8 A7 4B F9 28 7B 7D C8 B8 96 2F FE 42 6B 85 C4 B2 EF 00 29 43 B9 12 C6 A5 60 1A 34 66 D4 8E 52 F0 3D 35 CF 4C C2 78 16 BB 23 FB 05 4B E8 2C C2 6B B2 9E 37 4A 24 4E D6 E0 6E B9 CA 67 A1 A4 B2 E2 FB E2 7E 5B E3 19 35 7F 9C 84 96 54 DC 33 F6 65 99 86 A8 8E AA CA 5D 12 07 A1 0B 13 67 51 17 8B C3 FB AC 48 9B E1 48 CD 5A EC 47 72 3C 79 38 82 CD 98 87 A1 26 08 28 0E F3 C4 A8 B3 4B DC 98 C6 73 50 5B 60 E4 00 C3 DE 35 55 27 95 A0 3D 8F C2 AC 59 89 2C F9 42 93 9E 9B E6 F1 17

The header info tells us the signature body starts at the 4th octet with 04 01 01 08 00 1D - a version 4 signature (0x04) of a canonical text document (0x01) using an RSA key (0x01) and SHA256 hash (0x08) with 29 additional octets (0x00 0x1D) of hashed subpacket data: 04 01 01 08 00 1D 16 21 04 E6 8A CA CD 5E A9 C6 7A F7 0A 28 96 33 D4 2B 5B D3 92 EB E2 05 02 60 6F F5 9B

Since this is a version 4 signature with 35 octets of hashed signature data, we construct the extra trailer: 04 FF 00 00 00 23

This produces the full set of hashed data: 66 6F 6F 0D 0A 62 61 72 04 01 01 08 00 1D 16 21 04 E6 8A CA CD 5E A9 C6 7A F7 0A 28 96 33 D4 2B 5B D3 92 EB E2 05 02 60 6F F5 9B 04 FF 00 00 00 23

Checking the hash:

$ printf '\x66\x6F\x6F\x0D\x0A\x62\x61\x72\x04\x01\x01\x08\x00\x1D\x16\x21\x04\xE6\x8A\xCA\xCD\x5E\xA9\xC6\x7A\xF7\x0A\x28\x96\x33\xD4\x2B\x5B\xD3\x92\xEB\xE2\x05\x02\x60\x6F\xF5\x9B\x04\xFF\x00\x00\x00\x23' | sha256sum
1a601bf0156447669150c0b06cedfb24d0a08a55e1e9556acb49f4918016bc45  -

This matches the hash given in the debug output:

1A601BF0156447669150C0B06CEDFB24D0A08A55E1E9556ACB49F4918016BC45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .