plumbing: object, add scheme-agnostic object verification API#2235
plumbing: object, add scheme-agnostic object verification API#2235pjbgf wants to merge 1 commit into
Conversation
Introduce a plugin-based, scheme-agnostic API for verifying Git object signatures, replacing the OpenPGP-only Commit.Verify/Tag.Verify. - Add plugin.Verifier, plugin.Verification and the plugin.ObjectVerifier() key (x/plugin), mirroring the existing Signer plugin. - Commit.Verify / Tag.Verify now take a context and VerifyOption(s), using the verifier from WithVerifier or, by default, the registered ObjectVerifier. Core ships only the contract; concrete verifiers live off-tree in go-git/x. - EncodeWithoutSignature returns a streaming io.Reader whose WriteTo feeds the verifier's hash directly, avoiding a full-payload buffer. - Signature and SignatureSHA256 are now []byte, removing string<->[]byte conversions in the sign/verify paths. - Multi-signature rejection moves to the OpenPGP verifier; core stays scheme-agnostic and no longer depends on ProtonMail/go-crypto. - Move the gpg/git conformance suite to go-git/x. Assisted-by: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: Paulo Gomes <paulo@entire.io>
There was a problem hiding this comment.
Pull request overview
This PR introduces a scheme-agnostic, plugin-based Git object signature verification API (paralleling the existing signing plugin approach), while also refactoring commit/tag signature handling to use []byte and enabling streaming “encode-without-signature” payload generation for signing/verifying.
Changes:
- Added
plugin.Verifier/plugin.Verificationand theplugin.ObjectVerifier()registry key to support out-of-tree verification implementations. - Updated
Commit.Verify/Tag.Verifyto takecontext.Context+VerifyOptions and delegate to a configured (or registered)Verifier. - Refactored signature storage to
[]byteand changedEncodeWithoutSignatureto return a streamingio.Reader(viaio.WriterTo) to avoid full-payload buffering.
Reviewed changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| x/plugin/plugin_verifier.go | Adds the verifier plugin contract and the ObjectVerifier plugin key. |
| worktree_commit.go | Stores generated commit signatures as []byte. |
| worktree_commit_test.go | Adjusts signature assertions for []byte commit signatures. |
| tests/objectverify/tag_test.go | Removes in-tree tag verification conformance tests (moved off-tree). |
| tests/objectverify/main_test.go | Removes in-tree object verification harness (moved off-tree). |
| tests/objectverify/commit_test.go | Removes in-tree commit verification conformance tests (moved off-tree). |
| signer.go | Switches signing to consume a streaming EncodeWithoutSignature() reader. |
| signer_test.go | Updates example output for []byte signatures. |
| repository.go | Updates tag signing path to return/store []byte signatures. |
| plumbing/object/verify.go | Introduces core scheme-agnostic verify helper + options. |
| plumbing/object/verify_test.go | Adds tests for verifier selection and registered default verifier behavior. |
| plumbing/object/verify_bench_test.go | Adds benchmarks focusing on streaming verification behavior. |
| plumbing/object/tag.go | Converts tag signatures to []byte, adds streaming EncodeWithoutSignature, and switches Verify to plugin-based verifier. |
| plumbing/object/tag_test.go | Updates tag tests for []byte signatures and new EncodeWithoutSignature shape; removes OpenPGP Verify tests. |
| plumbing/object/tag_scanner.go | Stores tag signature header data into []byte. |
| plumbing/object/signature.go | Adds streaming signedReader, refactors signature parsing helpers, and makes signature stripping stream-oriented. |
| plumbing/object/signature_test.go | Updates tests/fuzzing for the refactored signature parsing helpers. |
| plumbing/object/commit.go | Converts commit signatures to []byte, adds streaming EncodeWithoutSignature, and switches Verify to plugin-based verifier. |
| plumbing/object/commit_test.go | Updates commit tests for []byte signatures and new EncodeWithoutSignature shape; removes OpenPGP Verify tests. |
| plumbing/object/commit_scanner.go | Stores commit signature header data into []byte. |
| go.sum | Removes ProtonMail/go-crypto and related indirect sums. |
| go.mod | Removes ProtonMail/go-crypto and related indirect dependencies. |
| EXTENDING.md | Documents the new verification plugin API and usage patterns. |
| v := cfg.verifier | ||
| if v == nil { | ||
| var err error | ||
| if v, err = plugin.Get(plugin.ObjectVerifier()); err != nil { | ||
| return nil, err | ||
| } | ||
| } |
| func (f *fakeVerifier) Verify(_ context.Context, message io.Reader, signature []byte) (*plugin.Verification, error) { | ||
| b, _ := io.ReadAll(message) | ||
| f.gotMessage = b | ||
| f.gotSignature = signature | ||
| return f.result, f.err | ||
| } |
| Method SignatureType | ||
| // Details carries scheme-specific data, for example an *openpgp.Entity | ||
| // for OpenPGP signatures. Callers type-assert on it based on Method. | ||
| Details any |
There was a problem hiding this comment.
@Bluebugs This should enable any additional scheme-specific information to be shared with users (as per separate thread).
Trust levels becomes an implementation detail of the verifier, as opposed to the API first class citizen. I haven't added them to the initial GPG implementation, but that is something we should be able to easily add as a follow-up.
There was a problem hiding this comment.
Nice. I haven't worked much on go-git lately as I don't want to overwhelm more the PR queue :-) But I might try to implement support for allowed_signers on top of your PR for go-git/x ( https://man7.org/linux/man-pages/man1/ssh-keygen.1.html#ALLOWED_SIGNERS ).
Introduce a plugin-based, scheme-agnostic API for verifying Git object signatures, replacing the OpenPGP-only
Commit.Verify/Tag.Verify.This results in:
Verifierin-tree, which aligns with the approach taken forSigner.ObjectVerifierimplementations will be placed ingo-git/xso that users of go-git that don't need the third-party dependencies won't have them in their projects.Global verifier
Explicit verifier
Proposed implementation for gpg and ssh can be seen here.
Supersedes #1883.
Relates to #1869.