Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions cmd/cosign/cli/fulcio/fulcio.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,6 @@ type Signer struct {
}

func NewSigner(ctx context.Context, ko options.KeyOpts, signer signature.SignerVerifier) (*Signer, error) {
return NewSignerWithAdapter(ctx, ko, signer, signer)
}

// NewSignerWithAdapter creates a Fulcio Signer with a `fulcioSigner` that is
// used to sign the Proof Of Possession sent to Fulcio. In most cases this will
// be the same as the `signer`, however it is possible to use a different signer.
// For example when ed25519ph is used for signing, the `fulcioSigner` will be
// the equivalent PureED25519 signer, given that Fulcio does not support ed25519ph.
func NewSignerWithAdapter(ctx context.Context, ko options.KeyOpts, signer signature.SignerVerifier, fulcioSigner signature.SignerVerifier) (*Signer, error) {
fClient, err := NewClient(ko.FulcioURL)
if err != nil {
return nil, fmt.Errorf("creating Fulcio client: %w", err)
Expand All @@ -96,7 +87,7 @@ func NewSignerWithAdapter(ctx context.Context, ko options.KeyOpts, signer signat
return nil, fmt.Errorf("setting auth flow: %w", err)
}

resp, err := GetCert(ctx, fulcioSigner, idToken, flow, ko.OIDCIssuer, ko.OIDCClientID, ko.OIDCClientSecret, ko.OIDCRedirectURL, fClient)
resp, err := GetCert(ctx, signer, idToken, flow, ko.OIDCIssuer, ko.OIDCClientID, ko.OIDCClientSecret, ko.OIDCRedirectURL, fClient)
if err != nil {
return nil, fmt.Errorf("retrieving cert: %w", err)
}
Expand Down
6 changes: 1 addition & 5 deletions cmd/cosign/cli/fulcio/fulcioverifier/fulcioverifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ import (
)

func NewSigner(ctx context.Context, ko options.KeyOpts, signer signature.SignerVerifier) (*fulcio.Signer, error) {
return NewSignerWithAdapter(ctx, ko, signer, signer)
}

func NewSignerWithAdapter(ctx context.Context, ko options.KeyOpts, signer signature.SignerVerifier, fulcioSigner signature.SignerVerifier) (*fulcio.Signer, error) {
fs, err := fulcio.NewSignerWithAdapter(ctx, ko, signer, fulcioSigner)
fs, err := fulcio.NewSigner(ctx, ko, signer)
if err != nil {
return nil, err
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/cosign/cli/options/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ type VerifyAttestationOptions struct {
CertVerify CertVerifyOptions
Registry RegistryOptions
Predicate PredicateRemoteOptions
SignatureDigest SignatureDigestOptions
Policies []string
LocalImage bool
}
Expand All @@ -151,6 +152,7 @@ func (o *VerifyAttestationOptions) AddFlags(cmd *cobra.Command) {
o.Registry.AddFlags(cmd)
o.Predicate.AddFlags(cmd)
o.CommonVerifyOptions.AddFlags(cmd)
o.SignatureDigest.AddFlags(cmd)

cmd.Flags().StringVar(&o.Key, "key", "",
"path to the public key file, KMS URI or Kubernetes Secret")
Expand Down Expand Up @@ -178,6 +180,7 @@ type VerifyBlobOptions struct {
CertVerify CertVerifyOptions
Rekor RekorOptions
CommonVerifyOptions CommonVerifyOptions
SignatureDigest SignatureDigestOptions

RFC3161TimestampPath string
}
Expand All @@ -190,6 +193,7 @@ func (o *VerifyBlobOptions) AddFlags(cmd *cobra.Command) {
o.Rekor.AddFlags(cmd)
o.CertVerify.AddFlags(cmd)
o.CommonVerifyOptions.AddFlags(cmd)
o.SignatureDigest.AddFlags(cmd)

cmd.Flags().StringVar(&o.Key, "key", "",
"path to the public key file, KMS URI or Kubernetes Secret")
Expand Down Expand Up @@ -233,6 +237,7 @@ type VerifyBlobAttestationOptions struct {
CertVerify CertVerifyOptions
Rekor RekorOptions
CommonVerifyOptions CommonVerifyOptions
SignatureDigest SignatureDigestOptions

RFC3161TimestampPath string

Expand All @@ -249,6 +254,7 @@ func (o *VerifyBlobAttestationOptions) AddFlags(cmd *cobra.Command) {
o.Rekor.AddFlags(cmd)
o.CertVerify.AddFlags(cmd)
o.CommonVerifyOptions.AddFlags(cmd)
o.SignatureDigest.AddFlags(cmd)

cmd.Flags().StringVar(&o.Key, "key", "",
"path to the public key file, KMS URI or Kubernetes Secret")
Expand Down
31 changes: 4 additions & 27 deletions cmd/cosign/cli/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,45 +702,22 @@ func signerFromNewKey() (*SignerVerifier, error) {
}, nil
}

// adaptSignerVerifierToFulcio adapts, if necessary, the SignerVerifier to be
// used to interact with Fulcio.
//
// This is needed in particular for ED25519 keys with the pre-hashed version of
// the algorithm, which is not supported by Fulcio. This function creates a
// ED25519 SignerVerifier based on that instead.
func adaptSignerVerifierToFulcio(sv *SignerVerifier) (*SignerVerifier, error) {
if ed25519phSV, ok := sv.SignerVerifier.(*signature.ED25519phSignerVerifier); ok {
signerVerifier, err := ed25519phSV.ToED25519SignerVerifier()
if err != nil {
return nil, err
}

return &SignerVerifier{
SignerVerifier: signerVerifier,
Cert: sv.Cert,
Chain: sv.Chain,
}, nil
}
return sv, nil
}

func KeylessSigner(ctx context.Context, ko options.KeyOpts, sv *SignerVerifier) (*SignerVerifier, error) {
var (
k *fulcio.Signer
err error
)

fulcioSV, err := adaptSignerVerifierToFulcio(sv)
if err != nil {
return nil, fmt.Errorf("adapting signer verifier to Fulcio: %w", err)
if _, ok := sv.SignerVerifier.(*signature.ED25519phSignerVerifier); ok {
return nil, fmt.Errorf("ed25519ph unsupported by Fulcio")
}

if ko.InsecureSkipFulcioVerify {
if k, err = fulcio.NewSignerWithAdapter(ctx, ko, sv, fulcioSV); err != nil {
if k, err = fulcio.NewSigner(ctx, ko, sv); err != nil {
return nil, fmt.Errorf("getting key from Fulcio: %w", err)
}
} else {
if k, err = fulcioverifier.NewSignerWithAdapter(ctx, ko, sv, fulcioSV); err != nil {
if k, err = fulcioverifier.NewSigner(ctx, ko, sv); err != nil {
return nil, fmt.Errorf("getting key from Fulcio: %w", err)
}
}
Expand Down
18 changes: 18 additions & 0 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ against the transparency log.`,
o.CommonVerifyOptions.IgnoreTlog = true
}

hashAlgorithm, err := o.SignatureDigest.HashAlgorithm()
if err != nil {
return err
}

v := &verify.VerifyAttestationCommand{
RegistryOptions: o.Registry,
CommonVerifyOptions: o.CommonVerifyOptions,
Expand Down Expand Up @@ -247,6 +252,7 @@ against the transparency log.`,
TSACertChainPath: o.CommonVerifyOptions.TSACertChainPath,
IgnoreTlog: o.CommonVerifyOptions.IgnoreTlog,
MaxWorkers: o.CommonVerifyOptions.MaxWorkers,
HashAlgorithm: hashAlgorithm,
UseSignedTimestamps: o.CommonVerifyOptions.UseSignedTimestamps,
}

Expand Down Expand Up @@ -330,6 +336,11 @@ The blob may be specified as a path to a file or - for stdin.`,
o.CommonVerifyOptions.IgnoreTlog = true
}

hashAlgorithm, err := o.SignatureDigest.HashAlgorithm()
if err != nil {
return err
}

ko := options.KeyOpts{
KeyRef: o.Key,
Sk: o.SecurityKey.Use,
Expand Down Expand Up @@ -359,6 +370,7 @@ The blob may be specified as a path to a file or - for stdin.`,
IgnoreTlog: o.CommonVerifyOptions.IgnoreTlog,
UseSignedTimestamps: o.CommonVerifyOptions.UseSignedTimestamps,
TrustedRootPath: o.CommonVerifyOptions.TrustedRootPath,
HashAlgorithm: hashAlgorithm,
}

ctx, cancel := context.WithTimeout(cmd.Context(), ro.Timeout)
Expand Down Expand Up @@ -401,6 +413,11 @@ The blob may be specified as a path to a file.`,
o.CommonVerifyOptions.IgnoreTlog = true
}

hashAlgorithm, err := o.SignatureDigest.HashAlgorithm()
if err != nil {
return err
}

ko := options.KeyOpts{
KeyRef: o.Key,
Sk: o.SecurityKey.Use,
Expand Down Expand Up @@ -434,6 +451,7 @@ The blob may be specified as a path to a file.`,
TrustedRootPath: o.CommonVerifyOptions.TrustedRootPath,
Digest: o.Digest,
DigestAlg: o.DigestAlg,
HashAlgorithm: hashAlgorithm,
}
// We only use the blob if we are checking claims.
if o.CheckClaims && len(args) == 0 && (o.Digest == "" || o.DigestAlg == "") {
Expand Down
9 changes: 8 additions & 1 deletion cmd/cosign/cli/verify/verify_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package verify

import (
"context"
"crypto"
"errors"
"flag"
"fmt"
Expand Down Expand Up @@ -73,6 +74,7 @@ type VerifyAttestationCommand struct {
IgnoreTlog bool
MaxWorkers int
UseSignedTimestamps bool
HashAlgorithm crypto.Hash
}

// Exec runs the verification command
Expand All @@ -81,6 +83,11 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e
return flag.ErrHelp
}

// always default to sha256 if the algorithm hasn't been explicitly set
if c.HashAlgorithm == 0 {
c.HashAlgorithm = crypto.SHA256
}

// We can't have both a key and a security key
if options.NOf(c.KeyRef, c.Sk) > 1 {
return &options.KeyParseError{}
Expand Down Expand Up @@ -191,7 +198,7 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e
// Keys are optional!
switch {
case keyRef != "":
co.SigVerifier, err = sigs.PublicKeyFromKeyRef(ctx, keyRef)
co.SigVerifier, err = sigs.PublicKeyFromKeyRefWithHashAlgo(ctx, keyRef, c.HashAlgorithm)
if err != nil {
return fmt.Errorf("loading public key: %w", err)
}
Expand Down
8 changes: 7 additions & 1 deletion cmd/cosign/cli/verify/verify_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,16 @@ type VerifyBlobCmd struct {
Offline bool
UseSignedTimestamps bool
IgnoreTlog bool
HashAlgorithm crypto.Hash
}

// nolint
func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
// always default to sha256 if the algorithm hasn't been explicitly set
if c.HashAlgorithm == 0 {
c.HashAlgorithm = crypto.SHA256
}

// Require a certificate/key OR a local bundle file that has the cert.
if options.NOf(c.KeyRef, c.CertRef, c.Sk, c.BundlePath) == 0 {
return fmt.Errorf("provide a key with --key or --sk, a certificate to verify against with --certificate, or a bundle with --bundle")
Expand Down Expand Up @@ -116,7 +122,7 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
opts := make([]static.Option, 0)
switch {
case c.KeyRef != "":
co.SigVerifier, err = sigs.PublicKeyFromKeyRef(ctx, c.KeyRef)
co.SigVerifier, err = sigs.PublicKeyFromKeyRefWithHashAlgo(ctx, c.KeyRef, c.HashAlgorithm)
if err != nil {
return fmt.Errorf("loading public key: %w", err)
}
Expand Down
12 changes: 9 additions & 3 deletions cmd/cosign/cli/verify/verify_blob_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ type VerifyBlobAttestationCommand struct {
SignaturePath string // Path to the signature
UseSignedTimestamps bool

Digest string
DigestAlg string
Digest string
DigestAlg string
HashAlgorithm crypto.Hash
}

// Exec runs the verification command
Expand All @@ -89,6 +90,11 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st
return fmt.Errorf("please specify path to the DSSE envelope signature via --signature or --bundle")
}

// always default to sha256 if the algorithm hasn't been explicitly set
if c.HashAlgorithm == 0 {
c.HashAlgorithm = crypto.SHA256
}

// Require a certificate/key OR a local bundle file that has the cert.
if options.NOf(c.KeyRef, c.CertRef, c.Sk, c.BundlePath) == 0 {
return fmt.Errorf("provide a key with --key or --sk, a certificate to verify against with --certificate, or a bundle with --bundle")
Expand Down Expand Up @@ -126,7 +132,7 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st
opts := make([]static.Option, 0)
switch {
case c.KeyRef != "":
co.SigVerifier, err = sigs.PublicKeyFromKeyRef(ctx, c.KeyRef)
co.SigVerifier, err = sigs.PublicKeyFromKeyRefWithHashAlgo(ctx, c.KeyRef, c.HashAlgorithm)
if err != nil {
return fmt.Errorf("loading public key: %w", err)
}
Expand Down
14 changes: 7 additions & 7 deletions cmd/cosign/cli/verify/verify_blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import (

"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
"github.com/go-openapi/runtime"
"github.com/go-openapi/swag"
"github.com/go-openapi/swag/conv"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/internal/pkg/cosign/tsa/mock"
"github.com/sigstore/cosign/v2/internal/test"
Expand Down Expand Up @@ -701,9 +701,9 @@ func makeRekorEntry(t *testing.T, rekorSigner signature.ECDSASignerVerifier,
}
e := models.LogEntryAnon{
Body: base64.StdEncoding.EncodeToString(leaf),
IntegratedTime: swag.Int64(integratedTime.Unix()),
LogIndex: swag.Int64(0),
LogID: swag.String(logID),
IntegratedTime: conv.Pointer(integratedTime.Unix()),
LogIndex: conv.Pointer(int64(0)),
LogID: conv.Pointer(logID),
}
// Marshal payload, sign, and set SET in Bundle
jsonPayload, err := json.Marshal(e)
Expand All @@ -723,9 +723,9 @@ func makeRekorEntry(t *testing.T, rekorSigner signature.ECDSASignerVerifier,
e.Verification = &models.LogEntryAnonVerification{
SignedEntryTimestamp: bundleSig,
InclusionProof: &models.InclusionProof{
LogIndex: swag.Int64(0),
TreeSize: swag.Int64(1),
RootHash: swag.String(hex.EncodeToString(uuid)),
LogIndex: conv.Pointer(int64(0)),
TreeSize: conv.Pointer(int64(1)),
RootHash: conv.Pointer(hex.EncodeToString(uuid)),
Hashes: []string{},
},
}
Expand Down
1 change: 1 addition & 0 deletions doc/cosign_verify-attestation.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions doc/cosign_verify-blob-attestation.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions doc/cosign_verify-blob.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading