4 votes

Comment GPG génère-t-il une empreinte MD5 à partir d'une clé publique ?

J'ai la clé publique GPG suivante stockée dans un fichier appelé publickey.pub et codé en ASCII Armor (Radix-64) :

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.3ia

mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N
syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J
+oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR
tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF
EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3
p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e
cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF
hiXZ
=K7lL
-----END PGP PUBLIC KEY BLOCK-----

Si je tape :

$ gpg --with-fingerprint publickey.pub

J'ai l'empreinte digitale de la clé :

Empreinte de la clé = 00 C9 21 8E D1 AB 70 37 DD 67 A2 3A 0A 6F 8D A5

Maintenant, comment GPG fait-il ? Je veux dire, y a-t-il une commande que je peux exécuter sans utiliser gpg et obtenir toujours la même empreinte digitale ? Avec SSH, par exemple, étant donné une clé publique, je peux faire ce qui suit :

$ cat ~/.ssh/id_rsa.pub | awk '{print $2}' | base64 -D | md5

Et cela retournera le même hachage que :

$ ssh-keygen -l -f ~/.ssh/id_rsa.pub

Je sais que le contenu réel de la clé publique devrait être :

mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N
syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J
+oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR
tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF
EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3
p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e
cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF
hiXZ

Sans le dernier =K7lL qui fait référence à la somme de contrôle CRC encodée en Base64. Mais si je tape :

$ echo -n "mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N
>     syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J
>     +oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR
>     tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF
>     EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3
>     p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e
>     cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF
>     hiXZ" | base64 -D | md5

J'obtiens le résultat suivant :

4697e84969da935454c7f2cdc19aaf08

Ce qui, comme vous pouvez le voir, ne correspond pas 00 C9 21 8E...

Vérifier la RFC 4880 -> https://www.rfc-editor.org/rfc/rfc4880#section-12.2 :

Pour une clé V3, l'identifiant de clé de huit octets est constitué des 64 bits inférieurs de l'identifiant de clé V3.
le modulus public de la clé RSA.

L'empreinte digitale d'une clé V3 est formée par le hachage du corps (mais pas de la clé V3). la longueur de deux octets) des MPI qui constituent le matériel de la clé (public, privé, privé).
module n, suivi de l'exposant e) avec MD5. Notez que les deux clés V3
et MD5 sont obsolètes.

Une empreinte digitale V4 est le hachage SHA-1 de 160 bits de l'octet 0x99,
suivi de la longueur du paquet de deux octets, suivi de l'ensemble de l'information
Paquet de clés publiques commençant par le champ version. L'ID de la clé est le 64 bits de poids faible de l'empreinte digitale.

Comment cela se traduit-il par une commande en ligne de commande ?

EDIT 1 : J'essaie de faire cela avec pgpdump -i :

$ pgpdump -i publickey.pub
Old: Public Key Packet(tag 6)(141 bytes)
    Ver 3 - old
    Public key creation time - Mon Apr 28 17:19:48 MSD 1997
    Valid days - 0[0 is forever]
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(1024 bits) - d6 76 92 93 7f a0 c9 33 e2 da b3 c6 f2 8f 67 0b 3f 5f 0b 03 d1 8f 84 e7 fc bb 3f 60 c8 c3 8b 87 4b fe 0d b3 24 1b 82 47 6b 66 13 c1 95 70 ef eb c0 d0 8a 81 d7 5a c6 fd d3 8a b2 af b8 99 07 52 c2 e4 8b 4a f4 c8 2a 94 af 99 da 6b cf aa c1 9b 1c cf 09 fa 86 22 6f c9 1f db 32 7a 1e fa d8 ac fe cd 60 1d 2d 37 d6 18 ba 6d 88 0a dc 7e 84 88 ba 68 a1 97 74 1d 40 4c 0e 5e af 06 26 bb 43 7d 
    RSA e(5 bits) - 11 
Old: User ID Packet(tag 13)(41 bytes)
    User ID - Ralf S. Engelschall <rse@engelschall.com>
Old: Signature Packet(tag 2)(149 bytes)
    Ver 3 - old
    Hash material(5 bytes):
        Sig type - Generic certification of a User ID and Public Key packet(0x10).
        Creation time - Mon Apr 28 17:19:48 MSD 1997
    Key ID - 0x0E5EAF0626BB437D
    Pub alg - RSA Encrypt or Sign(pub 1)
    Hash alg - MD5(hash 1)
    Hash left 2 bytes - 29 5a 
    RSA m^d mod n(1023 bits) - 62 bf fb 8a 5c c2 1c 68 93 e1 64 b8 bc 02 e4 f9 ee 87 fd 68 78 e6 07 88 a6 30 c7 46 77 a7 4f 51 2e f0 ed 36 57 6b e9 50 fe 68 bf 49 96 dc 5d 3d 30 11 cd 9f 0c e7 45 2a a0 5f 63 32 bd b9 1a 27 e1 78 56 21 8a 5c 30 e3 53 95 64 0d de 70 b5 e5 2e 07 5a d7 eb 74 bd 6b 37 12 0f e2 d9 bd 1a ad 04 03 68 8a bb 3d e4 5d 8d d1 03 83 09 c6 e3 10 5a a9 a0 2a 7e 0c 70 39 72 7e 2c f5 85 86 25 d9 
        -> PKCS-1

