Quelles données sont en cours de signature lorsque vous git commit –gpg-sign = `?

J’essaie de comprendre comment signer / vérifier les commits à la main, mais je ne sais pas quelles données sont en train d’être signées pour créer la signature. En d’autres termes, je ne peux pas comprendre ce que dans gpg --verify doit être.

Voici le morceau pertinent du code source de git: https://github.com/git/git/blob/master/commit.c#L1047-L1231 mais je suis également novice en C.


Voici quelques exemples de données:

Dans un nouveau repository ledger.txt , je crée un fichier ledger.txt et le ledger.txt avec un commit signé:

 git config --global user.signingkey 7E482429 git init echo "EAC5-531F-38E8-9670-81AE-4E77-C7AA-5FC3-7E48-2429 1\n" > ledger.txt git add ledger.txt git commit -m "Initial commit" --gpg-sign=7E482429 

Et le voici dans le journal:

 git log --show-signature commit 876793da21833b5b8197b08462523fd6aad3e5ba gpg: Signature made Fri May 9 20:01:55 2014 CDT using RSA key ID 7E482429 gpg: Good signature from "Dan Neumann " Author: Dan Neumann  Date: Fri May 9 20:01:55 2014 -0500 Initial commit 

Voici l’object commit très imprimé (qui réside dans .git/objects/87/6793da21833b5b8197b08462523fd6aad3e5ba ):

 git cat-file -p 876793da21833b5b8197b08462523fd6aad3e5ba tree 70e7c184c3a89c749174b4987830c287fd78952d author Dan Neumann  1399683715 -0500 committer Dan Neumann  1399683715 -0500 gpgsig -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTbXqDAAoJEMeqX8N+SCQpTBIH/3zCpf0w0+xp8hkwz7dTV9Bw ercZp4UpxKV1HgqCxu2r/nGIuZyabLwTis1rcwXOVC4DgRxO0f2BiP0xnyL3OhJu CKh8l+HZvvGqVH3Dopm0D/kOxDAWHcjokbyzWBbYJX6WhvT8OI7SSYmwuF4r610h hkZ1xgjo4p1x9WegY296PzA1wEe6yy9BvvdIpJHoqBVKClgFrZvtE5PidbrAyLGF Kl/2f0K3peBdo6XP0Zaml8NyQlFmAlCV831hHgUmZsBSRpgh/WNvrDSNILTlFJgY BOPb2yPP+tiJOXYB66MsjQY9GlX7n43miu5wMtdk1AGqh+26OExbSrZcYVFLk4w= =sRee -----END PGP SIGNATURE----- Initial commit 

Et voici le contenu réel du fichier object commit:

 hexdump .git/objects/87/6793da21833b5b8197b08462523fd6aad3e5ba | \ zlib-decompress | \ bin-to-ascii commit 671\0tree 70e7c184c3a89c749174b4987830c287fd78952d\nauthor Dan Neumann  1399683715 -0500\ncommitter Dan Neumann  1399683715 -0500\ngpgsig -----BEGIN PGP SIGNATURE-----\n Version: GnuPG v1\n \n iQEcBAABAgAGBQJTbXqDAAoJEMeqX8N+SCQpTBIH/3zCpf0w0+xp8hkwz7dTV9Bw\n ercZp4UpxKV1HgqCxu2r/nGIuZyabLwTis1rcwXOVC4DgRxO0f2BiP0xnyL3OhJu\n CKh8l+HZvvGqVH3Dopm0D/kOxDAWHcjokbyzWBbYJX6WhvT8OI7SSYmwuF4r610h\n hkZ1xgjo4p1x9WegY296PzA1wEe6yy9BvvdIpJHoqBVKClgFrZvtE5PidbrAyLGF\n Kl/2f0K3peBdo6XP0Zaml8NyQlFmAlCV831hHgUmZsBSRpgh/WNvrDSNILTlFJgY\n BOPb2yPP+tiJOXYB66MsjQY9GlX7n43miu5wMtdk1AGqh+26OExbSrZcYVFLk4w=\n =sRee\n -----END PGP SIGNATURE-----\n\nInitial commit\n 

Après avoir lu le code dans commit_tree_extended , il semble que les données utilisées pour signer soient la partie allant de “tree” à la fin du commentaire, bien sûr en excluant la signature.

Dans votre exemple, cela devrait être:

 tree 70e7c184c3a89c749174b4987830c287fd78952d author Dan Neumann  1399683715 -0500 committer Dan Neumann  1399683715 -0500 Initial commit 

De la source git :

Init de tampon:

 strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */ strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree)); 

Parent commet traversant:

 /* * NOTE! This ordering means that the same exact tree merged with a * different order of parents will be a _different_ changeset even * if everything else stays the same. */ while (parents) { struct commit_list *next = parents->next; struct commit *parent = parents->item; strbuf_addf(&buffer, "parent %s\n", sha1_to_hex(parent->object.sha1)); free(parents); parents = next; } 

Information personne / date:

 if (!author) author = git_author_info(IDENT_STRICT); strbuf_addf(&buffer, "author %s\n", author); strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_STRICT)); if (!encoding_is_utf8) strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding); while (extra) { add_extra_header(&buffer, extra); extra = extra->next; } strbuf_addch(&buffer, '\n'); 

Le commentaire et l’encodage:

 /* And add the comment */ strbuf_addbuf(&buffer, msg); /* And check the encoding */ if (encoding_is_utf8 && !verify_utf8(&buffer)) fprintf(stderr, commit_utf8_warn); 

C’est là que se passe la signature. La signature sera ajoutée après l’en-tête.

 if (sign_commit && do_sign_commit(&buffer, sign_commit)) return -1; 

Il y aurait aussi des informations sur les parents si votre commit en avait.

Cette réponse est un travail en cours.

Contexte

Premièrement, quelques reflections sur les problèmes liés au mécanisme de signature Git actuel.

Idéalement, Git utiliserait l’un des mécanismes de signature intégrés à GnuPG. Si tel était le cas, il serait facile de vérifier les commits de Git sans avoir à l’invoquer ou à écrire des scripts, en utilisant simplement gpg --verify ou gpg2 --verify .

À cet égard, il est dommage que Git n’ait pas adopté le mécanisme de signature par “signature détachée” de GnuPG, comme proposé sur la liste de diffusion du kernel Linux en 2005 . Plus récemment, Owen Jacobson a énuméré quelques raisons supplémentaires pour lesquelles des signatures détachées seraient souhaitables par rapport à l’approche actuelle de Git. Il fait remarquer qu’actuellement:

  • Les signatures sont intégrées aux objects qu’elles signent. La signature fait partie de l’identité de l’object. étant donné que Git est adressé à un contenu, cela signifie qu’un object ne peut être ni signé rétroactivement ni privé rétroactivement de sa signature sans modifier l’identité de l’object. Le modèle dissortingbué de Git signifie que ces types de changements d’identité sont à la fois compliqués et facilement détectables.

  • Les signatures d’engagement sont des citoyens de seconde classe. Ils constituent un ajout relativement récent à la suite Git et leur mise en œuvre et les conventions sociales qui les entourent continuent d’évoluer.

  • Seuls certains objects peuvent être signés. Bien que Git applique des règles relativement faibles en matière de workflow, le système de signature suppose que vous utilisez l’un des workflows les plus répandus de Git en limitant vos options à au plus une signature et en limitant les signatures aux balises et aux commits ).

Mike Gerwitz souligne l’ une des conséquences les plus graves de l’approche actuelle de Git. Les commits Git ont à la fois un champ “committer” et un “auteur”, ce qui permet à l’auteur et à l’auteur d’un commit d’être deux personnes distinctes. Cependant, les commits Git n’autorisent actuellement l’inclusion que d’une signature. Alors, à qui devrait être la signature? Idéalement, l’auteur et le committer pourraient signer le commit. Les signatures détachées permettraient cela. Il en serait de même pour les signatures en ligne nestedes. Mais comme Git n’utilise aucune de ces options, cela nous oblige à choisir entre deux options peu satisfaisantes:

  1. Le committer enlève la signature de l’auteur et signe lui-même un engagement.

  2. Le committer refuse de signer le commit.

Cela résume les mauvaises nouvelles. La bonne nouvelle est que l’encapsuleur de Git pour GnuPG inclut au moins l’option --show-signature pour le git log , qui vérifie les signatures à l’aide de GnuPG. Cela permet au journal Git d’indiquer si une clé portant un UID que vous avez placé en confiance a été ou non signée.

Si c’est le cas, GnuPG affichera:

 Good signature from "John Doe " 

Sinon, GnuPG affichera:

 Good signature from "John Doe " WARNING: This key is not certified with a trusted signature! There is no indication that the signature belongs to the owner. 

Ta question

Comme indiqué dans la réponse de Poko , votre commit semble, à première vue, être équivalent au document clairement signé suivant:

 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 tree 70e7c184c3a89c749174b4987830c287fd78952d author Dan Neumann  1399683715 -0500 committer Dan Neumann  1399683715 -0500 Initial commit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTbXqDAAoJEMeqX8N+SCQpTBIH/3zCpf0w0+xp8hkwz7dTV9Bw ercZp4UpxKV1HgqCxu2r/nGIuZyabLwTis1rcwXOVC4DgRxO0f2BiP0xnyL3OhJu CKh8l+HZvvGqVH3Dopm0D/kOxDAWHcjokbyzWBbYJX6WhvT8OI7SSYmwuF4r610h hkZ1xgjo4p1x9WegY296PzA1wEe6yy9BvvdIpJHoqBVKClgFrZvtE5PidbrAyLGF Kl/2f0K3peBdo6XP0Zaml8NyQlFmAlCV831hHgUmZsBSRpgh/WNvrDSNILTlFJgY BOPb2yPP+tiJOXYB66MsjQY9GlX7n43miu5wMtdk1AGqh+26OExbSrZcYVFLk4w= =sRee -----END PGP SIGNATURE----- 

Cependant, supposons que nous sauvegardions cela sous le nom danneau_stackoverflow_example.asc et que nous danneau_stackoverflow_example.asc de le vérifier, voici le résultat:

 $ gpg --verify danneau_stackoverflow_example.asc gpg: Signature made Sat 10 May 2014 02:01:55 BST gpg: using RSA key C7AA5FC37E482429 gpg: Can't check signature: public key not found 

Ce que GnuPG entend par là, c’est que, parce que je n’ai pas votre clé publique, elle ne peut pas réellement dire si la signature est bonne ou mauvaise. Donc, même si je modifie le contenu, je reçois le même résultat:

 $ echo "-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 tree 70e7c184c3a89c749174b4987830c287fd78952d author Dan Neumann  1399683715 -0500 committer Dan Neumann  1399683715 -0500 EVIL MESSAGE HERE -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTbXqDAAoJEMeqX8N+SCQpTBIH/3zCpf0w0+xp8hkwz7dTV9Bw ercZp4UpxKV1HgqCxu2r/nGIuZyabLwTis1rcwXOVC4DgRxO0f2BiP0xnyL3OhJu CKh8l+HZvvGqVH3Dopm0D/kOxDAWHcjokbyzWBbYJX6WhvT8OI7SSYmwuF4r610h hkZ1xgjo4p1x9WegY296PzA1wEe6yy9BvvdIpJHoqBVKClgFrZvtE5PidbrAyLGF Kl/2f0K3peBdo6XP0Zaml8NyQlFmAlCV831hHgUmZsBSRpgh/WNvrDSNILTlFJgY BOPb2yPP+tiJOXYB66MsjQY9GlX7n43miu5wMtdk1AGqh+26OExbSrZcYVFLk4w= =sRee -----END PGP SIGNATURE----- " | gpg --verify - gpg: Signature made Sat 10 May 2014 02:01:55 BST gpg: using RSA key C7AA5FC37E482429 gpg: Can't check signature: public key not found 

Cela signifie donc que Poko n’a peut-être pas correctement compris ce que vous avez signé après tout.

Afin d’aller au fond des choses , j’ai essayé de convertir les commits, signés par des clés privées dont je possède les clés publiques correspondantes, en fichiers clairement signés, et de les transmettre à GnuPG pour vérification. Jusqu’à présent, je n’ai jamais reçu que des réponses “Bad signature”. Si je découvre où je me trompe, je mettrai à jour cette réponse.