Xác minh cam kết git đã ký?


95

Với các phiên bản mới hơn git, bạn có thể ký các cam kết riêng lẻ (ngoài các thẻ) bằng khóa PGP:

git commit -m "some message" -S

Và bạn có thể hiển thị các chữ ký này trong đầu ra của git logvới --show-signaturetùy chọn:

$ 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

Nhưng có cách nào để xác minh theo chương trình chữ ký trên một cam kết nhất định không bằng cách ghi đầu ra của git log? Tôi đang tìm kiếm tương đương với cam kết git tag -v- thứ gì đó sẽ cung cấp mã thoát cho biết liệu có chữ ký hợp lệ trên một cam kết nhất định hay không.


1
Tôi nghĩ rằng nên git commit ...git log .... Theo như tôi biết, gpgđã không thêm các lệnh con được chuyển đến một gitcách minh bạch ... Tôi không có bất kỳ đại diện nào để kiểm tra, nhưng có git show --show-signature <commitish>hoạt động không?
twalberg

show_signaturechỉ thêm những thứ vào đầu ra (xem github.com/git/git/blob/master/log-tree.c#L370 ).
Emil Sit

Lưu ý: bạn sẽ sớm có --rawcho git verify-tag/ git verify-commit. Xem câu trả lời của tôi bên dưới
VonC

1
Lưu ý: Với Git 2.11 (Q4 2016), git loggiới thiệu thêm mã trạng thái E, X, Y, Rcho ERRSIG, EXPSIG, EXPKEYSIG, và REVKEYSIG, vì vậy mà người dùng của %G?được biết thêm thông tin. Xem câu trả lời đã được chỉnh sửa của tôi bên dưới
VonC

1
Với Git 2.26 (Q1 2020), cấu hình mới gpg.minTrustLevelcó thể trợ giúp khi sử dụng git verify-tag/ verify -commit. Xem câu trả lời đã chỉnh sửa của tôi bên dưới .
VonC

Câu trả lời:


114

Đề phòng trường hợp ai đó truy cập trang này thông qua một công cụ tìm kiếm, như tôi đã làm: Các công cụ mới đã được cung cấp trong hai năm kể từ khi câu hỏi được đăng: Hiện có các lệnh git cho tác vụ này: git verify-commitgit verify-tagcó thể được sử dụng để xác minh các cam kết và tương ứng.


34

Lưu ý: tối đa git 2.5 git verify-commitgit verify-tagchỉ hiển thị một thông báo con người có thể đọc được.
Nếu bạn muốn tự động kiểm tra, git 2.6+ (Q3 2015) sẽ thêm một đầu ra khác.

Xem cam kết e18443e , cam kết aeff29d , cam kết ca194d5 , cam kết 434060e , cam kết 8e98e5f , cam kết a4cc18f , cam kết d66aeff (21 tháng 6 năm 2015) bởi brian m. carlson ( bk2204) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- in commit ba12cb2 , 03/08/2015)

verify-tag/ verify-commit: thêm tùy chọn để in thông tin trạng thái gpg thô

verify-tag/ verify-committheo mặc định hiển thị đầu ra mà con người có thể đọc được trên lỗi tiêu chuẩn.
Tuy nhiên, nó cũng có thể hữu ích khi truy cập vào thông tin trạng thái gpg thô, có thể đọc được bằng máy, cho phép thực hiện tự động chính sách ký kết .

Thêm --rawtùy chọn để tạo verify-tagthông tin trạng thái gpg trên lỗi chuẩn thay vì định dạng con người có thể đọc được.

Thêm:

verify-tagthoát thành công nếu chữ ký tốt nhưng khóa không đáng tin cậy. verify-committhoát không thành công.
Sự khác biệt trong hành vi là bất ngờ và không mong muốn.
Kể từ khi verify-tagtồn tại trước đó, hãy thêm một bài kiểm tra không đạt để có hành vi verify-commitchia sẻ verify-tag.


