Skip to content

Commit

Permalink
Add --signing-algorithm flag
Browse files Browse the repository at this point in the history
  • Loading branch information
ret2libc committed Jan 23, 2024
1 parent 5bc12dd commit a11042f
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 22 deletions.
11 changes: 9 additions & 2 deletions cmd/cosign/cli/generate/generate_key_pair.go
Expand Up @@ -28,12 +28,14 @@ import (
"github.com/sigstore/cosign/v2/pkg/cosign/git"
"github.com/sigstore/cosign/v2/pkg/cosign/git/github"
"github.com/sigstore/cosign/v2/pkg/cosign/git/gitlab"
v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"

icos "github.com/sigstore/cosign/v2/internal/pkg/cosign"
"github.com/sigstore/cosign/v2/internal/ui"
"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"
)

Expand All @@ -43,7 +45,7 @@ var (
)

// nolint
func GenerateKeyPairCmd(ctx context.Context, kmsVal string, outputKeyPrefixVal string, args []string) error {
func GenerateKeyPairCmd(ctx context.Context, kmsVal string, outputKeyPrefixVal string, signatureAlgorithm v1.KnownSignatureAlgorithm, args []string) error {
privateKeyFileName := outputKeyPrefixVal + ".key"
publicKeyFileName := outputKeyPrefixVal + ".pub"

Expand Down Expand Up @@ -86,7 +88,12 @@ func GenerateKeyPairCmd(ctx context.Context, kmsVal string, outputKeyPrefixVal s
return fmt.Errorf("undefined provider: %s", provider)
}

keys, err := cosign.GenerateKeyPair(GetPass)
algorithmDetails, err := signature.GetAlgorithmDetails(signatureAlgorithm)
if err != nil {
return err
}

keys, err := cosign.GenerateKeyPairWithAlgo(GetPass, algorithmDetails)
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/cosign/cli/generate/generate_key_pair_test.go
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/google/go-cmp/cmp"
icos "github.com/sigstore/cosign/v2/internal/pkg/cosign"
v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
)

func TestReadPasswordFn_env(t *testing.T) {
Expand Down Expand Up @@ -57,7 +58,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", v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256, nil)

checkIfFileExistsThenDelete(privateKeyName, t)
checkIfFileExistsThenDelete(publicKeyName, t)
Expand Down
5 changes: 4 additions & 1 deletion cmd/cosign/cli/generate_key_pair.go
Expand Up @@ -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
Expand Down Expand Up @@ -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.Value(), args)
},
}

Expand Down
23 changes: 21 additions & 2 deletions cmd/cosign/cli/options/generate_key_pair.go
Expand Up @@ -16,14 +16,21 @@
package options

import (
"fmt"
"sort"
"strings"

"github.com/sigstore/cosign/v2/pkg/cosign"
"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 cosign.SupportedAlgorithmOption
}

var _ Interface = (*GenerateKeyPairOptions)(nil)
Expand All @@ -34,4 +41,16 @@ 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 := []string{}
for _, keyAlgorithm := range cosign.ClientAlgorithmsRegistry.ListPermittedAlgorithms() {
keyFlag, err := signature.FormatSignatureAlgorithmFlag(keyAlgorithm)
if err != nil {
panic(err)
}
keyAlgorithmTypes = append(keyAlgorithmTypes, *keyFlag)
}
sort.Strings(keyAlgorithmTypes)
keyAlgorithmHelp := fmt.Sprintf("signing algorithm to use for signing/hashing (allowed %s)", strings.Join(keyAlgorithmTypes, ", "))
cmd.Flags().Var(&o.SigningAlgorithm, "signing-algorithm", keyAlgorithmHelp)
}
6 changes: 5 additions & 1 deletion cmd/cosign/cli/options/key.go
Expand Up @@ -15,12 +15,16 @@

package options

import "github.com/sigstore/cosign/v2/pkg/cosign"
import (
"github.com/sigstore/cosign/v2/pkg/cosign"
v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
)

