Memverifikasi git commit yang ditandatangani?

96

Dengan versi yang lebih baru git, dimungkinkan untuk menandatangani komit individu (selain tag) dengan kunci PGP:

git commit -m "some message" -S

Dan Anda dapat menunjukkan tanda tangan ini di output git logdengan --show-signatureopsi:

$ 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 <[email protected]>"
Author: Lars Kellogg-Stedman <[email protected]>
Date:   Fri Jun 28 14:28:41 2013 -0400

    this is a test

Tetapi apakah ada cara untuk memverifikasi tanda tangan secara terprogram pada komit yang diberikan selain dengan meng-grep output dari git log? Saya mencari padanan komit dari git tag -v- sesuatu yang akan memberikan kode keluar yang menunjukkan apakah ada tanda tangan yang valid pada komit yang diberikan.

larsks
sumber
1
Saya pikir itu harus git commit ...dan git log .... Sejauh yang saya tahu, gpgbelum menambahkan sub-perintah yang diteruskan ke secara gittransparan ... Saya tidak memiliki repo untuk diuji, tetapi apakah git show --show-signature <commitish>berfungsi?
twalberg
show_signaturehanya menambahkan sesuatu ke keluaran (lihat github.com/git/git/blob/master/log-tree.c#L370 ).
Emil Sit
Catatan: Anda akan segera memiliki --rawuntuk git verify-tag/ git verify-commit. Lihat jawaban saya di bawah ini
VonC
1
Catatan: dengan git 2.11 (Q4 2016), git logkode status memperkenalkan tambahan E, X, Y, Runtuk ERRSIG, EXPSIG, EXPKEYSIG, dan REVKEYSIG, sehingga pengguna dari %G?mendapatkan informasi lebih lanjut. Lihat jawaban saya yang telah diedit di bawah
VonC
1
Dengan Git 2.26 (Q1 2020), konfigurasi baru gpg.minTrustLeveldapat membantu saat menggunakan git verify-tag/ verify -commit. Lihat jawaban saya yang sudah diedit di bawah .
VonC

Jawaban:

115

Seandainya seseorang datang ke halaman ini melalui mesin pencari, seperti yang saya lakukan: Alat baru telah tersedia dalam dua tahun sejak pertanyaan diposting: Sekarang ada perintah git untuk tugas ini: git verify-commitdan git verify-tagdapat digunakan untuk memverifikasi komit dan tag, masing-masing.

tarleb
sumber
34

Catatan: hingga git 2.5, git verify-commitdan git verify-taghanya menampilkan pesan yang dapat dibaca manusia.
Jika Anda ingin mengotomatiskan pemeriksaan, git 2.6+ (Q3 2015) menambahkan keluaran lain.

Lihat commit e18443e , commit aeff29d , commit ca194d5 , commit 434060e , commit 8e98e5f , commit a4cc18f , commit d66aeff (21 Jun 2015) oleh brian m. carlson ( bk2204) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit ba12cb2 , 03 Agustus 2015)

verify-tag/ verify-commit: tambahkan opsi untuk mencetak informasi status gpg mentah

verify-tag/ verify-commitsecara default menampilkan keluaran yang dapat dibaca manusia pada kesalahan standar.
Namun, dapat juga berguna untuk mendapatkan akses ke informasi status gpg mentah, yang dapat dibaca mesin, memungkinkan penerapan otomatis kebijakan penandatanganan .

Tambahkan --rawopsi agar verify-tagmenghasilkan informasi status gpg pada kesalahan standar alih-alih format yang dapat dibaca manusia.

Plus:

verify-tagberhasil keluar jika tanda tangannya bagus tetapi kuncinya tidak tepercaya. verify-commitkeluar tidak berhasil.
Perbedaan perilaku ini tidak terduga dan tidak diinginkan.
Sejak verify-tagada sebelumnya, tambahkan pengujian yang gagal untuk memiliki perilaku verify-commitberbagi verify-tag.


git 2.9 (Juni 2016) perbarui dokumen git merge :

Lihat commit 05a5869 (13 Mei 2016) oleh Keller Fuchs (``) .
Dibantu oleh: Junio ​​C Hamano ( gitster) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit be6ec17 , 17 Mei 2016)

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

Verifikasi bahwa komit tip dari cabang samping yang digabungkan ditandatangani dengan kunci yang valid, yaitu kunci yang memiliki uid yang valid: dalam model kepercayaan default, ini berarti kunci penandatanganan telah ditandatangani oleh kunci tepercaya.
Jika komit tip dari cabang samping tidak ditandatangani dengan kunci yang valid, penggabungan dibatalkan
.