git 2.9 (tháng 6 năm 2016) cập nhật git merge doc :

Xem cam kết 05a5869 (ngày 13 tháng 5 năm 2016) bởi Keller Fuchs (``) .
Người hỗ trợ: Junio ​​C Hamano ( gitster) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- in cam kết be6ec17 , ngày 17 tháng 5 năm 2016)

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

Xác minh rằng cam kết mẹo của nhánh bên đang được hợp nhất được ký bằng một khóa hợp lệ, tức là khóa có uid hợp lệ: trong mô hình tin cậy mặc định, điều này có nghĩa là khóa ký đã được ký bởi một khóa đáng tin cậy.
Nếu cam kết đầu của nhánh bên không được ký bằng khóa hợp lệ, hợp nhất sẽ bị hủy bỏ
.


Cập nhật Git 2.10 (Quý 3 năm 2016)

Xem cam kết b624a3e (16 tháng 8, 2016) của Linus Torvalds ( torvalds) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 83d9eb0 , ngày 19 tháng 8 năm 2016)

gpg-interface: ưu tiên đầu ra định dạng khóa "dài" khi xác minh chữ ký pgp

" git log --show-signature" và các lệnh khác hiển thị trạng thái xác minh của chữ ký PGP hiện hiển thị key-id dài hơn, vì key-id 32-bit là thế kỷ trước.

Bản gốc của Linus đã được phục hồi để áp dụng cho theo dõi bảo trì trong trường hợp các nhà phân phối nhị phân bị mắc kẹt trong quá khứ muốn đưa nó vào cơ sở mã cũ hơn của họ.


Git 2.11+ (Q4 2016) thậm chí sẽ chính xác hơn.

Xem cam kết 661a180 (12 tháng 10 năm 2016) của Michael J Gruber ( mjg) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 56d268b , ngày 26 tháng 10 năm 2016)

Trạng thái xác minh GPG được hiển thị trong trình %G?xác định định dạng đẹp "" không đủ phong phú để phân biệt chữ ký được tạo bởi khóa hết hạn, chữ ký được tạo bởi khóa bị thu hồi, v.v.
Các chữ cái xuất mới đã được chỉ định để thể hiện chúng .

Theo gpg2'sdoc/DETAILS :

Đối với mỗi chữ ký duy nhất một trong các mã GOODSIG, BADSIG, EXPSIG, EXPKEYSIG, REVKEYSIGhoặc ERRSIGsẽ được phát ra.

Các git pretty-formattài liệu hiện nay bao gồm:

  • ' %G?': hiển thị
    • " G" cho một chữ ký tốt (hợp lệ),
    • " B" cho một chữ ký xấu,
    • " U" cho một chữ ký tốt nhưng không rõ giá trị,
    • " X" cho một chữ ký tốt đã hết hạn,
    • " Y" cho một chữ ký tốt được tạo bởi một khóa đã hết hạn,
    • " R" cho một chữ ký tốt được tạo bởi một khóa đã bị thu hồi,
    • " E" nếu không thể kiểm tra chữ ký (ví dụ thiếu khóa) và "N" nếu không có chữ ký

Git 2.12 (Q1 2017) " git tag" và " git verify-tag" đã học cách đặt trạng thái xác minh GPG ở --format=<placeholders>định dạng đầu ra " " của chúng .

Xem cam kết 4fea72f , cam kết 02c5433 , cam kết ff3c8c8 (17 tháng 1 năm 2017) bởi Santiago Torres ( SantiagoTorres) .
Xem cam kết 07d347c , cam kết 2111aa7 , cam kết 94240b9 (17/01/2017) bởi Lukas Puehringer (``) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 237bdd9 , ngày 31 tháng 1 năm 2017)

Thêm --formatđể git tag -vtắt tiếng đầu ra mặc định của xác minh GPG và thay vào đó in đối tượng thẻ được định dạng.
Điều này cho phép người gọi kiểm tra chéo tên thẻ từ refs / thẻ với tên thẻ từ tiêu đề đối tượng thẻ khi xác minh GPG.