Comment dois-je extraire le module et l'exposant ? Je suppose que je devrais faire quelque chose avec cette partie de la sortie :

Hash left 2 bytes - 29 5a 
RSA m^d mod n(1023 bits) - 62 bf fb 8a 5c c2 1c 68 93 e1 64 b8 bc 02 e4 f9 ee 87 fd 68 78 e6 07 88 a6 30 c7 46 77 a7 4f 51 2e f0 ed 36 57 6b e9 50 fe 68 bf 49 96 dc 5d 3d 30 11 cd 9f 0c e7 45 2a a0 5f 63 32 bd b9 1a 27 e1 78 56 21 8a 5c 30 e3 53 95 64 0d de 70 b5 e5 2e 07 5a d7 eb 74 bd 6b 37 12 0f e2 d9 bd 1a ad 04 03 68 8a bb 3d e4 5d 8d d1 03 83 09 c6 e3 10 5a a9 a0 2a 7e 0c 70 39 72 7e 2c f5 85 86 25 d9  

J'ai essayé de faire écho aux valeurs binaires de ces chiffres hexadécimaux :

29 5a (hachage des 2 octets restants) concaténé avec : 62 bf fb 8a 5c c2 1c 68 93 e1 64 b8 bc 02 e4 f9 ee 87 fd 68 78 e6 07 88 a6 30 c7 46 77 a7 4f 51 2e f0 ed 36 57 6b e9 50 fe 68 bf 49 96 dc 5d 3d 30 11 cd 9f 0c e7 45 2a a0 5f 63 32 bd b9 1a 27 e1 78 56 21 8a 5c 30 e3 53 95 64 0d de 70 b5 e5 2e 07 5a d7 eb 74 bd 6b 37 12 0f e2 d9 bd 1a ad 04 03 68 8a bb 3d e4 5d 8d d1 03 83 09 c6 e3 10 5a a9 a0 2a 7e 0c 70 39 72 7e 2c f5 85 86 25 d9

Et la commande à laquelle j'ai abouti était :

$ echo -ne "\x29\x5a\x62\xbf\xfb\x8a\x5c\xc2\x1c\x68\x93\xe1\x64\xb8\xbc\x02\xe4\xf9\xee\x87\xfd\x68\x78\xe6\x07\x88\xa6\x30\xc7\x46\x77\xa7\x4f\x51\x2e\xf0\xed\x36\x57\x6b\xe9\x50\xfe\x68\xbf\x49\x96\xdc\x5d\x3d\x30\x11\xcd\x9f\x0c\xe7\x45\x2a\xa0\x5f\x63\x32\xbd\xb9\x1a\x27\xe1\x78\x56\x21\x8a\x5c\x30\xe3\x53\x95\x64\x0d\xde\x70\xb5\xe5\x2e\x07\x5a\xd7\xeb\x74\xbd\x6b\x37\x12\x0f\xe2\xd9\xbd\x1a\xad\x04\x03\x68\x8a\xbb\x3d\xe4\x5d\x8d\xd1\x03\x83\x09\xc6\xe3\x10\x5a\xa9\xa0\x2a\x7e\x0c\x70\x39\x72\x7e\x2c\xf5\x85\x86\x25\xd9" | md5

Ce qui devrait produire les données binaires de ces chiffres hexadécimaux, puis calculer le hachage MD5 sur ces données binaires, mais le hachage que j'obtiens est toujours différent :

6f09f2ac5c5af1c6dd3833e584387103

Je sais que je m'y prends mal, mais je n'ai pas trouvé d'informations sur la façon d'interpréter les données de l'enquête. pgpdump correctement et quelles parties de ce que je dois concaténer et ensuite hacher...

EDIT : Grâce à Jens Erat, avec ce petit "geeking des empreintes digitales d'OpenPGP" je peux conclure que :

Pour Clés V3 RSA 1024 bit Les clés sont hachées avec MD5 l'empreinte digitale est calculée par rapport à 129 octets composés de l 128 octets de l RSA n MPI (qui commence à l'offset de l'octet 14 (à condition que le premier octet soit à l'offset 1 ) de la clé publique OpenPGP brute exportée avec gpg --export $UID ) concaténée avec 1 qui est l'octet à l'offset 144 et donc d'omettre le 2 longueur octets à l'offset 142 y 143 comme le dit la RFC 4880.