Perbarui Git 2.10 (Q3 2016)

Lihat commit b624a3e (16 Agustus 2016) oleh Linus Torvalds ( torvalds) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 83d9eb0 , 19 Agustus 2016)

gpg-interface: lebih memilih keluaran format kunci "panjang" saat memverifikasi tanda tangan pgp

" git log --show-signature" dan perintah lain yang menampilkan status verifikasi tanda tangan PGP sekarang menampilkan key-id yang lebih panjang, karena 32-bit key-id adalah abad terakhir.

Versi asli Linus dibuat ulang untuk diterapkan ke jalur pemeliharaan jika distributor biner yang terjebak di masa lalu ingin membawanya ke basis kode lama mereka.


Git 2.11+ (Q4 2016) bahkan akan lebih presisi.

Lihat commit 661a180 (12 Okt 2016) oleh Michael J Gruber ( mjg) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 56d268b , 26 Okt 2016)

Status verifikasi GPG yang ditampilkan dalam %G?penentu format cantik " " tidak cukup kaya untuk membedakan tanda tangan yang dibuat oleh kunci yang kedaluwarsa, tanda tangan yang dibuat oleh kunci yang dicabut, dll.
Huruf keluaran baru telah ditetapkan untuk mengekspresikannya .

Menurut gpg2doc/DETAILS :

Untuk setiap tanda tangan hanya salah satu kode GOODSIG, BADSIG, EXPSIG, EXPKEYSIG, REVKEYSIGatau ERRSIGakan dipancarkan.

The git pretty-formatDokumentasi sekarang termasuk:

  • ' %G?': tunjukkan
    • " G" untuk tanda tangan yang baik (valid),
    • " B" untuk tanda tangan yang buruk,
    • " U" untuk tanda tangan yang baik dengan validitas yang tidak diketahui,
    • " X" untuk tanda tangan baik yang telah kedaluwarsa,
    • " Y" untuk tanda tangan bagus yang dibuat dengan kunci yang kedaluwarsa,
    • " R" untuk tanda tangan bagus yang dibuat dengan kunci yang dicabut,
    • " E" jika tanda tangan tidak dapat diperiksa (mis. kunci hilang) dan "N" jika tidak ada tanda tangan

Git 2.12 (K1 2017) " git tag" dan " git verify-tag" belajar menempatkan status verifikasi GPG dalam --format=<placeholders>format keluaran " " .

Lihat commit 4fea72f , commit 02c5433 , commit ff3c8c8 (17 Jan 2017) oleh Santiago Torres ( SantiagoTorres) .
Lihat commit 07d347c , commit 2111aa7 , commit 94240b9 (17 Jan 2017) oleh Lukas Puehringer (``) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 237bdd9 , 31 Jan 2017)

Menambahkan --formatuntuk git tag -vmembungkam keluaran default dari verifikasi GPG dan sebagai gantinya mencetak objek tag yang diformat.
Hal ini memungkinkan pemanggil untuk memeriksa ulang tagname dari refs / tag dengan tagname dari header objek tag pada verifikasi GPG.


Git 2.16 (Q1 2018) akan memungkinkan verifikasi tanda tangan komit menjadi lebih otomatis, dengan merge.verifySignaturesvariabel konfigurasi.

Lihat commit 7f8ca20 , commit ca779e8 (10 Des 2017) oleh Hans Jerry Illikainen (``) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 0433d53 , 28 Des 2017)

merge: tambahkan opsi konfigurasi untuk verifySignatures

git merge --verify-signatures dapat digunakan untuk memverifikasi bahwa komit tip dari cabang yang digabungkan ditandatangani dengan benar, tetapi rumit untuk harus menentukannya setiap saat.

Tambahkan opsi konfigurasi yang memungkinkan perilaku ini secara default, yang dapat diganti oleh --no-verify-signatures.

The git mergehalaman manual config sekarang berbunyi:

merge.verifySignatures:

Jika benar, ini setara dengan --verify-signaturesopsi baris perintah.


Git 2.19 (K3 2018) bahkan lebih berguna, karena " git verify-tag" dan " git verify-commit" telah diajarkan untuk menggunakan status keluar dari " gpg --verify" yang mendasari untuk menandakan tanda tangan yang buruk atau tidak tepercaya yang mereka temukan.

