Weryfikujesz podpisane zatwierdzenia Git?


96

W nowszych wersjach gitmożliwe jest podpisywanie poszczególnych zatwierdzeń (oprócz tagów) kluczem PGP:

git commit -m "some message" -S

Możesz pokazać te podpisy na wyjściu git logza pomocą --show-signatureopcji:

$ git log --show-signature
commit 93bd0a7529ef347f8dbca7efde43f7e99ab89515
gpg: Signature made Fri 28 Jun 2013 02:28:41 PM EDT using RSA key ID AC1964A8
gpg: Good signature from "Lars Kellogg-Stedman <lars@seas.harvard.edu>"
Author: Lars Kellogg-Stedman <lars@seas.harvard.edu>
Date:   Fri Jun 28 14:28:41 2013 -0400

    this is a test

Ale czy istnieje sposób na programowe zweryfikowanie podpisu na danym zatwierdzeniu inny niż przez grepowanie wyniku git log? Szukam odpowiednika zatwierdzenia git tag -v- czegoś, co zapewni kod zakończenia wskazujący, czy na danym zatwierdzeniu był ważny podpis.


1
Myślę, że tak powinno być git commit ...i git log .... O ile wiem, gpgnie dodał podpoleceń, które są przekazywane w sposób gitprzejrzysty ... Nie mam żadnych repozytoriów do przetestowania, ale czy git show --show-signature <commitish>działa?
twalberg

show_signaturetylko dodaje rzeczy do wyjścia (patrz github.com/git/git/blob/master/log-tree.c#L370 ).
Emil Sit

Uwaga: wkrótce mieć --rawdo git verify-tag/ git verify-commit. Zobacz moją odpowiedź poniżej
VonC

1
Uwaga: W GIT 2,11 (Q4 2016), git logwprowadza dodatkowe kody stanu E, X, Y, Rna ERRSIG, EXPSIG, EXPKEYSIG, i REVKEYSIG, tak, że użytkownik %G?dostaje więcej informacji. Zobacz moją zredagowaną odpowiedź poniżej
VonC

1
Dzięki Git 2.26 (Q1 2020) nowa konfiguracja gpg.minTrustLevelmoże pomóc przy używaniu git verify-tag/ verify -commit. Zobacz moją zredagowaną odpowiedź poniżej .
VonC

Odpowiedzi:


115

Na wypadek, gdyby ktoś wszedł na tę stronę przez wyszukiwarkę, tak jak ja: Nowe narzędzia zostały udostępnione w ciągu dwóch lat od opublikowania pytania: Istnieją teraz polecenia git do tego zadania: git verify-commiti git verify-tagmogą być używane do weryfikacji zatwierdzeń i tagi.


34

Uwaga: do git 2.5 git verify-commiti git verify-tagwyświetlał tylko komunikat czytelny dla człowieka.
Jeśli chcesz zautomatyzować sprawdzanie, git 2.6+ (Q3 2015) dodaje kolejne wyjście.

Zobacz commit e18443e , commit aeff29d , commit ca194d5 , commit 434060e , commit 8e98e5f , commit a4cc18f , commit d66aeff (21 czerwca 2015) autor: brian m. carlson ( bk2204) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu ba12cb2 , 03 sierpnia 2015)

verify-tag/ verify-commit: dodaj opcję drukowania nieprzetworzonych informacji o stanie gpg

verify-tag/ verify-commitdomyślnie wyświetla dane w postaci czytelnej dla człowieka w przypadku błędu standardowego.
Jednak przydatne może być również uzyskanie dostępu do nieprzetworzonych informacji o stanie gpg, które można odczytać maszynowo, co pozwala na zautomatyzowaną implementację zasad podpisywania .

Dodaj --rawopcję, aby verify-taggenerować informacje o stanie gpg w przypadku standardowego błędu zamiast formatu czytelnego dla człowieka.

Plus:

verify-tagkończy pracę pomyślnie, jeśli podpis jest prawidłowy, ale klucz jest niezaufany. verify-commitwychodzi bezskutecznie.
Ta rozbieżność w zachowaniu jest nieoczekiwana i niepożądana.
Ponieważ verify-tagistniało wcześniej, dodaj test zakończony niepowodzeniem, aby uzyskać zachowanie verify-commitudziału verify-tag.


git 2.9 (czerwiec 2016) zaktualizuj dokument git merge :

Zobacz zatwierdzenie 05a5869 (13 maja 2016) autorstwa Keller Fuchs (``) .
Z pomocą: Junio ​​C Hamano ( gitster) .
(Scalony przez Junio ​​C Hamano - gitster- w zobowiązaniu be6ec17 , 17 maja 2016 r.)

