keygrip format

Daniel Kahn Gillmor dkg at
Thu Dec 7 23:17:22 CET 2017

On Thu 2017-12-07 22:40:19 +0100, Werner Koch wrote:
> The Libgcrypt keygrip is in general different from the PCKS-15 keygrip.
> With the exception of RSA the Libgcrypt keygrip always includes an
> identifier for the algorithm.

What identifier?  Is this documented somewhere other than the source

From what i can see, _gcry_pk_get_keygrip() in cipher/pubkey.c doesn't
inject the header directly, and just initializes the digest object and
invokes the comp_keygrip member of the pk_spec.

And the comp_keygrip member of the rsa pk_spec is compute_keygrip in
cipher/rsa.c, which just passes the raw data to the message digest

> I tried to keep the RSA keygrip similar to the PCKS-15 defined one
> but:
> /* Compute a keygrip.  [...]
>    PKCS-15 says that for RSA only the modulus should be hashed -
>    however, it is not clear whether this is meant to use the raw bytes
>    (assuming this is an unsigned integer) or whether the DER required
>    0 should be prefixed.  We hash the raw bytes.  */

OK, so i tried to replicate this for RSA and i failed :(

0 dkg at alice:~$ gpg --with-keygrip --with-key-data --list-keys D238EA65D64C67ED4C3073F28A861B1C7EFD60D9
gpg: please do a --check-trustdb
uid:q::::1413720402::D49001903ADA4875E769A87C05F25BD14DD7A7D9::Werner Koch (Release Signing Key)::::::::::0:
0 dkg at alice:~$ 

the grp: line has the keygrip, and the pkd:0: line is the modulus,

So, we should be able to compute that in python, but i'm not seeing it,
with the raw bytes in either order:

In [1]: import hashlib, codecs

In [2]: keydata = codecs.decode('B493C79928398DA9D99AC0E949FE6EB62F683CB974FFFBF
   ...: BC01066F5C9A89BD3DC48EAD7C65F36EA943C2B2C865C26C4884FF9EDFDA8C99C855B737
   ...: D77EEF6B85DBC0CCEC0E900C1F89A6893A2A93E8B31028469B6927CEB2F08687E547C686
   ...: B0A2F7E50A194FF7AB7637E03DE0912EF7F6E5F1EC37625BD1620CCC2E7A56431E168CDA
   ...: FBD1D9E61AE47A69A6FA03EF22F844528A710B2392F262B95A3078CF321DC8325F92A569
   ...: 1EF69F34FD0DE0B22C79D29DC87723FCADE463829E8E5F7D196D73D6C9C180F6A6A0DDBF
   ...: 7B9D8F7FA293C36163B12199EF6A1A95CAE4051E3069C522CC6C4A7110F663A5DAD20F66
   ...: C13A1674D050088208FAE4F33B3AB5103', 'hex')

In [3]: hashlib.sha1(keydata).hexdigest()
Out[3]: '805cfd0a15e427ef8345c01ae6657b4de888ea13'

In [4]: hashlib.sha1(bytes(reversed(keydata))).hexdigest()
Out[4]: '92ab5f591661031b7270edc61119e67faf47382f'

neither Out[3] nor Out[4] is 'e56ee6ee5a2fdc3e989dfe49daf56743e3272833',
which i'd expect from the grp: line above.

What am i doing wrong in python here?

> For ECC we hash an s-expression with all curve parameters in a well
> defined order.  For other algorithms we use the standard Libgcrypt
> s-expression using the parameters in the order given by Libgcrypt's
> implementation.

This sounds like something that needs to be publicly documented if
there's any intent to allow other implementations to talk to gpg-agent,
or to do anything else which requires knowing the keygrip corresponding
to a public key.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <>

More information about the Gnupg-devel mailing list