Git 2.16 (Q1 2018) sẽ cho phép xác minh chữ ký cam kết thậm chí còn tự động hơn, với merge.verifySignaturesbiến cấu hình.

Xem cam kết 7f8ca20 , cam kết ca779e8 (10 tháng 12 năm 2017) bởi Hans Jerry Illikainen (``) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- in cam kết 0433d53 , 28 thg 12, 2017)

merge: thêm tùy chọn cấu hình cho verifySignatures

git merge --verify-signatures có thể được sử dụng để xác minh rằng cam kết mẹo của nhánh được hợp nhất đã được ký đúng cách hay chưa, nhưng thật phức tạp khi phải chỉ định điều đó mọi lúc.

Thêm tùy chọn cấu hình cho phép hành vi này theo mặc định, có thể bị ghi đè bởi --no-verify-signatures.

Các git mergetrang người đàn ông cấu hình bây giờ đọc:

merge.verifySignatures:

Nếu đúng, điều này tương đương với --verify-signaturestùy chọn dòng lệnh.


Git 2.19 (Quý 3 năm 2018) thậm chí còn hữu ích hơn vì " git verify-tag" và " git verify-commit" đã được dạy cách sử dụng trạng thái thoát của cơ sở " gpg --verify" để báo hiệu chữ ký xấu hoặc không đáng tin cậy mà họ tìm thấy.

Lưu ý: với Git 2.19, gpg.formatcó thể được đặt thành " openpgp" hoặc " x509" và gpg.<format>.programđược sử dụng để chỉ định chương trình nào sẽ sử dụng để xử lý định dạng) để cho phép sử dụng chứng chỉ x.509 với CMS qua " gpgsm" thay vì openpgpqua " gnupg".

Xem cam kết 4e5dc9c (09/08/2018) bởi Junio ​​C Hamano ( gitster) .
Được trợ giúp bởi: Vojtech Myslivec ( VojtechMyslivec) , brian m. carlson ( bk2204)Jeff King ( peff) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 4d34122 , ngày 20 tháng 8 năm 2018)

gpg-interface: thông báo trạng thái thoát từ gpgtrở lại người gọi

Khi hỗ trợ hợp nhất API gpg-interface cho các đường dẫn xác minh chữ ký cho các thẻ đã ký và các cam kết đã ký vào giữa năm 2015 ở khoảng v2.6.0-rc0 ~ 114, chúng tôi đã vô tình nới lỏng xác minh chữ ký GPG.

Trước khi thay đổi đó, các cam kết đã ký đã được xác minh bằng cách tìm kiếm " G" chữ ký xác thực từ GPG, đồng thời bỏ qua trạng thái thoát của gpg --verifyquy trình "", trong khi các thẻ đã ký được xác minh bằng cách chuyển trạng thái thoát của "gpg --verify"qua.

Mã hợp nhất mà chúng tôi hiện có bỏ qua trạng thái thoát của " gpg --verify" và trả về xác minh thành công khi chữ ký khớp với khóa chưa hết hạn bất kể độ tin cậy được đặt trên khóa (nghĩa là ngoài " G" khóa, chúng tôi chấp nhận " U" khóa không tin cậy ).

Làm cho các lệnh này báo hiệu thất bại với trạng thái thoát của chúng khi bên dưới " gpg --verify" (hoặc lệnh tùy chỉnh được chỉ định bởi gpg.programbiến cấu hình "") làm như vậy.
Điều này về cơ bản thay đổi hành vi của chúng theo cách không tương thích ngược để từ chối các chữ ký được tạo bằng khóa không đáng tin cậy ngay cả khi chúng xác minh chính xác, vì đó là cách " gpg --verify" hoạt động.