--verify-signatures:
--no-verify-signatures:

Sprawdź, czy zatwierdzenie końcówki scalanej gałęzi bocznej jest podpisane prawidłowym kluczem, tj. Kluczem, który ma prawidłowy identyfikator UID: w domyślnym modelu zaufania oznacza to, że klucz podpisywania został podpisany zaufanym kluczem.
Jeśli zatwierdzenie końcówki gałęzi bocznej nie jest podpisane prawidłowym kluczem, scalanie jest przerywane
.


Zaktualizuj Git 2.10 (III kwartał 2016 r.)

Zobacz commit b624a3e (16 sierpnia 2016) autorstwa Linusa Torvaldsa ( torvalds) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 83d9eb0 , 19 sierpnia 2016 r.)

gpg-interface: preferuje wyjście w formacie „długiego” klucza podczas weryfikacji podpisów pgp

git log --show-signature” i inne polecenia, które wyświetlają stan weryfikacji podpisu PGP, pokazują teraz dłuższy identyfikator klucza, ponieważ 32-bitowy identyfikator klucza jest taki sam w ubiegłym wieku.

Oryginał Linusa został zmieniony, aby zastosować go do ścieżki konserwacyjnej na wypadek, gdyby dystrybutorzy plików binarnych, którzy utknęli w przeszłości, chcieli przenieść go do swojej starszej bazy kodów.


Git 2.11+ (Q4 2016) będzie jeszcze bardziej precyzyjny.

Zobacz commit 661a180 (12 października 2016) autorstwa Michaela J. Grubera ( mjg) .
(Scalone przez Junio ​​C Hamano - gitster- w zobowiązaniu 56d268b , 26 października 2016 r.)

Status weryfikacji GPG pokazany w " %G?" specyfikatorze ładnego formatu nie był wystarczająco bogaty, aby odróżnić podpis złożony przez wygasły klucz, podpis złożony przez odwołany klucz, itp.
Aby je wyrazić, przypisano nowe litery wyjściowe .

Według gpg2doc/DETAILS :

Dla każdego podpisu tylko jeden z kodów GOODSIG, BADSIG, EXPSIG, EXPKEYSIG, REVKEYSIGlub ERRSIGbędą emitowane.

git pretty-formatDokumentacja teraz to:

  • ' %G?': pokaż
    • " G" za dobry (ważny) podpis,
    • B” za zły podpis,
    • U” dla dobrego podpisu o nieznanej ważności,
    • X” za dobry podpis, który wygasł,
    • Y” za dobry podpis wykonany przez wygasły klucz,
    • R” za dobry podpis wykonany przez unieważniony klucz,
    • E” jeśli podpisu nie można sprawdzić (np. brak klucza) i „N” oznacza brak podpisu

Git 2.12 (Q1 2017) " git tag" i " git verify-tag" nauczyli się umieszczać status weryfikacji GPG w swoim " --format=<placeholders>" formacie wyjściowym .

Zobacz commit 4fea72f , commit 02c5433 , commit ff3c8c8 (17 stycznia 2017) autorstwa Santiago Torres ( SantiagoTorres) .
Zobacz commit 07d347c , commit 2111aa7 , commit 94240b9 (17 stycznia 2017) autorstwa Lukasa Puehringera (``) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 237bdd9 , 31 stycznia 2017 r.)

Dodanie --formatdo git tag -vwycisza domyślne wyjście weryfikacji GPG i zamiast tego wyświetla sformatowany obiekt znacznika.
Pozwala to wywołującym na sprawdzenie krzyżowe zmiennej z odnośników / tagów ze zmienną z nagłówka obiektu znacznika po weryfikacji GPG.


Git 2.16 (Q1 2018) pozwoli jeszcze bardziej zautomatyzować weryfikację podpisu zatwierdzenia dzięki merge.verifySignatureszmiennej konfiguracyjnej.

Zobacz commit 7f8ca20 , commit ca779e8 (10 grudnia 2017) autorstwa Hansa Jerry'ego Illikainena (``) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 0433d53 , 28 grudnia 2017 r.)

merge: dodaj opcję konfiguracji dla verifySignatures

git merge --verify-signatures może być użyty do sprawdzenia, czy zatwierdzenie końcówki scalanej gałęzi jest poprawnie podpisane, ale określanie tego za każdym razem jest uciążliwe.

Dodaj opcję konfiguracji, która domyślnie włącza to zachowanie, co może zostać zastąpione przez --no-verify-signatures.

Strona git mergepodręcznika konfiguracji brzmi teraz:

merge.verifySignatures:

Jeśli prawda, jest to równoważne z --verify-signaturesopcją wiersza poleceń.


Git 2.19 (Q3 2018) jest jeszcze bardziej pomocny, ponieważ „ git verify-tag” i „ git verify-commit” zostały nauczone używania statusu wyjścia podstawowego „ gpg --verify” do sygnalizowania złego lub niezaufanego podpisu, który znaleźli.

Uwaga: w przypadku Git 2.19 gpg.formatmożna to ustawić na „ openpgp” lub „ x509” i gpg.<format>.programjest to używane do określenia programu , który ma obsługiwać format), aby umożliwić używanie certyfikatów x.509 z CMS za pośrednictwem „ gpgsm” zamiast openpgpprzez „ gnupg”.

Zobacz commit 4e5dc9c (09 sierpnia 2018) autorstwa Junio ​​C Hamano ( gitster) .
Pomagali: Vojtech Myslivec ( VojtechMyslivec) , brian m. carlson ( bk2204) i Jeff King ( peff) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 4d34122 , 20 sierpnia 2018 r.)

gpg-interface: propaguje status wyjścia z gpgpowrotem do wywołujących

Gdy interfejs API gpg-interface ujednolicił obsługę ścieżek kodowych weryfikacji podpisów dla podpisanych tagów i podpisanych zatwierdzeń w połowie 2015 roku na poziomie około 2.6.0-rc0 ~ 114, przypadkowo poluzowaliśmy weryfikację podpisu GPG.

Przed tą zmianą podpisane zatwierdzenia były weryfikowane poprzez wyszukanie " G" podpisu ood z GPG, z pominięciem statusu wyjścia procesu " gpg --verify", podczas gdy podpisane tagi weryfikowano, po prostu przekazując status wyjścia "gpg --verify"przez".

Zunifikowany kod, który obecnie posiadamy, ignoruje stan wyjścia „ gpg --verify” i zwraca pomyślną weryfikację, gdy podpis pasuje do klucza G, który nie Uwygasł, niezależnie od zaufania pokładanego w kluczu (tj. Oprócz „ ” kluczy ood akceptujemy te niezaufane).

Spraw, aby te polecenia sygnalizowały niepowodzenie ich statusem wyjścia, gdy jest to " gpg --verify" bazowe (lub polecenie niestandardowe określone w gpg.programzmiennej konfiguracyjnej " ").
To zasadniczo zmienia ich zachowanie w sposób niekompatybilny wstecz, aby odrzucać podpisy, które zostały wykonane przy użyciu niezaufanych kluczy, nawet jeśli poprawnie zweryfikują, ponieważ tak " gpg --verify" się zachowuje.

Zwróć uwagę, że kod nadal zastępuje zerowy status wyjścia uzyskany z " gpg" (lub gpg.program), jeśli wynik nie mówi, że podpis jest dobry lub jest obliczany poprawnie, ale wykonany z niezaufanymi kluczami, aby złapać źle napisane opakowanie wokół " gpg", które użytkownik może nam dać .

Moglibyśmy wykluczyć " U" zaufaną obsługę z tego kodu rezerwowego, ale oznaczałoby to wprowadzenie dwóch niekompatybilnych wstecz zmian w jednym zatwierdzeniu, więc na razie unikajmy tego.
W razie potrzeby może to zrobić następcza zmiana.


klucz musi być zaufany / podpisany przed wykonaniem jakiegokolwiek szyfrowania

Po stronie zaufania jest postęp: w
Git 2.26 (Q1 2020) gpg.minTrustLevelwprowadzono zmienną konfiguracyjną, która informuje różne ścieżki weryfikacji podpisów o wymaganym minimalnym poziomie zaufania.

Zobacz commit 54887b4 (27 grudnia 2019) autorstwa Hansa Jerry'ego Illikainena ( illikainen) .
(Scalone przez Junio ​​C Hamano - gitster- w zobowiązaniu 11ad30b , 30 stycznia 2020 r.)

gpg-interface: dodaj minTrustLevel jako opcję konfiguracji

Podpisał: Hans Jerry Illikainen

Wcześniej weryfikacja podpisu dla operacji scalania i ściągania sprawdzała, czy klucz ma poziom zaufania jeden TRUST_NEVERlub TRUST_UNDEFINEDw verify_merge_signature().

Jeśli tak było, proces die()'d.

Inne ścieżki kodu, które przeprowadziły weryfikację podpisu, opierały się całkowicie na kodzie zwrotnym z check_commit_signature().

A podpisy wykonane przy użyciu dobrego klucza, niezależnie od poziomu zaufania, zostały uznane za ważne przez check_commit_signature().

