@@ -49,7 +49,7 @@ import (
49
49
// Verifier represents a mechanism to get and verify Rekor entries for the given Git data.
50
50
type Verifier interface {
51
51
Verify (ctx context.Context , commitSHA string , cert * x509.Certificate ) (* models.LogEntryAnon , error )
52
- VerifyOffline (ctx context.Context , sig []byte ) (* models.LogEntryAnon , error )
52
+ VerifyInclusion (ctx context.Context , sig []byte , cert * x509. Certificate ) (* models.LogEntryAnon , error )
53
53
}
54
54
55
55
// Writer represents a mechanism to write content to Rekor.
@@ -179,7 +179,7 @@ func rekorPubsFromClient(rekorClient *client.Rekor) (*cosign.TrustedTransparency
179
179
// 1. Searching Rekor for an entry matching the commit SHA + cert.
180
180
// 2. Use the same cert to verify the commit content.
181
181
//
182
- // Note: While not truly deprecated, Client.VerifyOffline is generally preferred.
182
+ // Note: While not truly deprecated, using offline verification is generally preferred.
183
183
// This function relies on non-GA behavior of Rekor, and remains for backwards
184
184
// compatibility with older signatures.
185
185
func (c * Client ) Verify (ctx context.Context , commitSHA string , cert * x509.Certificate ) (* models.LogEntryAnon , error ) {
@@ -245,9 +245,10 @@ func (c *Client) PublicKeys() *cosign.TrustedTransparencyLogPubKeys {
245
245
return c .publicKeys
246
246
}
247
247
248
- // VerifyOffline verifies a signature using offline verification.
249
- // Unlike Client.Verify, only the commit content is considered during verification.
250
- func (c * Client ) VerifyOffline (ctx context.Context , sig []byte ) (* models.LogEntryAnon , error ) {
248
+ // VerifyInclusion verifies a signature's inclusion in Rekor using offline verification.
249
+ // NOTE: This does **not** verify the correctness of the signature against the content.
250
+ // Prefer using [git.Verify] instead for complete verification.
251
+ func (c * Client ) VerifyInclusion (ctx context.Context , sig []byte , cert * x509.Certificate ) (* models.LogEntryAnon , error ) {
251
252
// Try decoding as PEM
252
253
var der []byte
253
254
if blk , _ := pem .Decode (sig ); blk != nil {
@@ -261,27 +262,30 @@ func (c *Client) VerifyOffline(ctx context.Context, sig []byte) (*models.LogEntr
261
262
return nil , fmt .Errorf ("failed to parse signature: %w" , err )
262
263
}
263
264
264
- // Generate verification options.
265
- certs , err := sd .GetCertificates ()
266
- if err != nil {
267
- return nil , fmt .Errorf ("error getting signature certs: %w" , err )
268
- }
269
- if len (certs ) == 0 {
270
- return nil , fmt .Errorf ("no certificates found in signature" )
271
- }
272
- cert := certs [0 ]
273
-
274
- // Recompute HashedRekord body by rehashing the authenticated attributes.
265
+ // Extract signer from signature. The spec allows for multiple signers, but in
266
+ // practice for Git commits there's typically only ever 1 signer (the committer).
275
267
r := sd .Raw ()
276
268
if len (r .SignerInfos ) == 0 {
277
269
return nil , fmt .Errorf ("no signers found in signature" )
278
270
}
279
271
si := r .SignerInfos [0 ]
280
- message , err := si .SignedAttrs .MarshaledForVerification ()
272
+
273
+ // Double check cert matches the signer. This technically isn't needed
274
+ // since if this didn't match then the verify below should also fail,
275
+ // but this helps us distinguish the error in the unlikely event this does happen.
276
+ if _ , err := si .FindCertificate ([]* x509.Certificate {cert }); err != nil {
277
+ return nil , fmt .Errorf ("signer certificate mismatch: %w" , err )
278
+ }
279
+
280
+ // Get HashedRekord body from the signature.
281
+ // We are assuming here that the signature has already been authenticated against the
282
+ // cert, so it is okay to rely the precomputed checksum in the SignerInfo.
283
+ message , err := si .GetMessageDigestAttribute ()
281
284
if err != nil {
282
285
return nil , err
283
286
}
284
287
288
+ // Reassemble the tlog entry from the signature pieces.
285
289
tlog , err := rekoroid .ToLogEntry (ctx , message , si .Signature , cert , si .UnsignedAttrs )
286
290
if err != nil {
287
291
return nil , err
0 commit comments