Skip to content

Commit

Permalink
Use Hash for Signer/Verifier as an option
Browse files Browse the repository at this point in the history
  • Loading branch information
ret2libc committed Jan 22, 2024
1 parent b7c5930 commit afdad84
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 39 deletions.
13 changes: 9 additions & 4 deletions cmd/cosign/cli/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,12 @@ func SignCmd(ro *options.RootOptions, ko options.KeyOpts, signOpts options.SignO
ctx, cancel := context.WithTimeout(context.Background(), ro.Timeout)
defer cancel()

sv, err := signerFromKeyOptsWithSVOpts(ctx, "", "", ko, signature.WithED25519ph())
svOptions := []signature.SignerVerifierOption{
signature.WithHash(crypto.SHA256),
signature.WithED25519ph(),
}

sv, err := signerFromKeyOptsWithSVOpts(ctx, "", "", ko, svOptions...)
if err != nil {
return fmt.Errorf("getting signer: %w", err)
}
Expand Down Expand Up @@ -526,12 +531,12 @@ func signerFromKeyRef(ctx context.Context, certPath, certChainPath, keyRef strin
return certSigner, nil
}

func signerFromNewKey() (*SignerVerifier, error) {
func signerFromNewKey(svOpts ...signature.SignerVerifierOption) (*SignerVerifier, error) {
privKey, err := cosign.GeneratePrivateKey()
if err != nil {
return nil, fmt.Errorf("generating cert: %w", err)
}
sv, err := signature.LoadECDSASignerVerifier(privKey, crypto.SHA256)
sv, err := signature.LoadSignerVerifierWithOpts(privKey, svOpts...)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -576,7 +581,7 @@ func signerFromKeyOptsWithSVOpts(ctx context.Context, certPath string, certChain
default:
genKey = true
ui.Infof(ctx, "Generating ephemeral keys...")
sv, err = signerFromNewKey()
sv, err = signerFromNewKey(svOpts...)
}
if err != nil {
return nil, err
Expand Down
7 changes: 6 additions & 1 deletion cmd/cosign/cli/sign/sign_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ func SignBlobCmd(ro *options.RootOptions, ko options.KeyOpts, payloadPath string
ctx, cancel := context.WithTimeout(context.Background(), ro.Timeout)
defer cancel()

sv, err := signerFromKeyOptsWithSVOpts(ctx, "", "", ko, signature.WithED25519ph())
svOptions := []signature.SignerVerifierOption{
signature.WithHash(crypto.SHA256),
signature.WithED25519ph(),
}

sv, err := signerFromKeyOptsWithSVOpts(ctx, "", "", ko, svOptions...)
if err != nil {
return nil, err
}
Expand Down
13 changes: 9 additions & 4 deletions cmd/cosign/cli/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,16 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
}
}

svOpts := []signature.SignerVerifierOption{
signature.WithHash(crypto.SHA256),
signature.WithED25519ph(),
}

// Keys are optional!
var pubKey signature.Verifier
switch {
case keyRef != "":
pubKey, err = sigs.PublicKeyFromKeyRefWithOpts(ctx, keyRef, c.HashAlgorithm, signature.WithED25519ph())
pubKey, err = sigs.PublicKeyFromKeyRefWithOpts(ctx, keyRef, svOpts...)
if err != nil {
return fmt.Errorf("loading public key: %w", err)
}
Expand Down Expand Up @@ -251,7 +256,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
if err != nil {
return fmt.Errorf("getting Fulcio intermediates: %w", err)
}
pubKey, err = cosign.ValidateAndUnpackCertWithOpts(cert, co, cosign.WithSignerVerifierOptions(signature.WithED25519ph()))
pubKey, err = cosign.ValidateAndUnpackCertWithOpts(cert, co, cosign.WithSignerVerifierOptions(svOpts...))
if err != nil {
return err
}
Expand All @@ -261,7 +266,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
if err != nil {
return err
}
pubKey, err = cosign.ValidateAndUnpackCertWithOpts(cert, co, cosign.WithChain(chain), cosign.WithSignerVerifierOptions(signature.WithED25519ph()))
pubKey, err = cosign.ValidateAndUnpackCertWithOpts(cert, co, cosign.WithChain(chain), cosign.WithSignerVerifierOptions(svOpts...))
if err != nil {
return err
}
Expand Down Expand Up @@ -302,7 +307,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
return fmt.Errorf("resolving attachment type %s for image %s: %w", c.Attachment, img, err)
}

verified, bundleVerified, err := cosign.VerifyImageSignatures(ctx, ref, co)
verified, bundleVerified, err := cosign.VerifyImageSignaturesWithOpts(ctx, ref, co, svOpts...)
if err != nil {
return cosignError.WrapError(err)
}
Expand Down
11 changes: 8 additions & 3 deletions cmd/cosign/cli/verify/verify_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,15 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
}
}

svOpts := []signature.SignerVerifierOption{
signature.WithHash(crypto.SHA256),
signature.WithED25519ph(),
}

// Keys are optional!
switch {
case c.KeyRef != "":
co.SigVerifier, err = sigs.PublicKeyFromKeyRefWithOpts(ctx, c.KeyRef, crypto.SHA256, signature.WithED25519ph())
co.SigVerifier, err = sigs.PublicKeyFromKeyRefWithOpts(ctx, c.KeyRef, svOpts...)
if err != nil {
return fmt.Errorf("loading public key: %w", err)
}
Expand Down Expand Up @@ -219,7 +224,7 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
bundleCert, err := loadCertFromPEM(certBytes)
if err != nil {
// check if cert is actually a public key
co.SigVerifier, err = sigs.LoadPublicKeyRawWithOpts(certBytes, crypto.SHA256, signature.WithED25519ph())
co.SigVerifier, err = sigs.LoadPublicKeyRawWithOpts(certBytes, svOpts...)
if err != nil {
return fmt.Errorf("loading verifier from bundle: %w", err)
}
Expand Down Expand Up @@ -298,7 +303,7 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
if err != nil {
return err
}
if _, err = cosign.VerifyBlobSignature(ctx, signature, co); err != nil {
if _, err = cosign.VerifyBlobSignatureWithOpts(ctx, signature, co, svOpts...); err != nil {
return err
}

Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/secure-systems-lab/go-securesystemslib v0.8.0
github.com/sigstore/fulcio v1.4.3
github.com/sigstore/protobuf-specs v0.2.2-0.20240118022641-cea4265fd6c5
github.com/sigstore/rekor v1.3.4
github.com/sigstore/sigstore v1.8.0
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.0
Expand Down Expand Up @@ -277,6 +278,6 @@ require (
sigs.k8s.io/yaml v1.4.0 // indirect
)

replace github.com/sigstore/sigstore => github.com/trail-of-forks/sigstore v0.0.0-20240117103256-3095d93bafe8
replace github.com/sigstore/sigstore => /Users/ret2libc/projects/sigstore/sigstore

replace github.com/sigstore/rekor => github.com/trail-of-forks/rekor v0.0.0-20240117141752-51caf324f906
replace github.com/sigstore/rekor => /Users/ret2libc/projects/sigstore/rekor
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,8 @@ github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/sigstore/fulcio v1.4.3 h1:9JcUCZjjVhRF9fmhVuz6i1RyhCc/EGCD7MOl+iqCJLQ=
github.com/sigstore/fulcio v1.4.3/go.mod h1:BQPWo7cfxmJwgaHlphUHUpFkp5+YxeJes82oo39m5og=
github.com/sigstore/protobuf-specs v0.2.2-0.20240118022641-cea4265fd6c5 h1:zd0WcTFjKmp50qey4orR4Xzmyt5lxyyPQOEeyWa24xU=
github.com/sigstore/protobuf-specs v0.2.2-0.20240118022641-cea4265fd6c5/go.mod h1:ynKzXpqr3dUj2Xk9O/5ZUhjnpi0F53DNi5AdH6pS3jc=
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.0 h1:nLaaOX85YjBKQOQHWY2UlDkbx+je8ozTEM+t1ySAb78=
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.0/go.mod h1:fLxrKqPP9lIz/B3UBD4ZK6j6984eX2czu/0zxm99fkE=
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.0 h1:Txd7Fjei2NVb/sjBNYybrl+FcZGptO6FXXH4pVNBQMs=
Expand Down Expand Up @@ -672,10 +674,6 @@ github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHT
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/trail-of-forks/rekor v0.0.0-20240117141752-51caf324f906 h1:xiHDiDcZ3yeBikoG6RZvjkDqwWQnmslPQqvZxueZV3E=
github.com/trail-of-forks/rekor v0.0.0-20240117141752-51caf324f906/go.mod h1:20v68aaBb2C/sUjSluGGhhL+eR8G9+Vd4SLX5F1u/cU=
github.com/trail-of-forks/sigstore v0.0.0-20240117103256-3095d93bafe8 h1:0tnfVIeZPhbzIOmpHJrrOKH4Fb1W1rmIAJsgkwnc2TU=
github.com/trail-of-forks/sigstore v0.0.0-20240117103256-3095d93bafe8/go.mod h1:l12B1gFlLIpBIVeqk/q1Lb+6YSOGNuN3xLExIjYH+qc=
github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4=
github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A=
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
Expand Down
2 changes: 1 addition & 1 deletion pkg/cosign/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,5 +228,5 @@ func LoadPrivateKeyWithOpts(key []byte, pass []byte, opts ...signature.SignerVer
if err != nil {
return nil, fmt.Errorf("parsing private key: %w", err)
}
return signature.LoadSignerVerifierWithOpts(pk, crypto.SHA256, opts...)
return signature.LoadSignerVerifierWithOpts(pk, opts...)
}
28 changes: 21 additions & 7 deletions pkg/cosign/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ func ValidateAndUnpackCertWithOpts(cert *x509.Certificate, co *CheckOpts, opts .
co.IntermediateCerts = subPool
}

verifier, err := signature.LoadVerifierWithOpts(cert.PublicKey, crypto.SHA256, o.svOpts...)
verifier, err := signature.LoadVerifierWithOpts(cert.PublicKey, o.svOpts...)
if err != nil {
return nil, fmt.Errorf("invalid certificate found on signature: %w", err)
}
Expand Down Expand Up @@ -543,6 +543,10 @@ func (fos *fakeOCISignatures) Get() ([]oci.Signature, error) {
// Note that if co.ExperimentlOCI11 is set, we will attempt to verify
// signatures using the experimental OCI 1.1 behavior.
func VerifyImageSignatures(ctx context.Context, signedImgRef name.Reference, co *CheckOpts) (checkedSignatures []oci.Signature, bundleVerified bool, err error) {
return VerifyImageSignaturesWithOpts(ctx, signedImgRef, co)
}

func VerifyImageSignaturesWithOpts(ctx context.Context, signedImgRef name.Reference, co *CheckOpts, svOpts ...signature.SignerVerifierOption) (checkedSignatures []oci.Signature, bundleVerified bool, err error) {
// Try first using OCI 1.1 behavior if experimental flag is set.
if co.ExperimentalOCI11 {
verified, bundleVerified, err := verifyImageSignaturesExperimentalOCI(ctx, signedImgRef, co)
Expand Down Expand Up @@ -642,7 +646,7 @@ func VerifyLocalImageSignatures(ctx context.Context, path string, co *CheckOpts)
return verifySignatures(ctx, sigs, h, co)
}

func verifySignatures(ctx context.Context, sigs oci.Signatures, h v1.Hash, co *CheckOpts) (checkedSignatures []oci.Signature, bundleVerified bool, err error) {
func verifySignatures(ctx context.Context, sigs oci.Signatures, h v1.Hash, co *CheckOpts, svOpts ...signature.SignerVerifierOption) (checkedSignatures []oci.Signature, bundleVerified bool, err error) {
sl, err := sigs.Get()
if err != nil {
return nil, false, err
Expand Down Expand Up @@ -670,7 +674,7 @@ func verifySignatures(ctx context.Context, sigs oci.Signatures, h v1.Hash, co *C
return
}

verified, err := VerifyImageSignature(ctx, sig, h, co)
verified, err := VerifyImageSignatureWithOpts(ctx, sig, h, co, svOpts...)
bundlesVerified[index] = verified
if err != nil {
t.Done(err)
Expand Down Expand Up @@ -876,13 +880,23 @@ func keyBytes(sig oci.Signature, co *CheckOpts) ([]byte, error) {

// VerifyBlobSignature verifies a blob signature.
func VerifyBlobSignature(ctx context.Context, sig oci.Signature, co *CheckOpts) (bundleVerified bool, err error) {
return VerifyBlobSignatureWithOpts(ctx, sig, co)
}

// VerifyBlobSignature verifies a blob signature.
func VerifyBlobSignatureWithOpts(ctx context.Context, sig oci.Signature, co *CheckOpts, svOpts ...signature.SignerVerifierOption) (bundleVerified bool, err error) {
// The hash of the artifact is unused.
return verifyInternal(ctx, sig, v1.Hash{}, verifyOCISignature, co, signature.WithED25519ph())
return verifyInternal(ctx, sig, v1.Hash{}, verifyOCISignature, co, svOpts...)
}

// VerifyImageSignature verifies a signature
func VerifyImageSignature(ctx context.Context, sig oci.Signature, h v1.Hash, co *CheckOpts) (bundleVerified bool, err error) {
return verifyInternal(ctx, sig, h, verifyOCISignature, co, signature.WithED25519ph())
return VerifyImageSignatureWithOpts(ctx, sig, h, co)
}

// VerifyImageSignature verifies a signature
func VerifyImageSignatureWithOpts(ctx context.Context, sig oci.Signature, h v1.Hash, co *CheckOpts, svOpts ...signature.SignerVerifierOption) (bundleVerified bool, err error) {
return verifyInternal(ctx, sig, h, verifyOCISignature, co, svOpts...)
}

func loadSignatureFromFile(ctx context.Context, sigRef string, signedImgRef name.Reference, co *CheckOpts) (oci.Signatures, error) {
Expand Down Expand Up @@ -1433,7 +1447,7 @@ func correctAnnotations(wanted, have map[string]interface{}) bool {

// verifyImageSignaturesExperimentalOCI does all the main cosign checks in a loop, returning the verified signatures.
// If there were no valid signatures, we return an error, using OCI 1.1+ behavior.
func verifyImageSignaturesExperimentalOCI(ctx context.Context, signedImgRef name.Reference, co *CheckOpts) (checkedSignatures []oci.Signature, bundleVerified bool, err error) {
func verifyImageSignaturesExperimentalOCI(ctx context.Context, signedImgRef name.Reference, co *CheckOpts, svOpts ...signature.SignerVerifierOption) (checkedSignatures []oci.Signature, bundleVerified bool, err error) {
// Enforce this up front.
if co.RootCerts == nil && co.SigVerifier == nil {
return nil, false, errors.New("one of verifier or root certs is required")
Expand Down Expand Up @@ -1486,5 +1500,5 @@ func verifyImageSignaturesExperimentalOCI(ctx context.Context, signedImgRef name
}
}

return verifySignatures(ctx, sigs, h, co)
return verifySignatures(ctx, sigs, h, co, svOpts...)
}
26 changes: 13 additions & 13 deletions pkg/signature/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ func LoadPublicKey(ctx context.Context, keyRef string) (verifier signature.Verif
// VerifierForKeyRef parses the given keyRef, loads the key and returns an appropriate
// verifier using the provided hash algorithm
func VerifierForKeyRef(ctx context.Context, keyRef string, hashAlgorithm crypto.Hash) (verifier signature.Verifier, err error) {
return VerifierForKeyRefWithOpts(ctx, keyRef, hashAlgorithm)
return VerifierForKeyRefWithOpts(ctx, keyRef, signature.WithHash(hashAlgorithm))
}

// VerifierForKeyRefWithOpts parses the given keyRef, loads the key and returns an appropriate
// verifier using the provided hash algorithm and options
func VerifierForKeyRefWithOpts(ctx context.Context, keyRef string, hashAlgorithm crypto.Hash, opts ...signature.SignerVerifierOption) (verifier signature.Verifier, err error) {
func VerifierForKeyRefWithOpts(ctx context.Context, keyRef string, opts ...signature.SignerVerifierOption) (verifier signature.Verifier, err error) {
// The key could be plaintext, in a file, at a URL, or in KMS.
var perr *kms.ProviderNotFoundError
kmsKey, err := kms.Get(ctx, keyRef, hashAlgorithm)
kmsKey, err := kms.Get(ctx, keyRef, signature.GetSignerVerifierOptionHash(opts...))
switch {
case err == nil:
// KMS specified
Expand All @@ -75,7 +75,7 @@ func VerifierForKeyRefWithOpts(ctx context.Context, keyRef string, hashAlgorithm
return nil, fmt.Errorf("pem to public key: %w", err)
}

return signature.LoadVerifierWithOpts(pubKey, hashAlgorithm, opts...)
return signature.LoadVerifierWithOpts(pubKey, opts...)
}

func loadKey(keyPath string, pf cosign.PassFunc, opts ...signature.SignerVerifierOption) (signature.SignerVerifier, error) {
Expand All @@ -95,16 +95,16 @@ func loadKey(keyPath string, pf cosign.PassFunc, opts ...signature.SignerVerifie

// LoadPublicKeyRaw loads a verifier from a PEM-encoded public key
func LoadPublicKeyRaw(raw []byte, hashAlgorithm crypto.Hash) (signature.Verifier, error) {
return LoadPublicKeyRawWithOpts(raw, hashAlgorithm)
return LoadPublicKeyRawWithOpts(raw, signature.WithHash(hashAlgorithm))
}

// LoadPublicKeyRawWithOpts loads a verifier from a PEM-encoded public key with options
func LoadPublicKeyRawWithOpts(raw []byte, hashAlgorithm crypto.Hash, opts ...signature.SignerVerifierOption) (signature.Verifier, error) {
func LoadPublicKeyRawWithOpts(raw []byte, opts ...signature.SignerVerifierOption) (signature.Verifier, error) {
pub, err := cryptoutils.UnmarshalPEMToPublicKey(raw)
if err != nil {
return nil, err
}
return signature.LoadVerifierWithOpts(pub, hashAlgorithm, opts...)
return signature.LoadVerifierWithOpts(pub, opts...)
}

func SignerFromKeyRef(ctx context.Context, keyRef string, pf cosign.PassFunc) (signature.Signer, error) {
Expand Down Expand Up @@ -184,22 +184,22 @@ func SignerVerifierFromKeyRefWithOpts(ctx context.Context, keyRef string, pf cos
}

func PublicKeyFromKeyRef(ctx context.Context, keyRef string) (signature.Verifier, error) {
return PublicKeyFromKeyRefWithOpts(ctx, keyRef, crypto.SHA256)
return PublicKeyFromKeyRefWithOpts(ctx, keyRef, signature.WithHash(crypto.SHA256))
}

func PublicKeyFromKeyRefWithHashAlgo(ctx context.Context, keyRef string, hashAlgorithm crypto.Hash) (signature.Verifier, error) {
return PublicKeyFromKeyRefWithOpts(ctx, keyRef, hashAlgorithm)
return PublicKeyFromKeyRefWithOpts(ctx, keyRef, signature.WithHash(hashAlgorithm))
}

func PublicKeyFromKeyRefWithOpts(ctx context.Context, keyRef string, hashAlgorithm crypto.Hash, opts ...signature.SignerVerifierOption) (signature.Verifier, error) {
func PublicKeyFromKeyRefWithOpts(ctx context.Context, keyRef string, opts ...signature.SignerVerifierOption) (signature.Verifier, error) {
if strings.HasPrefix(keyRef, kubernetes.KeyReference) {
s, err := kubernetes.GetKeyPairSecret(ctx, keyRef)
if err != nil {
return nil, err
}

if len(s.Data) > 0 {
return LoadPublicKeyRawWithOpts(s.Data["cosign.pub"], hashAlgorithm, opts...)
return LoadPublicKeyRawWithOpts(s.Data["cosign.pub"], opts...)
}
}

Expand Down Expand Up @@ -238,11 +238,11 @@ func PublicKeyFromKeyRefWithOpts(ctx context.Context, keyRef string, hashAlgorit
}

if len(pubKey) > 0 {
return LoadPublicKeyRawWithOpts([]byte(pubKey), hashAlgorithm, opts...)
return LoadPublicKeyRawWithOpts([]byte(pubKey), opts...)
}
}

return VerifierForKeyRefWithOpts(ctx, keyRef, hashAlgorithm, opts...)
return VerifierForKeyRefWithOpts(ctx, keyRef, opts...)
}

func PublicKeyPem(key signature.PublicKeyProvider, pkOpts ...signature.PublicKeyOption) ([]byte, error) {
Expand Down

0 comments on commit afdad84

Please sign in to comment.