Lưu ý rằng mã vẫn ghi đè trạng thái thoát 0 nhận được từ " gpg" (hoặc gpg.program) nếu đầu ra không cho biết chữ ký là tốt hoặc tính toán chính xác nhưng được thực hiện bằng các khóa không đáng tin cậy, để bắt một trình bao bọc được viết kém xung quanh " gpg" mà người dùng có thể cung cấp cho chúng tôi .

Chúng tôi có thể loại trừ Uhỗ trợ đáng tin cậy "" khỏi mã dự phòng này, nhưng điều đó sẽ tạo ra hai thay đổi không tương thích ngược trong một cam kết duy nhất, vì vậy hãy tránh điều đó ngay bây giờ.
Một thay đổi tiếp theo có thể làm như vậy nếu muốn.


chìa khóa cần được tin cậy / ký trước khi thực hiện bất kỳ mã hóa nào

Về mặt tin cậy, có sự tiến bộ:
Với Git 2.26 (Q1 2020), gpg.minTrustLevelbiến cấu hình đã được giới thiệu để cho các đường dẫn xác minh chữ ký khác nhau biết mức độ tin cậy tối thiểu cần thiết.

Xem cam kết 54887b4 (ngày 27 tháng 12 năm 2019) của Hans Jerry Illikainen ( illikainen) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 11ad30b , ngày 30 tháng 1 năm 2020)

gpg-interface: thêm minTrustLevel làm tùy chọn cấu hình

Ký tên: Hans Jerry Illikainen

Trước đây, xác minh chữ ký cho các hoạt động hợp nhất và kéo kiểm tra nếu phím đã có một niềm tin cấp của một trong hai TRUST_NEVERhoặc TRUST_UNDEFINEDtrong verify_merge_signature().

Nếu đúng như vậy, quy trình die()'d.

Các đường dẫn mã khác đã thực hiện xác minh chữ ký hoàn toàn dựa vào mã trả về từ check_commit_signature().

Và chữ ký được tạo bằng một khóa tốt, không có bất thường về mức độ tin cậy của nó, được coi là hợp lệ check_commit_signature().

Sự khác biệt về hành vi này có thể khiến người dùng giả định một cách sai lầm rằng mức độ tin cậy của một khóa trong chuỗi khóa của họ luôn được Git xem xét, ngay cả đối với các hoạt động không phải như vậy (ví dụ: trong một verify-commithoặc verify-tag) .

Cách nó hoạt động là gpg-interface.clưu trữ kết quả từ trạng thái khóa / chữ ký hai mức tin cậy thấp nhất trong resultthành viên của signature_checkcấu trúc (dòng trạng thái cuối cùng gặp phải đã được ghi vào result).

Những điều này được ghi lại trong GPG dưới phần phụ General status codesKey relatedtương ứng.

Tài liệu GPG cho biết những điều sau trên các TRUST_ status :


Đây là một số mã trạng thái tương tự:

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

Đối với chữ ký tốt, một trong những dòng trạng thái này được phát ra để cho biết tính hợp lệ của khóa được sử dụng để tạo chữ ký.
Các giá trị mã thông báo lỗi hiện chỉ được phát ra bởi gpgsm.


Cách giải thích của tôi là mức độ tin cậy khác về mặt khái niệm với hiệu lực của khóa và / hoặc chữ ký.

Đó dường như cũng là giả định của mã cũ trong check_signature()đó kết quả của ' G' (như trong GOODSIG) và ' U' (như trong TRUST_NEVERhoặc TRUST_UNDEFINED)cả hai đều được coi là thành công.

Hai trường hợp kết quả của ' U' có ý nghĩa đặc biệt là trong verify_merge_signature()(nơi này gây ra gitđể die()) và trong format_commit_one()(nơi mà nó ảnh hưởng đến đầu ra của %G?specifier định dạng).