Catatan: dengan Git 2.19, gpg.formatitu dapat disetel ke " openpgp" atau " x509", dan gpg.<format>.programitu digunakan untuk menentukan program apa yang akan digunakan untuk menangani format) untuk mengizinkan x.509 sertifikat dengan CMS melalui " gpgsm" untuk digunakan alih-alih openpgpmelalui " gnupg".

Lihat commit 4e5dc9c (09 Agustus 2018) oleh Junio ​​C Hamano ( gitster) .
Dibantu oleh: Vojtech Myslivec ( VojtechMyslivec) , brian m. carlson ( bk2204) , dan Jeff King ( peff) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 4d34122 , 20 Agustus 2018)

gpg-interface: menyebarkan status keluar dari gpgbelakang ke penelepon

Saat gpg-interface API menyatukan dukungan untuk jalur kode verifikasi tanda tangan untuk tag yang ditandatangani dan komitmen yang ditandatangani pada pertengahan 2015 di sekitar v2.6.0-rc0 ~ 114, kami secara tidak sengaja melonggarkan verifikasi tanda tangan GPG.

Sebelum perubahan itu, komit yang ditandatangani diverifikasi dengan mencari " G" tanda tangan ood dari GPG, sementara mengabaikan status keluar dari gpg --verifyproses " ", sementara tag yang ditandatangani diverifikasi hanya dengan meneruskan status keluar dari "gpg --verify"melalui.

Kode terpadu yang saat ini kami abaikan status keluarnya dari " gpg --verify" dan mengembalikan verifikasi yang berhasil ketika tanda tangan cocok dengan kunci yang belum kedaluwarsa terlepas dari kepercayaan yang ditempatkan pada kunci (yaitu sebagai tambahan untuk " G" yang baik, kami menerima " U" yang tidak dipercaya).

Buat perintah ini menandakan kegagalan dengan status keluarnya saat " gpg --verify" mendasari (atau perintah khusus yang ditentukan oleh gpg.programvariabel konfigurasi " ") melakukannya.
Ini pada dasarnya mengubah perilaku mereka dengan cara yang tidak kompatibel dengan versi sebelumnya untuk menolak tanda tangan yang telah dibuat dengan kunci yang tidak tepercaya meskipun mereka memverifikasi dengan benar, karena begitulah perilaku " gpg --verify".

Perhatikan bahwa kode tersebut masih menimpa status keluar nol yang diperoleh dari " gpg" (atau gpg.program) jika keluaran tidak menyatakan bahwa tanda tangannya baik atau dihitung dengan benar tetapi dibuat dengan kunci tidak tepercaya, untuk menangkap pembungkus yang ditulis dengan buruk di sekitar " gpg" yang mungkin diberikan pengguna kepada kita .

Kita bisa mengecualikan Udukungan yang " " tidak tepercaya dari kode fallback ini, tapi itu akan membuat dua perubahan yang tidak kompatibel ke belakang dalam satu komit, jadi mari kita hindari itu untuk saat ini.
Perubahan tindak lanjut dapat dilakukan jika diinginkan.


kunci harus dipercaya / ditandatangani sebelum melakukan enkripsi apa pun

Di sisi kepercayaan, ada kemajuan:
Dengan Git 2.26 (Q1 2020), gpg.minTrustLevelvariabel konfigurasi telah diperkenalkan untuk memberi tahu berbagai jalur kode verifikasi tanda tangan tingkat kepercayaan minimum yang diperlukan.

Lihat commit 54887b4 (27 Des 2019) oleh Hans Jerry Illikainen ( illikainen) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 11ad30b , 30 Jan 2020)

gpg-interface: tambahkan minTrustLevel sebagai opsi konfigurasi

Ditandatangani oleh: Hans Jerry Illikainen

Sebelumnya, verifikasi tanda tangan untuk operasi penggabungan dan penarikan diperiksa apakah kunci tersebut memiliki tingkat kepercayaan salah satu TRUST_NEVERatau TRUST_UNDEFINEDdalam verify_merge_signature().

Jika itu masalahnya, prosesnya die()d.

Jalur kode lain yang melakukan verifikasi tanda tangan bergantung sepenuhnya pada kode pengembalian dari check_commit_signature().

Dan tanda tangan yang dibuat dengan kunci yang baik, terlepas dari tingkat kepercayaannya, dianggap sah oleh check_commit_signature().