Ta różnica w zachowaniu może skłonić użytkowników do błędnego założenia, że ​​poziom zaufania klucza w ich bazie kluczy jest zawsze uwzględniany przez Git, nawet w przypadku operacji, w których tak nie jest (np. Podczas a verify-commitlub verify-tag) .

Sposób działania polegał na gpg-interface.cprzechowywaniu wyniku stanu klucza / podpisu i dwóch najniższych poziomów zaufania w resultelemencie signature_checkstruktury (ostatnie napotkane wiersze stanu zostały zapisane result).

Są one udokumentowane w GPG odpowiednio w podrozdziale General status codesi Key related.

Dokumentacja GPG mówi o TRUST_ statuskodach, co następuje :


Oto kilka podobnych kodów stanu:

- TRUST_UNDEFINED <error_token>
- TRUST_NEVER     <error_token>
- TRUST_MARGINAL  [0  [<validation_model>]]
- TRUST_FULLY     [0  [<validation_model>]]
- TRUST_ULTIMATE  [0  [<validation_model>]]

W przypadku dobrych podpisów emitowany jest jeden z tych wierszy stanu, aby wskazać ważność klucza użytego do utworzenia podpisu.
Wartości tokenu błędu są obecnie emitowane tylko przez gpgsm.


Moja interpretacja jest taka, że ​​poziom zaufania jest koncepcyjnie różny od ważności klucza i / lub podpisu.

Wydaje się, że było to również założeniem starego kodu, w check_signature()którym wynik „ G” (jak w GOODSIG) i „ U” (jak w TRUST_NEVERlub TRUST_UNDEFINED)oba były uważane za sukces.

Te dwa przypadki, w których rezultatem „ U” miał specjalnego znaczenia były w verify_merge_signature()(gdzie to spowodowało gitby die()) oraz format_commit_one()(jeżeli ma to wpływ na wyjście %G?specyfikacją formatu).

Myślę, że sensowne jest refaktoryzacja przetwarzania TRUST_ statuswierszy w taki sposób, aby użytkownicy mogli skonfigurować minimalny poziom zaufania, który jest wymuszany globalnie, zamiast zlecać wykonanie tego samodzielnie przez poszczególne części git(np. Scalanie) (z wyjątkiem okresu karencji z kompatybilnością wsteczną).

Myślę również, że sensowne jest, aby nie przechowywać poziomu zaufania w tym samym elemencie struktury, co stan klucza / podpisu.

Chociaż obecność TRUST_ statuskodu sugeruje, że podpis jest dobry (zobacz pierwszy akapit powyższego dołączonego fragmentu), o ile wiem, kolejność linii statusu z GPG nie jest dobrze zdefiniowana; w związku z tym wydaje się prawdopodobne, że poziom zaufania mógłby zostać nadpisany statusem klucza / podpisu, gdyby były one przechowywane w tym samym elemencie signature_checkstruktury.

Ta poprawka wprowadza nową opcję konfiguracji: gpg.minTrustLevel.

Konsoliduje weryfikację na poziomie zaufania do struktury gpg-interface.ci dodaje nowego trust_levelczłonka do signature_checkstruktury.

Zgodność z poprzednimi wersjami jest utrzymywana przez wprowadzenie specjalnego przypadku, w verify_merge_signature()którym jeśli nie gpg.minTrustLeveljest ustawiona żadna konfiguracja przez użytkownika , to stare zachowanie odrzucania TRUST_UNDEFINEDi TRUST_NEVERjest wymuszane.

Jeśli, z drugiej strony, gpg.minTrustLeveljest ustawiona, wówczas ta wartość zastępuje stare zachowanie.

Podobnie, specyfikator %G?formatu będzie nadal wyświetlał „ U” dla podpisów utworzonych za pomocą klucza, który ma poziom zaufania równy TRUST_UNDEFINEDlub TRUST_NEVER,nawet jeśli Uznak „ ” już nie istnieje w resultelemencie signature_checkstruktury.

Wprowadzono także nowy specyfikator formatu %GTdla użytkowników, którzy chcą pokazać wszystkie możliwe poziomy zaufania dla podpisu.

Innym podejściem byłoby po prostu odrzucenie wymogu poziomu zaufania verify_merge_signature().

Spowodowałoby to również, że zachowanie byłoby spójne z innymi częściami git, które wykonują weryfikację podpisów.

Jednak wymaganie minimalnego poziomu zaufania do kluczy podpisywania wydaje się mieć prawdziwy przypadek użycia.

Na przykład system kompilacji używany przez projekt Qubes OS obecnie analizuje nieprzetworzone dane wyjściowe z tagu weryfikacyjnego w celu zapewnienia minimalnego poziomu zaufania dla kluczy używanych do podpisywania tagów git .