Tôi nghĩ việc cấu trúc lại quá trình xử lý các TRUST_ statusdòng để người dùng có thể định cấu hình mức độ tin cậy tối thiểu được thực thi trên toàn cầu là rất hợp lý, thay vì để các bộ phận riêng lẻ git(ví dụ: hợp nhất) tự thực hiện (ngoại trừ thời gian gia hạn với khả năng tương thích ngược).

Tôi cũng nghĩ rằng việc không lưu trữ mức độ tin cậy trong cùng một thành viên cấu trúc giống như trạng thái khóa / chữ ký là rất hợp lý.

Mặc dù sự hiện diện của một TRUST_ statusđoạn mã ngụ ý rằng chữ ký đó là tốt (xem đoạn đầu tiên trong đoạn mã bao gồm ở trên), theo như tôi có thể nói, thứ tự của các dòng trạng thái từ GPG không được xác định rõ ràng; do đó, có vẻ hợp lý rằng mức độ tin cậy có thể được ghi đè bằng trạng thái khóa / chữ ký nếu chúng được lưu trữ trong cùng một thành viên của signature_checkcấu trúc.

Vá này giới thiệu một tùy chọn cấu hình mới: gpg.minTrustLevel.

Nó hợp nhất xác minh mức độ tin cậy gpg-interface.cvà thêm một trust_levelthành viên mới vào signature_checkcấu trúc.

Khả năng tương thích ngược được duy trì bằng cách đưa ra một trường hợp đặc biệt verify_merge_signature()mà nếu không có người dùng có thể định cấu hình gpg.minTrustLevelđược đặt, thì hành vi từ chối cũ TRUST_UNDEFINEDTRUST_NEVERđược thực thi.

Mặt khác, nếu gpg.minTrustLevelđược đặt, thì giá trị đó sẽ ghi đè hành vi cũ.

Tương tự, bộ %G?định dạng sẽ tiếp tục hiển thị ' U' cho các chữ ký được tạo bằng khóa có mức độ tin cậy TRUST_UNDEFINEDhoặc TRUST_NEVER,ngay cả khi Uký tự '' không còn tồn tại trong resultthành viên của signature_checkcấu trúc.

Một bộ định dạng mới %GT, cũng được giới thiệu cho những người dùng muốn hiển thị tất cả các mức độ tin cậy có thể có cho một chữ ký.

Một cách tiếp cận khác sẽ đơn giản là bỏ yêu cầu mức độ tin cậy vào verify_merge_signature().

Điều này cũng sẽ làm cho hành vi nhất quán với các phần khác của git thực hiện xác minh chữ ký.

Tuy nhiên, việc yêu cầu mức độ tin cậy tối thiểu để ký khóa dường như có một trường hợp sử dụng trong thế giới thực.

Ví dụ: hệ thống xây dựng được sử dụng bởi dự án Qubes OS hiện phân tích cú pháp đầu ra thô từ thẻ xác minh để xác nhận mức độ tin cậy tối thiểu cho các khóa được sử dụng để ký thẻ git .

Các git config gpgtrang người đàn ông hiện nay bao gồm:

gpg.minTrustLevel:

Chỉ định mức tin cậy tối thiểu để xác minh chữ ký.
Nếu tùy chọn này không được đặt, thì xác minh chữ ký cho các hoạt động hợp nhất yêu cầu một khóa có độ marginaltin cậy ít nhất .
Các hoạt động khác thực hiện xác minh chữ ký yêu cầu một khóa có độ undefinedtin cậy tối thiểu .
Đặt tùy chọn này sẽ ghi đè mức độ tin cậy cần thiết cho tất cả các hoạt động. Các giá trị được hỗ trợ, theo thứ tự ý nghĩa ngày càng tăng:

  • undefined
  • never
  • marginal
  • fully
  • ultimate

Với Git 2.26 (Q1 2020) , " git show" và những người khác đã đặt tên đối tượng ở định dạng thô trong đầu ra lỗi của nó, tên này đã được sửa lại để đặt nó ở dạng hex.