Perbedaan perilaku ini dapat menyebabkan pengguna salah berasumsi bahwa tingkat kepercayaan dari sebuah kunci dalam keyring mereka selalu dipertimbangkan oleh Git, bahkan untuk operasi yang tidak (misalnya selama a verify-commitatau verify-tag) .

Cara kerjanya adalah dengan gpg-interface.cmenyimpan hasil dari status kunci / tanda tangan dan dua tingkat kepercayaan terendah di resultanggota signature_checkstruktur (baris status terakhir yang ditemukan ditulis ke result).

Ini didokumentasikan dalam GPG di bawah sub-bagian General status codesdan Key related, masing-masing.

Dokumentasi GPG mengatakan berikut ini pada TRUST_ statuskode :


Ini adalah beberapa kode status yang serupa:

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

Untuk tanda tangan yang baik, salah satu baris status ini dikeluarkan untuk menunjukkan validitas kunci yang digunakan untuk membuat tanda tangan.
Nilai token kesalahan saat ini hanya dikeluarkan oleh gpgsm.


Interpretasi saya adalah bahwa tingkat kepercayaan secara konseptual berbeda dari validitas kunci dan / atau tanda tangan.

Itu tampaknya juga merupakan asumsi kode lama di check_signature()mana hasil dari ' G' (seperti dalam GOODSIG) dan ' U' (seperti dalam TRUST_NEVERatau TRUST_UNDEFINED)keduanya dianggap sukses.

Dua kasus di mana hasil dari ' U' memiliki arti khusus berada di verify_merge_signature()(di mana ini disebabkan gituntuk die()) dan format_commit_one()(di mana itu mempengaruhi output dari %G?format specifier).

Menurut saya masuk akal untuk melakukan refaktorisasi pemrosesan TRUST_ statusgaris sehingga pengguna dapat mengonfigurasi tingkat kepercayaan minimum yang diberlakukan secara global, daripada meminta bagian individu git(misalnya menggabungkan) melakukannya sendiri (kecuali untuk masa tenggang dengan kompatibilitas ke belakang).

Saya juga berpikir masuk akal untuk tidak menyimpan tingkat kepercayaan di anggota struct yang sama dengan status kunci / tanda tangan.

Meskipun keberadaan TRUST_ statuskode menyiratkan bahwa tanda tangannya baik (lihat paragraf pertama dalam cuplikan yang disertakan di atas), sejauh yang saya tahu, urutan baris status dari GPG tidak terdefinisi dengan baik; dengan demikian tampaknya masuk akal bahwa tingkat kepercayaan dapat ditimpa dengan status kunci / tanda tangan jika disimpan dalam anggota signature_checkstruktur yang sama.

Patch ini memperkenalkan pilihan konfigurasi baru: gpg.minTrustLevel.

Ini menggabungkan verifikasi tingkat kepercayaan gpg-interface.cdan menambahkan anggota baru trust_levelke signature_checkstruktur.

Kompatibilitas mundur dipertahankan dengan memasukkan kasus khusus verify_merge_signature()sedemikian rupa sehingga jika tidak ada konfigurasi pengguna gpg.minTrustLevelyang disetel, maka perilaku lama menolak TRUST_UNDEFINEDdan TRUST_NEVERditerapkan.

Sebaliknya, jika gpg.minTrustLeveldisetel, nilai itu menggantikan perilaku lama.

Demikian pula, penentu %G?format akan terus menampilkan ' U' untuk tanda tangan yang dibuat dengan kunci yang memiliki tingkat kepercayaan TRUST_UNDEFINEDatau TRUST_NEVER,meskipun karakter ' U' tidak lagi ada dalam resultanggota signature_checkstruktur.

Penentu format baru %GT,, juga diperkenalkan untuk pengguna yang ingin menampilkan semua kemungkinan tingkat kepercayaan untuk tanda tangan.

Pendekatan lain adalah dengan hanya menjatuhkan persyaratan tingkat kepercayaan verify_merge_signature().

Ini juga akan membuat perilaku konsisten dengan bagian lain dari git yang melakukan verifikasi tanda tangan.

Namun, membutuhkan tingkat kepercayaan minimum untuk menandatangani kunci tampaknya memiliki kasus penggunaan di dunia nyata.

Misalnya, sistem build yang digunakan oleh proyek Qubes OS saat ini mengurai keluaran mentah dari verifikasi-tag untuk menegaskan tingkat kepercayaan minimum untuk kunci yang digunakan untuk menandatangani tag git .

The git config gpghalaman manual sekarang termasuk:

gpg.minTrustLevel:

Menentukan tingkat kepercayaan minimum untuk verifikasi tanda tangan.
Jika opsi ini tidak disetel, verifikasi tanda tangan untuk operasi penggabungan memerlukan kunci dengan setidaknya marginalkepercayaan.
Operasi lain yang melakukan verifikasi tanda tangan memerlukan kunci dengan setidaknya undefinedkepercayaan.
Menyetel opsi ini menimpa tingkat kepercayaan yang diperlukan untuk semua operasi. Nilai yang didukung, dalam urutan signifikansinya:

  • undefined
  • never
  • marginal
  • fully
  • ultimate

Dengan Git 2.26 (K1 2020) , " git show" dan lainnya memberikan nama objek dalam format mentah dalam keluaran kesalahannya, yang telah dikoreksi menjadi hex.

show_one_mergetag: mencetak non-induk dalam bentuk hex.

Saat mergetag menamai non-induk, yang dapat terjadi setelah klon dangkal, hashnya sebelumnya dicetak sebagai data mentah.
Cetaklah dalam bentuk hex sebagai gantinya.

Diuji dengan git -C shallow log --graph --show-signature -n1 plain-shallowsetelah agit clone --depth 1 --no-local . shallow


Dengan Git 2.27 (Q2 2020), kode untuk berinteraksi dengan GnuPG telah difaktor ulang.

Lihat commit 6794898 , commit f1e3df3 (04 Mar 2020) oleh Hans Jerry Illikainen ( illikainen) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit fa82be9 , 27 Mar 2020)

gpg-interface: lebih memilih check_signature()untuk verifikasi GPG

Ditandatangani oleh: Hans Jerry Illikainen

Komit ini merefaktor penggunaan dari verify_signed_buffer()luar gpg-interface.cuntuk digunakan check_signature()sebagai gantinya.

Ini juga berubah verify_signed_buffer()menjadi fungsi file-local karena sekarang hanya dipanggil secara internal oleh check_signature().

Sebelumnya ada dua fungsi dengan cakupan global yang digunakan di berbagai bagian Git untuk melakukan verifikasi tanda tangan GPG: verify_signed_buffer()dan check_signature().

Sekarang hanya check_signature()digunakan.

The verify_signed_buffer()Fungsi tidak menjaga terhadap duplikat tanda tangan seperti yang dijelaskan oleh Michał Gorny .

Sebaliknya, ini hanya memastikan kode keluar yang tidak salah dari GPG dan keberadaan setidaknya satu GOODSIGbidang status.

Ini berbeda dengan check_signature()yang mengembalikan kesalahan jika lebih dari satu tanda tangan ditemukan.

Tingkat verifikasi yang lebih rendah membuat penggunaan verify_signed_buffer()bermasalah jika penelepon tidak mengurai dan memvalidasi berbagai bagian pesan status GPG itu sendiri.

Dan memproses pesan-pesan ini tampak seperti tugas yang harus dilakukan gpg-interface.cdengan fungsi tersebut check_signature().

Selain itu, penggunaan verify_signed_buffer()mempersulit pengenalan fungsi baru yang bergantung pada konten baris status GPG.

Sekarang semua operasi yang melakukan verifikasi tanda tangan berbagi satu titik masuk gpg-interface.c.

Ini membuatnya lebih mudah untuk menyebarkan fungsionalitas yang diubah atau tambahan dalam verifikasi tanda tangan GPG ke semua bagian Git, tanpa kasus tepi ganjil yang tidak melakukan tingkat verifikasi yang sama .

VonC
sumber
4

Pemeriksaan sepintas terhadap kode menunjukkan bahwa tidak ada metode langsung seperti itu.

Semua pengujian di sumber git bergantung pada grepping keluaran git show(lihat t / t7510-signed-commit.sh untuk pengujian).

Anda dapat menyesuaikan keluaran menggunakan sesuatu seperti --pretty "%H %G?%"untuk membuatnya mudah untuk diurai.

Tampaknya Anda dapat meminta git mergeuntuk memverifikasi tanda tangan tetapi sekali lagi, pengujiannya bergantung pada grep(lihat t / t7612-merge-verify-signatures.sh ). Tampaknya tanda tangan yang tidak valid akan menyebabkan git mergekeluar dengan tanda tangan yang buruk, jadi Anda berpotensi hari ini meretas hal ini dengan melakukan uji coba penggabungan di suatu tempat dan membuang penggabungan itu tetapi tampaknya lebih buruk daripada hanya memanggil grep.

Emil Sit
sumber