La commande suivante calcule l'empreinte digitale en utilisant les données GPG brutes et :

gpg --export $UID | xxd -p | tr -d '\n ' | tail \
-c +27 | cut -c -256,261-262 | sed -e 's/[0-9a-fA-F]\{2\}/\\\\x&/g' | while read TMP; do \
echo -ne $TMP; done | md5 | sed -e 's/[0-9a-f]\{2\}/ &/g' | \
awk '{print "\n MD5 fingerprint:"toupper($0)"\n"}' 

Où $UID est l'UID du détenteur de la clé.

Pour les clés publiques OpenPGP V4 RSA, l'histoire est différente :

Pour les clés publiques RSA de 2048 bits, l'empreinte digitale est obtenue en hachant les 272 premiers octets des données brutes de la clé OpenPGP avec SHA1 :

gpg --export $UID | head -c 272 | shasum | grep -Eo "[0-9a-f]+" | sed -e 's/[0-9a-f]\{4\}/ &/g' | \
awk '{print "\n RSA 2048 bit SHA1 fingerprint:"toupper($0)"\n"}'

Pour les clés publiques RSA de 4096 bits, l'empreinte digitale est obtenue en hachant les 528 premiers octets des données brutes de la clé OpenPGP avec SHA1 :

gpg --export $UID | head -c 528 | shasum | \
grep -Eo "[0-9a-f]+" | sed -e 's/[0-9a-f]\{4\}/ &/g' | \
awk '{print "\n RSA 4096 SHA1 fingerprint:"toupper($0)"\n"}'

Cela devrait suffire. Quoi qu'il en soit, en utilisant gpgsplit avec les touches V4 semble être plus portable.

4voto

Jens Erat Points 16432

Pour les clés OpenPGP, ce n'est pas aussi facile qu'avec SSH. L'empreinte digitale n'est pas calculée à partir de l'ensemble de la clé publique encodée en Base64, mais seulement sur certaines parties (binaires) de celle-ci.

Pour une clé OpenPGP version 3, ce que vous devez faire est :

  1. Analyse le paquet de clés publiques OpenPGP
  2. Pour RSA, extraire le module et l'exposant.
  3. Concaténer leurs valeurs binaires
  4. Calculer le hashsum

Pour les étapes 1 et 2, vous pouvez compter sur l'outil pgpdump qui peut analyser et afficher les nombres en utilisant la fonction -i drapeau.

Pour les clés de la version 4, c'est encore plus compliqué.

Si vous voulez calculer le hashsum à des fins pédagogiques, je vous recommande d'étendre pgpdump à la place et utiliser tout le code d'analyseur disponible, de sorte que vous puissiez travailler directement sur les informations extraites. Je suis presque sûr que la manipulation de l'information binaire sera plus facile qu'avec du code Shell pur, également.

UPDATE Tu as utilisé les mauvais nombres entiers. Utilisez ceux des lignes RSA n y RSA e à la place. Mettre tout en place en quelques lignes en utilisant des outils standards :

pgpdump -i publickey.pub | \
grep -E '(RSA n|RSA e)' | \
cut -d'-' -f2 | \
tr -d "\n " | \
perl -e 'print pack "H*", <STDIN>' | \
md5sum

pgpdump -i jette les MPIs de la clé, que nous grep dehors, cut de tout ce dont on n'a pas besoin, tr supprimer tous les espaces, convertir en binaire en utilisant perl et enfin calculer le md5sum .

Je fonctionne avec la clé que vous avez fournie :

$ pgpdump -i publickey.pub | \
> grep -E '(RSA n|RSA e)' | \
> cut -d'-' -f2 | \
> tr -d "\n " | \
> perl -e 'print pack "H*", <STDIN>' | \
> md5sum
00c9218ed1ab7037dd67a23a0a6f8da5  -

Ça semble correspondre à ce que nous recherchons.

Par souci d'exhaustivité, il en va de même pour les clés de la version 4, pour lesquelles vous avez besoin d'une autre chaîne d'outils. Nous avons besoin du paquet complet de clés publiques. Pour décomposer un message OpenPGP, gpgsplit est très utile. Ensuite, vous pouvez immédiatement calculer le sha1sum du fichier :

gpgsplit publickey.pub; sha1sum *.public_key

Par exemple, en fonctionnant sur ma propre clé :

$ gpgsplit publickey.pub; sha1sum *.public_key
0d69e11f12bdba077b3726ab4e1f799aa4ff2279  000001-006.public_key

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X