show_one_mergetag: in không phải cha ở dạng hex.

Khi một thẻ thương mại đặt tên cho một thẻ không phải là cha mẹ, có thể xảy ra sau một lần sao chép nông, mã băm của nó trước đó đã được in dưới dạng dữ liệu thô.
Thay vào đó hãy in nó ở dạng hex.

Đã kiểm tra git -C shallow log --graph --show-signature -n1 plain-shallowsau mộtgit clone --depth 1 --no-local . shallow


Với Git 2.27 (Quý 2 năm 2020), mã giao diện với GnuPG đã được cấu trúc lại.

Xem cam kết 6794898 , cam kết f1e3df3 (04 tháng 3 năm 2020) bởi Hans Jerry Illikainen ( illikainen) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- in commit fa82be9 , 27/03/2020)

gpg-interface: thích check_signature()xác minh GPG

Ký tên: Hans Jerry Illikainen

Cam kết này tái cấu trúc việc sử dụng verify_signed_buffer()bên ngoài gpg-interface.cđể sử dụng check_signature()thay thế.

Nó cũng biến verify_signed_buffer()thành một hàm tệp cục bộ vì bây giờ nó chỉ được gọi nội bộ bởi check_signature().

Trước đây có hai chức năng phạm vi toàn cầu được sử dụng trong các phần khác nhau của Git để thực hiện xác minh chữ ký GPG: verify_signed_buffer()check_signature().

Bây giờ chỉ check_signature()được sử dụng.

Các verify_signed_buffer()chức năng không bảo vệ chống lại chữ ký trùng lặp như mô tả của Michał Gorny .

Thay vào đó, nó chỉ đảm bảo mã thoát không bị lỗi từ GPG và sự hiện diện của ít nhất một GOODSIGtrường trạng thái.

Điều này trái ngược với check_signature()nó trả về lỗi nếu gặp nhiều hơn một chữ ký.

Mức độ xác minh thấp hơn khiến việc sử dụng verify_signed_buffer()có vấn đề nếu người gọi không phân tích cú pháp và xác thực các phần khác nhau của thông báo trạng thái GPG.

Và việc xử lý các thông báo này có vẻ như là một nhiệm vụ nên được dành riêng cho gpg-interface.chàm check_signature().

Hơn nữa, việc sử dụng verify_signed_buffer()làm cho việc giới thiệu chức năng mới dựa trên nội dung của các dòng trạng thái GPG trở nên khó khăn.

Giờ đây, tất cả các hoạt động xác minh chữ ký đều chia sẻ một điểm vào duy nhất gpg-interface.c.

Điều này giúp dễ dàng phổ biến chức năng đã thay đổi hoặc bổ sung trong xác minh chữ ký GPG tới tất cả các phần của Git, mà không có các trường hợp cạnh kỳ lạ không thực hiện cùng một mức độ xác minh .


4

Việc kiểm tra sơ qua mã cho thấy rằng không có phương pháp trực tiếp nào như vậy.

Tất cả các bài kiểm tra trong nguồn git đều dựa vào grepping đầu ra của git show(xem t / t7510-signed-commit.sh để biết các bài kiểm tra).

Bạn có thể tùy chỉnh đầu ra bằng cách sử dụng một cái gì đó như --pretty "%H %G?%"để phân tích cú pháp dễ dàng.

Có vẻ như bạn có thể yêu cầu git mergexác minh chữ ký nhưng một lần nữa, các bài kiểm tra của nó lại dựa vào grep(xem t / t7612-merge-verify-signatures.sh ). Có vẻ như một chữ ký không hợp lệ sẽ dẫn git mergeđến việc thoát ra với một chữ ký xấu, vì vậy ngày nay bạn có thể có khả năng tấn công điều này bằng cách thực hiện hợp nhất thử nghiệm ở đâu đó và loại bỏ hợp nhất đó nhưng điều đó có vẻ tồi tệ hơn là chỉ gọi grep.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.