Skip to content

Commit bca7ba6

Browse files
authored
Export function to verify individual signature (#1334)
Calling the existing VerifyImageSignatures function multiple times for the same image with different verifiers will download the OCI manifest multiple times. This is inefficient and slow. Exporting a function that verifies a single signature allows the decoupling of the OCI manifest fetch and verification stages. Signed-off-by: Rob Best <[email protected]>
1 parent b0e81eb commit bca7ba6

File tree

1 file changed

+52
-47
lines changed

1 file changed

+52
-47
lines changed

pkg/cosign/verify.go

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -321,53 +321,9 @@ func verifySignatures(ctx context.Context, sigs oci.Signatures, h v1.Hash, co *C
321321
validationErrs := []string{}
322322

323323
for _, sig := range sl {
324-
if err := func(sig oci.Signature) error {
325-
verifier := co.SigVerifier
326-
if verifier == nil {
327-
// If we don't have a public key to check against, we can try a root cert.
328-
cert, err := sig.Cert()
329-
if err != nil {
330-
return err
331-
}
332-
if cert == nil {
333-
return errors.New("no certificate found on signature")
334-
}
335-
verifier, err = ValidateAndUnpackCert(cert, co)
336-
if err != nil {
337-
return err
338-
}
339-
}
340-
341-
if err := verifyOCISignature(ctx, verifier, sig); err != nil {
342-
return err
343-
}
344-
345-
// We can't check annotations without claims, both require unmarshalling the payload.
346-
if co.ClaimVerifier != nil {
347-
if err := co.ClaimVerifier(sig, h, co.Annotations); err != nil {
348-
return err
349-
}
350-
}
351-
352-
verified, err := VerifyBundle(ctx, sig)
353-
if err != nil && co.RekorClient == nil {
354-
return errors.Wrap(err, "unable to verify bundle")
355-
}
356-
bundleVerified = bundleVerified || verified
357-
358-
if !verified && co.RekorClient != nil {
359-
if co.SigVerifier != nil {
360-
pub, err := co.SigVerifier.PublicKey(co.PKOpts...)
361-
if err != nil {
362-
return err
363-
}
364-
return tlogValidatePublicKey(ctx, co.RekorClient, pub, sig)
365-
}
366-
367-
return tlogValidateCertificate(ctx, co.RekorClient, sig)
368-
}
369-
return nil
370-
}(sig); err != nil {
324+
verified, err := VerifyImageSignature(ctx, sig, h, co)
325+
bundleVerified = bundleVerified || verified
326+
if err != nil {
371327
validationErrs = append(validationErrs, err.Error())
372328
continue
373329
}
@@ -381,6 +337,55 @@ func verifySignatures(ctx context.Context, sigs oci.Signatures, h v1.Hash, co *C
381337
return checkedSignatures, bundleVerified, nil
382338
}
383339

340+
// VerifyImageSignature verifies a signature
341+
func VerifyImageSignature(ctx context.Context, sig oci.Signature, h v1.Hash, co *CheckOpts) (bundleVerified bool, err error) {
342+
verifier := co.SigVerifier
343+
if verifier == nil {
344+
// If we don't have a public key to check against, we can try a root cert.
345+
cert, err := sig.Cert()
346+
if err != nil {
347+
return bundleVerified, err
348+
}
349+
if cert == nil {
350+
return bundleVerified, errors.New("no certificate found on signature")
351+
}
352+
verifier, err = ValidateAndUnpackCert(cert, co)
353+
if err != nil {
354+
return bundleVerified, err
355+
}
356+
}
357+
358+
if err := verifyOCISignature(ctx, verifier, sig); err != nil {
359+
return bundleVerified, err
360+
}
361+
362+
// We can't check annotations without claims, both require unmarshalling the payload.
363+
if co.ClaimVerifier != nil {
364+
if err := co.ClaimVerifier(sig, h, co.Annotations); err != nil {
365+
return bundleVerified, err
366+
}
367+
}
368+
369+
bundleVerified, err = VerifyBundle(ctx, sig)
370+
if err != nil && co.RekorClient == nil {
371+
return false, errors.Wrap(err, "unable to verify bundle")
372+
}
373+
374+
if !bundleVerified && co.RekorClient != nil {
375+
if co.SigVerifier != nil {
376+
pub, err := co.SigVerifier.PublicKey(co.PKOpts...)
377+
if err != nil {
378+
return bundleVerified, err
379+
}
380+
return bundleVerified, tlogValidatePublicKey(ctx, co.RekorClient, pub, sig)
381+
}
382+
383+
return bundleVerified, tlogValidateCertificate(ctx, co.RekorClient, sig)
384+
}
385+
386+
return bundleVerified, nil
387+
}
388+
384389
func loadSignatureFromFile(sigRef string, signedImgRef name.Reference, co *CheckOpts) (oci.Signatures, error) {
385390
var b64sig string
386391
targetSig, err := blob.LoadFileOrURL(sigRef)

0 commit comments

Comments
 (0)