From d27f70c8edc3db101721d82f17e69ee116cfae87 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Tue, 14 Sep 2021 12:48:40 -0700 Subject: [PATCH] Move `LoadEcdsa...` into `pkg/cosign/keys.go` Chains is consuming this public function, but because `./cmd/cosign/cli` pulls in `glog` we hit the `-log_dir` problem. With this change it can drop it's dependency on `cli`. Signed-off-by: Matt Moore --- cmd/cosign/cli/keys.go | 35 ++---------------------- cmd/cosign/cli/keys_test.go | 28 ------------------- pkg/cosign/keys.go | 28 +++++++++++++++++++ pkg/cosign/keys_test.go | 54 +++++++++++++++++++++++++++++++++++++ test/e2e_test.go | 2 +- 5 files changed, 85 insertions(+), 62 deletions(-) create mode 100644 pkg/cosign/keys_test.go diff --git a/cmd/cosign/cli/keys.go b/cmd/cosign/cli/keys.go index c555e8dbbeb..fb9786c96e5 100644 --- a/cmd/cosign/cli/keys.go +++ b/cmd/cosign/cli/keys.go @@ -17,10 +17,6 @@ package cli import ( "context" "crypto" - "crypto/ecdsa" - "crypto/x509" - "encoding/pem" - "fmt" "io/ioutil" "path/filepath" "strings" @@ -31,7 +27,6 @@ import ( "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" "github.com/sigstore/sigstore/pkg/signature/kms" - "github.com/theupdateframework/go-tuf/encrypted" ) func loadKey(keyPath string, pf cosign.PassFunc) (*signature.ECDSASignerVerifier, error) { @@ -43,7 +38,7 @@ func loadKey(keyPath string, pf cosign.PassFunc) (*signature.ECDSASignerVerifier if err != nil { return nil, err } - return LoadECDSAPrivateKey(kb, pass) + return cosign.LoadECDSAPrivateKey(kb, pass) } func loadPublicKey(raw []byte) (signature.Verifier, error) { @@ -73,7 +68,7 @@ func signerVerifierFromKeyRef(ctx context.Context, keyRef string, pf cosign.Pass } if len(s.Data) > 0 { - return LoadECDSAPrivateKey(s.Data["cosign.key"], s.Data["cosign.password"]) + return cosign.LoadECDSAPrivateKey(s.Data["cosign.key"], s.Data["cosign.password"]) } } @@ -102,29 +97,3 @@ func publicKeyPem(key signature.PublicKeyProvider, pkOpts ...signature.PublicKey } return cryptoutils.MarshalPublicKeyToPEM(pub) } - -func LoadECDSAPrivateKey(key []byte, pass []byte) (*signature.ECDSASignerVerifier, error) { - // Decrypt first - p, _ := pem.Decode(key) - if p == nil { - return nil, errors.New("invalid pem block") - } - if p.Type != cosign.PrivakeKeyPemType { - return nil, fmt.Errorf("unsupported pem type: %s", p.Type) - } - - x509Encoded, err := encrypted.Decrypt(p.Bytes, pass) - if err != nil { - return nil, errors.Wrap(err, "decrypt") - } - - pk, err := x509.ParsePKCS8PrivateKey(x509Encoded) - if err != nil { - return nil, errors.Wrap(err, "parsing private key") - } - epk, ok := pk.(*ecdsa.PrivateKey) - if !ok { - return nil, fmt.Errorf("invalid private key") - } - return signature.LoadECDSASignerVerifier(epk, crypto.SHA256) -} diff --git a/cmd/cosign/cli/keys_test.go b/cmd/cosign/cli/keys_test.go index b3257afb4a2..fb23b3bff9a 100644 --- a/cmd/cosign/cli/keys_test.go +++ b/cmd/cosign/cli/keys_test.go @@ -16,7 +16,6 @@ package cli import ( "context" - "crypto/rand" "io/ioutil" "testing" @@ -108,30 +107,3 @@ func TestPublicKeyFromFileRef(t *testing.T) { } } - -func TestLoadECDSAPrivateKey(t *testing.T) { - // Generate a valid keypair - keys, err := cosign.GenerateKeyPair(pass("hello")) - if err != nil { - t.Fatal(err) - } - - // Load the private key with the right password - if _, err := LoadECDSAPrivateKey(keys.PrivateBytes, []byte("hello")); err != nil { - t.Errorf("unexpected error decrypting key: %s", err) - } - - // Try it with the wrong one - if _, err := LoadECDSAPrivateKey(keys.PrivateBytes, []byte("wrong")); err == nil { - t.Error("expected error decrypting key!") - } - - // Try to decrypt garbage - buf := [100]byte{} - if _, err := rand.Read(buf[:]); err != nil { - t.Fatal(err) - } - if _, err := LoadECDSAPrivateKey(buf[:], []byte("wrong")); err == nil { - t.Error("expected error decrypting key!") - } -} diff --git a/pkg/cosign/keys.go b/pkg/cosign/keys.go index 8ad5b0550d1..2485b607aae 100644 --- a/pkg/cosign/keys.go +++ b/pkg/cosign/keys.go @@ -16,6 +16,7 @@ package cosign import ( + "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" @@ -28,6 +29,7 @@ import ( "github.com/theupdateframework/go-tuf/encrypted" "github.com/sigstore/sigstore/pkg/cryptoutils" + "github.com/sigstore/sigstore/pkg/signature" ) const ( @@ -104,3 +106,29 @@ func PemToECDSAKey(pemBytes []byte) (*ecdsa.PublicKey, error) { } return ecdsaPub, nil } + +func LoadECDSAPrivateKey(key []byte, pass []byte) (*signature.ECDSASignerVerifier, error) { + // Decrypt first + p, _ := pem.Decode(key) + if p == nil { + return nil, errors.New("invalid pem block") + } + if p.Type != PrivakeKeyPemType { + return nil, fmt.Errorf("unsupported pem type: %s", p.Type) + } + + x509Encoded, err := encrypted.Decrypt(p.Bytes, pass) + if err != nil { + return nil, errors.Wrap(err, "decrypt") + } + + pk, err := x509.ParsePKCS8PrivateKey(x509Encoded) + if err != nil { + return nil, errors.Wrap(err, "parsing private key") + } + epk, ok := pk.(*ecdsa.PrivateKey) + if !ok { + return nil, fmt.Errorf("invalid private key") + } + return signature.LoadECDSASignerVerifier(epk, crypto.SHA256) +} diff --git a/pkg/cosign/keys_test.go b/pkg/cosign/keys_test.go new file mode 100644 index 00000000000..e85d5e61730 --- /dev/null +++ b/pkg/cosign/keys_test.go @@ -0,0 +1,54 @@ +// +// Copyright 2021 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cosign + +import ( + "crypto/rand" + "testing" +) + +func pass(s string) PassFunc { + return func(_ bool) ([]byte, error) { + return []byte(s), nil + } +} + +func TestLoadECDSAPrivateKey(t *testing.T) { + // Generate a valid keypair + keys, err := GenerateKeyPair(pass("hello")) + if err != nil { + t.Fatal(err) + } + + // Load the private key with the right password + if _, err := LoadECDSAPrivateKey(keys.PrivateBytes, []byte("hello")); err != nil { + t.Errorf("unexpected error decrypting key: %s", err) + } + + // Try it with the wrong one + if _, err := LoadECDSAPrivateKey(keys.PrivateBytes, []byte("wrong")); err == nil { + t.Error("expected error decrypting key!") + } + + // Try to decrypt garbage + buf := [100]byte{} + if _, err := rand.Read(buf[:]); err != nil { + t.Fatal(err) + } + if _, err := LoadECDSAPrivateKey(buf[:], []byte("wrong")); err == nil { + t.Error("expected error decrypting key!") + } +} diff --git a/test/e2e_test.go b/test/e2e_test.go index 7276d48c203..7bb4f7f4d60 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -275,7 +275,7 @@ func TestGenerateKeyPairEnvVar(t *testing.T) { if err != nil { t.Fatal(err) } - if _, err := cli.LoadECDSAPrivateKey(keys.PrivateBytes, []byte("foo")); err != nil { + if _, err := cosign.LoadECDSAPrivateKey(keys.PrivateBytes, []byte("foo")); err != nil { t.Fatal(err) } }