type KeyOpts struct {
Sk bool
Slot string
KeyRef string
SigningAlgorithm v1.KnownSignatureAlgorithm
FulcioURL string
RekorURL string
IDToken string
Expand Down
19 changes: 19 additions & 0 deletions cmd/cosign/cli/options/sign.go
Expand Up @@ -16,12 +16,19 @@
package options

import (
"fmt"
"sort"
"strings"

"github.com/sigstore/cosign/v2/pkg/cosign"
"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 cosign.SupportedAlgorithmOption
Cert string
CertChain string
Upload bool
Expand Down Expand Up @@ -67,6 +74,18 @@ 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 := []string{}
for _, keyAlgorithm := range cosign.ClientAlgorithmsRegistry.ListPermittedAlgorithms() {
keyFlag, err := signature.FormatSignatureAlgorithmFlag(keyAlgorithm)
if err != nil {
panic(err)
}
keyAlgorithmTypes = append(keyAlgorithmTypes, *keyFlag)
}
sort.Strings(keyAlgorithmTypes)
keyAlgorithmHelp := fmt.Sprintf("signing algorithm to use for signing/hashing (allowed %s)", strings.Join(keyAlgorithmTypes, ", "))
cmd.Flags().Var(&o.SigningAlgorithm, "signing-algorithm", 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"})
Expand Down
19 changes: 19 additions & 0 deletions cmd/cosign/cli/options/signblob.go
Expand Up @@ -16,13 +16,20 @@
package options

import (
"fmt"
"sort"
"strings"

"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/spf13/cobra"
)

// SignBlobOptions is the top level wrapper for the sign-blob command.
// The new output-certificate flag is only in use when COSIGN_EXPERIMENTAL is enabled
type SignBlobOptions struct {
Key string
SigningAlgorithm cosign.SupportedAlgorithmOption
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.
Expand Down Expand Up @@ -57,6 +64,18 @@ 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 := []string{}
for _, keyAlgorithm := range cosign.ClientAlgorithmsRegistry.ListPermittedAlgorithms() {
keyFlag, err := signature.FormatSignatureAlgorithmFlag(keyAlgorithm)
if err != nil {
panic(err)
}
keyAlgorithmTypes = append(keyAlgorithmTypes, *keyFlag)
}
sort.Strings(keyAlgorithmTypes)
keyAlgorithmHelp := fmt.Sprintf("signing algorithm to use for signing/hashing (allowed %s)", strings.Join(keyAlgorithmTypes, ", "))
cmd.Flags().Var(&o.SigningAlgorithm, "signing-algorithm", keyAlgorithmHelp)

cmd.Flags().BoolVar(&o.Base64Output, "b64", true,
"whether to base64 encode the output")

Expand Down
1 change: 1 addition & 0 deletions cmd/cosign/cli/sign.go
Expand Up @@ -102,6 +102,7 @@ race conditions or (worse) malicious tampering.
}
ko := options.KeyOpts{
KeyRef: o.Key,
SigningAlgorithm: o.SigningAlgorithm.Value(),
PassFunc: generate.GetPass,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Expand Down
29 changes: 24 additions & 5 deletions cmd/cosign/cli/sign/sign.go
Expand Up @@ -18,7 +18,6 @@ package sign
import (
"bytes"
"context"
"crypto"
"crypto/x509"
"encoding/base64"
"encoding/json"
Expand All @@ -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"
Expand Down Expand Up @@ -138,8 +138,22 @@ func SignCmd(ro *options.RootOptions, ko options.KeyOpts, signOpts options.SignO
ctx, cancel := context.WithTimeout(context.Background(), ro.Timeout)
defer cancel()

// Always default to ECDSA_SHA2_256_NISTP256 for now
if ko.SigningAlgorithm == pb_go_v1.KnownSignatureAlgorithm_KNOWN_SIGNATURE_ALGORITHM_UNSPECIFIED {
ko.SigningAlgorithm = pb_go_v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256
}

if !cosign.ClientAlgorithmsRegistry.HasAlgorithmDetails(ko.SigningAlgorithm) {
return fmt.Errorf("unsupported signing algorithm: %s", ko.SigningAlgorithm.String())
}

algorithmDetails, err := cosign.ClientAlgorithmsRegistry.GetAlgorithmDetails(ko.SigningAlgorithm)
if err != nil {
return err
}
hashAlgorithm := algorithmDetails.GetHashType()
svOptions := []signature.SignerVerifierOption{
signature.WithHash(crypto.SHA256),
signature.WithHash(hashAlgorithm),
signature.WithED25519ph(),
}

Expand Down Expand Up @@ -531,8 +545,13 @@ func signerFromKeyRef(ctx context.Context, certPath, certChainPath, keyRef strin
return certSigner, nil
}

func signerFromNewKey(svOpts ...signature.SignerVerifierOption) (*SignerVerifier, error) {
privKey, err := cosign.GeneratePrivateKey()
func signerFromNewKey(signingAlgorithm pb_go_v1.KnownSignatureAlgorithm, svOpts ...signature.SignerVerifierOption) (*SignerVerifier, error) {
algorithmDetails, err := cosign.ClientAlgorithmsRegistry.GetAlgorithmDetails(signingAlgorithm)
if err != nil {
return nil, err
}

privKey, err := cosign.GeneratePrivateKeyWithAlgo(algorithmDetails)
if err != nil {
return nil, fmt.Errorf("generating cert: %w", err)
}
Expand Down Expand Up @@ -581,7 +600,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(ko.SigningAlgorithm, svOpts...)
}
if err != nil {
return nil, err
Expand Down
22 changes: 16 additions & 6 deletions cmd/cosign/cli/sign/sign_blob.go
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/sigstore/cosign/v2/internal/ui"
"github.com/sigstore/cosign/v2/pkg/cosign"
cbundle "github.com/sigstore/cosign/v2/pkg/cosign/bundle"
v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
signatureoptions "github.com/sigstore/sigstore/pkg/signature/options"
Expand Down Expand Up @@ -66,21 +67,30 @@ func SignBlobCmd(ro *options.RootOptions, ko options.KeyOpts, payloadPath string
ctx, cancel := context.WithTimeout(context.Background(), ro.Timeout)
defer cancel()

svOptions := []signature.SignerVerifierOption{
signature.WithHash(crypto.SHA256),
signature.WithED25519ph(),
// Always default to ECDSA_SHA2_256_NISTP256 for now
if ko.SigningAlgorithm == v1.KnownSignatureAlgorithm_KNOWN_SIGNATURE_ALGORITHM_UNSPECIFIED {
ko.SigningAlgorithm = v1.KnownSignatureAlgorithm_ECDSA_SHA2_256_NISTP256
}

sv, err := signerFromKeyOptsWithSVOpts(ctx, "", "", ko, svOptions...)
if !cosign.ClientAlgorithmsRegistry.HasAlgorithmDetails(ko.SigningAlgorithm) {
return nil, fmt.Errorf("unsupported signing algorithm: %s", ko.SigningAlgorithm.String())
}

algorithmDetails, err := cosign.ClientAlgorithmsRegistry.GetAlgorithmDetails(ko.SigningAlgorithm)
if err != nil {
return nil, err
}
defer sv.Close()
hashAlgorithm := algorithmDetails.GetHashType()
svOptions := []signature.SignerVerifierOption{
signature.WithHash(hashAlgorithm),
signature.WithED25519ph(),
}

hashAlgorithm, err := getHashAlgorithmFromSignerVerifier(sv)
sv, err := signerFromKeyOptsWithSVOpts(ctx, "", "", ko, svOptions...)
if err != nil {
return nil, err
}
defer sv.Close()

if payloadPath == "-" {
payload = internal.NewHashReader(os.Stdin, hashAlgorithm)
Expand Down
1 change: 1 addition & 0 deletions cmd/cosign/cli/signblob.go
Expand Up @@ -70,6 +70,7 @@ func SignBlob() *cobra.Command {
}
ko := options.KeyOpts{
KeyRef: o.Key,
SigningAlgorithm: o.SigningAlgorithm.Value(),
PassFunc: generate.GetPass,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Expand Down

0 comments on commit a11042f

Please sign in to comment.