From 0cfa089a96e5049766b03c5f97336f37a70bc588 Mon Sep 17 00:00:00 2001 From: Riccardo Schirone Date: Fri, 19 Jan 2024 17:53:43 +0100 Subject: [PATCH] Add --signing-algorithm flag --- cmd/cosign/cli/generate/generate_key_pair.go | 14 +++- .../cli/generate/generate_key_pair_test.go | 2 +- cmd/cosign/cli/generate_key_pair.go | 5 +- cmd/cosign/cli/options/generate_key_pair.go | 16 ++++- cmd/cosign/cli/options/key.go | 5 +- cmd/cosign/cli/options/sign.go | 12 ++++ cmd/cosign/cli/options/signblob.go | 12 ++++ cmd/cosign/cli/sign.go | 1 + cmd/cosign/cli/sign/sign.go | 41 ++++++----- cmd/cosign/cli/sign/sign_blob.go | 8 +-- cmd/cosign/cli/signblob.go | 1 + go.mod | 5 +- go.sum | 6 +- pkg/cosign/keys.go | 70 +++++++++++++++++-- 14 files changed, 158 insertions(+), 40 deletions(-) diff --git a/cmd/cosign/cli/generate/generate_key_pair.go b/cmd/cosign/cli/generate/generate_key_pair.go index 6311fe07611..fde11c24abe 100644 --- a/cmd/cosign/cli/generate/generate_key_pair.go +++ b/cmd/cosign/cli/generate/generate_key_pair.go @@ -34,6 +34,7 @@ import ( "github.com/sigstore/cosign/v2/pkg/cosign" "github.com/sigstore/cosign/v2/pkg/cosign/kubernetes" "github.com/sigstore/sigstore/pkg/cryptoutils" + "github.com/sigstore/sigstore/pkg/signature" "github.com/sigstore/sigstore/pkg/signature/kms" ) @@ -43,7 +44,7 @@ var ( ) // nolint -func GenerateKeyPairCmd(ctx context.Context, kmsVal string, outputKeyPrefixVal string, args []string) error { +func GenerateKeyPairCmd(ctx context.Context, kmsVal string, outputKeyPrefixVal string, signatureAlgorithmName string, args []string) error { privateKeyFileName := outputKeyPrefixVal + ".key" publicKeyFileName := outputKeyPrefixVal + ".pub" @@ -86,7 +87,16 @@ func GenerateKeyPairCmd(ctx context.Context, kmsVal string, outputKeyPrefixVal s return fmt.Errorf("undefined provider: %s", provider) } - keys, err := cosign.GenerateKeyPair(GetPass) + signatureAlgorithm, err := signature.ParseSignatureAlgorithmFlag(signatureAlgorithmName) + if err != nil { + return err + } + algorithmDetails, err := signature.GetAlgorithmDetails(signatureAlgorithm) + if err != nil { + return err + } + + keys, err := cosign.GenerateKeyPairWithAlgo(GetPass, algorithmDetails) if err != nil { return err } diff --git a/cmd/cosign/cli/generate/generate_key_pair_test.go b/cmd/cosign/cli/generate/generate_key_pair_test.go index f860382ea4e..33fab4a75d5 100644 --- a/cmd/cosign/cli/generate/generate_key_pair_test.go +++ b/cmd/cosign/cli/generate/generate_key_pair_test.go @@ -57,7 +57,7 @@ func TestGenerationOfKeys(t *testing.T) { // be default it's set to `cosign`, but this is done by the CLI flag // framework if there is no value set by the user when running the // command. - GenerateKeyPairCmd(context.Background(), "", "my-test", nil) + GenerateKeyPairCmd(context.Background(), "", "my-test", "ecdsa-sha2-256-nistp256", nil) checkIfFileExistsThenDelete(privateKeyName, t) checkIfFileExistsThenDelete(publicKeyName, t) diff --git a/cmd/cosign/cli/generate_key_pair.go b/cmd/cosign/cli/generate_key_pair.go index 3600d771d18..c0478632f89 100644 --- a/cmd/cosign/cli/generate_key_pair.go +++ b/cmd/cosign/cli/generate_key_pair.go @@ -34,6 +34,9 @@ func GenerateKeyPair() *cobra.Command { # generate key-pair and write to cosign.key and cosign.pub files cosign generate-key-pair + # generate ED25519 key-pair and write to cosign.key and cosign.pub files + cosign generate-key-pair --signing-algorithm=ed25519-ph + # generate key-pair and write to custom named my-name.key and my-name.pub files cosign generate-key-pair --output-key-prefix my-name @@ -67,7 +70,7 @@ CAVEATS: PersistentPreRun: options.BindViper, RunE: func(cmd *cobra.Command, args []string) error { - return generate.GenerateKeyPairCmd(cmd.Context(), o.KMS, o.OutputKeyPrefix, args) + return generate.GenerateKeyPairCmd(cmd.Context(), o.KMS, o.OutputKeyPrefix, o.SigningAlgorithm, args) }, } diff --git a/cmd/cosign/cli/options/generate_key_pair.go b/cmd/cosign/cli/options/generate_key_pair.go index 4acd94ae100..3a6a1bd8383 100644 --- a/cmd/cosign/cli/options/generate_key_pair.go +++ b/cmd/cosign/cli/options/generate_key_pair.go @@ -16,14 +16,21 @@ package options import ( + "fmt" + "strings" + + "github.com/sigstore/cosign/v2/pkg/cosign" + v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1" + "github.com/sigstore/sigstore/pkg/signature" "github.com/spf13/cobra" ) // GenerateKeyPairOptions is the top level wrapper for the generate-key-pair command. type GenerateKeyPairOptions struct { // KMS Key Management Service - KMS string - OutputKeyPrefix string + KMS string + OutputKeyPrefix string + SigningAlgorithm string } var _ Interface = (*GenerateKeyPairOptions)(nil) @@ -34,4 +41,9 @@ func (o *GenerateKeyPairOptions) AddFlags(cmd *cobra.Command) { "create key pair in KMS service to use for signing") cmd.Flags().StringVar(&o.OutputKeyPrefix, "output-key-prefix", "cosign", "name used for generated .pub and .key files (defaults to `cosign`)") + + keyAlgorithmTypes := cosign.GetSupportedAlgorithms() + keyAlgorithmHelp := fmt.Sprintf("signing algorithm to use for signing/hashing (allowed %s)", strings.Join(keyAlgorithmTypes, ", ")) + defaultKeyFlag, _ := signature.FormatSignatureAlgorithmFlag(v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256) + cmd.Flags().StringVar(&o.SigningAlgorithm, "signing-algorithm", defaultKeyFlag, keyAlgorithmHelp) } diff --git a/cmd/cosign/cli/options/key.go b/cmd/cosign/cli/options/key.go index 6af69afda37..0fccdce69e5 100644 --- a/cmd/cosign/cli/options/key.go +++ b/cmd/cosign/cli/options/key.go @@ -15,12 +15,15 @@ package options -import "github.com/sigstore/cosign/v2/pkg/cosign" +import ( + "github.com/sigstore/cosign/v2/pkg/cosign" +) type KeyOpts struct { Sk bool Slot string KeyRef string + SigningAlgorithm string FulcioURL string RekorURL string IDToken string diff --git a/cmd/cosign/cli/options/sign.go b/cmd/cosign/cli/options/sign.go index c7cef860723..2c1491eb4ac 100644 --- a/cmd/cosign/cli/options/sign.go +++ b/cmd/cosign/cli/options/sign.go @@ -16,12 +16,19 @@ package options import ( + "fmt" + "strings" + + "github.com/sigstore/cosign/v2/pkg/cosign" + v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1" + "github.com/sigstore/sigstore/pkg/signature" "github.com/spf13/cobra" ) // SignOptions is the top level wrapper for the sign command. type SignOptions struct { Key string + SigningAlgorithm string Cert string CertChain string Upload bool @@ -67,6 +74,11 @@ func (o *SignOptions) AddFlags(cmd *cobra.Command) { "path to the private key file, KMS URI or Kubernetes Secret") _ = cmd.Flags().SetAnnotation("key", cobra.BashCompFilenameExt, []string{}) + keyAlgorithmTypes := cosign.GetSupportedAlgorithms() + keyAlgorithmHelp := fmt.Sprintf("signing algorithm to use for signing/hashing (allowed %s)", strings.Join(keyAlgorithmTypes, ", ")) + defaultKeyFlag, _ := signature.FormatSignatureAlgorithmFlag(v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256) + cmd.Flags().StringVar(&o.SigningAlgorithm, "signing-algorithm", defaultKeyFlag, keyAlgorithmHelp) + cmd.Flags().StringVar(&o.Cert, "certificate", "", "path to the X.509 certificate in PEM format to include in the OCI Signature") _ = cmd.Flags().SetAnnotation("certificate", cobra.BashCompFilenameExt, []string{"cert"}) diff --git a/cmd/cosign/cli/options/signblob.go b/cmd/cosign/cli/options/signblob.go index 7cddde63dfc..48f0e0e11f0 100644 --- a/cmd/cosign/cli/options/signblob.go +++ b/cmd/cosign/cli/options/signblob.go @@ -16,6 +16,12 @@ package options import ( + "fmt" + "strings" + + "github.com/sigstore/cosign/v2/pkg/cosign" + v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1" + "github.com/sigstore/sigstore/pkg/signature" "github.com/spf13/cobra" ) @@ -23,6 +29,7 @@ import ( // The new output-certificate flag is only in use when COSIGN_EXPERIMENTAL is enabled type SignBlobOptions struct { Key string + SigningAlgorithm string Base64Output bool Output string // deprecated: TODO remove when the output flag is fully deprecated OutputSignature string // TODO: this should be the root output file arg. @@ -57,6 +64,11 @@ func (o *SignBlobOptions) AddFlags(cmd *cobra.Command) { "path to the private key file, KMS URI or Kubernetes Secret") _ = cmd.Flags().SetAnnotation("key", cobra.BashCompFilenameExt, []string{}) + keyAlgorithmTypes := cosign.GetSupportedAlgorithms() + keyAlgorithmHelp := fmt.Sprintf("signing algorithm to use for signing/hashing (allowed %s)", strings.Join(keyAlgorithmTypes, ", ")) + defaultKeyFlag, _ := signature.FormatSignatureAlgorithmFlag(v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256) + cmd.Flags().StringVar(&o.SigningAlgorithm, "signing-algorithm", defaultKeyFlag, keyAlgorithmHelp) + cmd.Flags().BoolVar(&o.Base64Output, "b64", true, "whether to base64 encode the output") diff --git a/cmd/cosign/cli/sign.go b/cmd/cosign/cli/sign.go index e937be58ae9..a540f365938 100644 --- a/cmd/cosign/cli/sign.go +++ b/cmd/cosign/cli/sign.go @@ -102,6 +102,7 @@ race conditions or (worse) malicious tampering. } ko := options.KeyOpts{ KeyRef: o.Key, + SigningAlgorithm: o.SigningAlgorithm, PassFunc: generate.GetPass, Sk: o.SecurityKey.Use, Slot: o.SecurityKey.Slot, diff --git a/cmd/cosign/cli/sign/sign.go b/cmd/cosign/cli/sign/sign.go index 348a985e03f..fde8af222b7 100644 --- a/cmd/cosign/cli/sign/sign.go +++ b/cmd/cosign/cli/sign/sign.go @@ -18,7 +18,6 @@ package sign import ( "bytes" "context" - "crypto" "crypto/x509" "encoding/base64" "encoding/json" @@ -32,6 +31,7 @@ import ( "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/remote" + pb_go_v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1" "github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio" "github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio/fulcioverifier" @@ -138,12 +138,7 @@ func SignCmd(ro *options.RootOptions, ko options.KeyOpts, signOpts options.SignO ctx, cancel := context.WithTimeout(context.Background(), ro.Timeout) defer cancel() - svOptions := []signature.LoadOption{ - signatureoptions.WithHash(crypto.SHA256), - signatureoptions.WithED25519ph(), - } - - sv, err := signerFromKeyOptsWithSVOpts(ctx, signOpts.Cert, signOpts.CertChain, ko, svOptions...) + sv, err := SignerFromKeyOpts(ctx, signOpts.Cert, signOpts.CertChain, ko) if err != nil { return fmt.Errorf("getting signer: %w", err) } @@ -531,8 +526,8 @@ func signerFromKeyRef(ctx context.Context, certPath, certChainPath, keyRef strin return certSigner, nil } -func signerFromNewKey(svOpts ...signature.LoadOption) (*SignerVerifier, error) { - privKey, err := cosign.GeneratePrivateKey() +func signerFromNewKey(algorithmDetails signature.AlgorithmDetails, svOpts ...signature.LoadOption) (*SignerVerifier, error) { + privKey, err := cosign.GeneratePrivateKeyWithAlgo(algorithmDetails) if err != nil { return nil, fmt.Errorf("generating cert: %w", err) } @@ -569,9 +564,27 @@ func keylessSigner(ctx context.Context, ko options.KeyOpts, sv *SignerVerifier) }, nil } -func signerFromKeyOptsWithSVOpts(ctx context.Context, certPath string, certChainPath string, ko options.KeyOpts, svOpts ...signature.LoadOption) (*SignerVerifier, error) { +func SignerFromKeyOpts(ctx context.Context, certPath string, certChainPath string, ko options.KeyOpts) (*SignerVerifier, error) { + var svOpts []signature.LoadOption + signingAlgorithm, err := signature.ParseSignatureAlgorithmFlag(ko.SigningAlgorithm) + if err != nil { + // Default to ECDSA_SHA2_256_NISTP256 if no algorithm is specified + signingAlgorithm = pb_go_v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256 + } + + algorithmDetails, err := signature.GetAlgorithmDetails(signingAlgorithm) + if err != nil { + return nil, err + } + hashAlgorithm := algorithmDetails.GetHashType() + svOpts = []signature.LoadOption{ + signatureoptions.WithHash(hashAlgorithm), + } + if algorithmDetails.GetSignatureAlgorithm() == pb_go_v1.KnownSignatureAlgorithm_ED25519_PH { + svOpts = append(svOpts, signatureoptions.WithED25519ph()) + } + var sv *SignerVerifier - var err error genKey := false switch { case ko.Sk: @@ -581,7 +594,7 @@ func signerFromKeyOptsWithSVOpts(ctx context.Context, certPath string, certChain default: genKey = true ui.Infof(ctx, "Generating ephemeral keys...") - sv, err = signerFromNewKey(svOpts...) + sv, err = signerFromNewKey(algorithmDetails, svOpts...) } if err != nil { return nil, err @@ -594,10 +607,6 @@ func signerFromKeyOptsWithSVOpts(ctx context.Context, certPath string, certChain return sv, nil } -func SignerFromKeyOpts(ctx context.Context, certPath string, certChainPath string, ko options.KeyOpts) (*SignerVerifier, error) { - return signerFromKeyOptsWithSVOpts(ctx, certPath, certChainPath, ko) -} - type SignerVerifier struct { Cert []byte Chain []byte diff --git a/cmd/cosign/cli/sign/sign_blob.go b/cmd/cosign/cli/sign/sign_blob.go index e7a4467daad..60ac52204e3 100644 --- a/cmd/cosign/cli/sign/sign_blob.go +++ b/cmd/cosign/cli/sign/sign_blob.go @@ -36,7 +36,6 @@ import ( "github.com/sigstore/cosign/v2/pkg/cosign" cbundle "github.com/sigstore/cosign/v2/pkg/cosign/bundle" "github.com/sigstore/sigstore/pkg/cryptoutils" - "github.com/sigstore/sigstore/pkg/signature" signatureoptions "github.com/sigstore/sigstore/pkg/signature/options" ) @@ -66,12 +65,7 @@ func SignBlobCmd(ro *options.RootOptions, ko options.KeyOpts, payloadPath string ctx, cancel := context.WithTimeout(context.Background(), ro.Timeout) defer cancel() - svOptions := []signature.LoadOption{ - signatureoptions.WithHash(crypto.SHA256), - signatureoptions.WithED25519ph(), - } - - sv, err := signerFromKeyOptsWithSVOpts(ctx, "", "", ko, svOptions...) + sv, err := SignerFromKeyOpts(ctx, "", "", ko) if err != nil { return nil, err } diff --git a/cmd/cosign/cli/signblob.go b/cmd/cosign/cli/signblob.go index ce3035a1d15..389797ff84c 100644 --- a/cmd/cosign/cli/signblob.go +++ b/cmd/cosign/cli/signblob.go @@ -70,6 +70,7 @@ func SignBlob() *cobra.Command { } ko := options.KeyOpts{ KeyRef: o.Key, + SigningAlgorithm: o.SigningAlgorithm, PassFunc: generate.GetPass, Sk: o.SecurityKey.Use, Slot: o.SecurityKey.Slot, diff --git a/go.mod b/go.mod index a8ed3cdf4fa..647bc0cae36 100644 --- a/go.mod +++ b/go.mod @@ -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.3.0-beta.2 github.com/sigstore/rekor v1.3.4 github.com/sigstore/sigstore v1.8.1 github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.1 @@ -278,6 +279,6 @@ require ( ) // TODO: REMOVE ME -replace github.com/sigstore/sigstore => github.com/trail-of-forks/sigstore v0.0.0-20240129151206-cff4abcde12e +replace github.com/sigstore/sigstore => /Users/ret2libc/projects/sigstore/sigstore -replace github.com/sigstore/rekor => github.com/trail-of-forks/rekor v0.0.0-20240129163653-3ac4c89bd056 +replace github.com/sigstore/rekor => /Users/ret2libc/projects/sigstore/rekor diff --git a/go.sum b/go.sum index ce0d2df33d2..0795d583fc9 100644 --- a/go.sum +++ b/go.sum @@ -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.3.0-beta.2 h1:neHS0O1z7qz4q21vyXqSaKuKYxA0upzJERT88NrgYlM= +github.com/sigstore/protobuf-specs v0.3.0-beta.2/go.mod h1:ynKzXpqr3dUj2Xk9O/5ZUhjnpi0F53DNi5AdH6pS3jc= github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.1 h1:rEDdUefulkIQaMJyzLwtgPDLNXBIltBABiFYfb0YmgQ= github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.1/go.mod h1:RCdYCc1IxCYWzh2IdzdA6Yf7JIY0cMRqH08fpQYechw= github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.1 h1:DvRWG99QGWZC5mp42SEde2Xke/Q384Idnj2da7yB+Mk= @@ -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-20240129163653-3ac4c89bd056 h1:jTVzEjC2Mm5x9mnZwKyspP7ygDyP1BiZHleUvh81V4Y= -github.com/trail-of-forks/rekor v0.0.0-20240129163653-3ac4c89bd056/go.mod h1:KMOYGlQZ96wQ0MfdHvVHjp8mM0fA8Lh6sqtwYkXP5YE= -github.com/trail-of-forks/sigstore v0.0.0-20240129151206-cff4abcde12e h1:EXVlV8GAQ7nct3uYZwga7JVjQ/GfwWAtMKbmYll3sZ8= -github.com/trail-of-forks/sigstore v0.0.0-20240129151206-cff4abcde12e/go.mod h1:rbZxJoss0Qf/OQeIuyqkQxo9jLKZlyLqOGX0BUaK7/I= 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= diff --git a/pkg/cosign/keys.go b/pkg/cosign/keys.go index fb6debfe396..ca5b65f4b24 100644 --- a/pkg/cosign/keys.go +++ b/pkg/cosign/keys.go @@ -19,7 +19,6 @@ import ( "crypto" "crypto/ecdsa" "crypto/ed25519" - "crypto/elliptic" "crypto/rand" "crypto/rsa" _ "crypto/sha256" // for `crypto.SHA256` @@ -29,9 +28,11 @@ import ( "fmt" "os" "path/filepath" + "sort" "github.com/secure-systems-lab/go-securesystemslib/encrypted" "github.com/sigstore/cosign/v2/pkg/oci/static" + v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" ) @@ -69,9 +70,56 @@ func (k *KeysBytes) Password() []byte { return k.password } +var ClientAlgorithmsRegistry, _ = signature.NewAlgorithmRegistryConfig([]v1.KnownSignatureAlgorithm{ + v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256, + v1.KnownSignatureAlgorithm_ED25519_PH, +}) + +func GetSupportedAlgorithms() []string { + // Get the list of supported algorithms from v1.KnownSignatureAlgorithm_name + // and sort them alphabetically. + algorithms := make([]string, 0, len(v1.KnownSignatureAlgorithm_name)) + for algorithmId := range v1.KnownSignatureAlgorithm_name { + signatureFlag, err := signature.FormatSignatureAlgorithmFlag(v1.KnownSignatureAlgorithm(algorithmId)) + if err != nil { + continue + } + algorithms = append(algorithms, signatureFlag) + } + sort.Strings(algorithms) + return algorithms +} + // TODO(jason): Move this to an internal package. func GeneratePrivateKey() (*ecdsa.PrivateKey, error) { - return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + algorithmDetails, err := signature.GetAlgorithmDetails(v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256) + if err != nil { + return nil, err + } + key, err := GeneratePrivateKeyWithAlgo(algorithmDetails) + return key.(*ecdsa.PrivateKey), err +} + +func GeneratePrivateKeyWithAlgo(signingAlgorithm signature.AlgorithmDetails) (crypto.PrivateKey, error) { + switch signingAlgorithm.GetKeyType() { + case signature.ECDSA: + curve, err := signingAlgorithm.GetECDSACurve() + if err != nil { + return nil, err + } + return ecdsa.GenerateKey(*curve, rand.Reader) + case signature.ED25519: + _, priv, err := ed25519.GenerateKey(rand.Reader) + return priv, err + case signature.RSA: + rsaBits, err := signingAlgorithm.GetRSAKeySize() + if err != nil { + return nil, err + } + return rsa.GenerateKey(rand.Reader, int(rsaBits)) + default: + return nil, fmt.Errorf("unsupported signing algorithm: %s", signingAlgorithm) + } } // TODO(jason): Move this to the only place it's used in cmd/cosign/cli/importkeypair, and unexport it. @@ -182,13 +230,27 @@ func marshalKeyPair(ptype string, keypair Keys, pf PassFunc) (key *KeysBytes, er // TODO(jason): Move this to an internal package. func GenerateKeyPair(pf PassFunc) (*KeysBytes, error) { - priv, err := GeneratePrivateKey() + algorithmDetails, err := signature.GetAlgorithmDetails(v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256) + if err != nil { + return nil, err + } + + return GenerateKeyPairWithAlgo(pf, algorithmDetails) +} + +func GenerateKeyPairWithAlgo(pf PassFunc, signatureAlgorithm signature.AlgorithmDetails) (*KeysBytes, error) { + priv, err := GeneratePrivateKeyWithAlgo(signatureAlgorithm) if err != nil { return nil, err } + privSigner, ok := priv.(crypto.Signer) + if !ok { + return nil, fmt.Errorf("unsupported private key type: %T", priv) + } + // Emit SIGSTORE keys by default - return marshalKeyPair(SigstorePrivateKeyPemType, Keys{priv, priv.Public()}, pf) + return marshalKeyPair(SigstorePrivateKeyPemType, Keys{priv, privSigner.Public()}, pf) } // TODO(jason): Move this to an internal package.