git config gpgStrona podręcznika zawiera teraz:

gpg.minTrustLevel:

Określa minimalny poziom zaufania do weryfikacji podpisów.
Jeśli ta opcja nie jest ustawiona, weryfikacja podpisu dla operacji scalania wymaga klucza z co najmniej marginalzaufaniem.
Inne operacje, które wykonują weryfikację podpisu, wymagają przynajmniej undefinedzaufania klucza .
Ustawienie tej opcji powoduje przesłonięcie wymaganego poziomu zaufania dla wszystkich operacji. Obsługiwane wartości, w kolejności rosnącej istotności:

  • undefined
  • never
  • marginal
  • fully
  • ultimate

W Git 2.26 (Q1 2020) , " git show" i inni podali nazwę obiektu w formacie surowym w wynikach błędów, która została poprawiona, aby podawać ją w postaci szesnastkowej.

show_one_mergetag: wypisuje nie-rodzica w postaci szesnastkowej.

Kiedy łącznik nazywa obiekt niebędący rodzicem, co może wystąpić po płytkim klonie, jego skrót został wcześniej wydrukowany jako dane surowe.
Zamiast tego wydrukuj go w formie szesnastkowej.

Testowane git -C shallow log --graph --show-signature -n1 plain-shallowpo agit clone --depth 1 --no-local . shallow


W Git 2.27 (drugi kwartał 2020 r.) Zmieniono kod interfejsu z GnuPG.

Zobacz commit 6794898 , commit f1e3df3 ( 04.03.2020 ) autorstwa Hansa Jerry'ego Illikainena ( illikainen) .
(Scalone przez Junio ​​C Hamano - gitster- w zobowiązaniu fa82be9 , 27 marca 2020 r.)

gpg-interface: preferowane check_signature()do weryfikacji GPG

Podpisał: Hans Jerry Illikainen

To zatwierdzenie refaktoryzuje użycie polecenia verify_signed_buffer()outside of gpg-interface.cto use check_signature().

Zmienia się również verify_signed_buffer()w funkcję lokalną dla pliku, ponieważ jest teraz wywoływana tylko wewnętrznie przez check_signature().

Wcześniej istniały dwie funkcje o zasięgu globalnym używane w różnych częściach Gita do weryfikacji podpisów GPG: verify_signed_buffer()i check_signature().

Teraz tylko check_signature()jest używany.

verify_signed_buffer()Funkcja nie ustrzec się przed powielone podpisy jak opisał Michał Górny .

Zamiast tego zapewnia jedynie niezawodny kod wyjścia z GPG i obecność co najmniej jednego GOODSIGpola statusu.

W przeciwieństwie do check_signature()tego zwraca błąd, jeśli napotkano więcej niż jeden podpis.

Niższy stopień weryfikacji sprawia, że ​​korzystanie z niego jest verify_signed_buffer()problematyczne, jeśli dzwoniący nie analizuje i nie weryfikuje samodzielnie różnych części komunikatu o stanie GPG.

Przetwarzanie tych wiadomości wydaje się zadaniem, które powinno być zarezerwowane dla gpg-interface.ctej funkcji check_signature().

Ponadto użycie narzędzi verify_signed_buffer()utrudnia wprowadzenie nowej funkcjonalności zależnej od zawartości linii statusu GPG.

Teraz wszystkie operacje, które wykonują weryfikację podpisu, współużytkują jeden punkt wejścia gpg-interface.c.

Ułatwia to propagowanie zmienionych lub dodatkowych funkcji weryfikacji podpisów GPG do wszystkich części Gita bez dziwnych przypadków brzegowych, które nie wykonują tego samego stopnia weryfikacji .


4

Pobieżna inspekcja kodu sugeruje, że nie ma takiej bezpośredniej metody.

Wszystkie testy w źródle git opierają się na greppingowaniu danych wyjściowych git show(zobacz t / t7510-signed-commit.sh dla testów).

Możesz dostosować dane wyjściowe, używając czegoś takiego, --pretty "%H %G?%"aby ułatwić ich analizę.

Wygląda na to, że możesz poprosić git mergeo weryfikację podpisu, ale ponownie jego testy polegają na grep(patrz t / t7612-merge-verify-signatures.sh ). Wygląda na to, że nieprawidłowy podpis spowoduje git mergewyjście ze złym podpisem, więc potencjalnie możesz dziś zhakować to, wykonując gdzieś testowe scalanie i wyrzucając to scalanie, ale wydaje się to gorsze niż zwykłe wywołanie grep.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.