Skip to content

Commit

Permalink
Move LoadEcdsa... into pkg/cosign/keys.go (#667)
Browse files Browse the repository at this point in the history
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 <mattomata@gmail.com>
  • Loading branch information
mattmoor committed Sep 14, 2021
1 parent c37c20e commit 152eefb
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 62 deletions.
35 changes: 2 additions & 33 deletions cmd/cosign/cli/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ package cli
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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"])
}
}

Expand Down Expand Up @@ -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)
}
28 changes: 0 additions & 28 deletions cmd/cosign/cli/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package cli

import (
"context"
"crypto/rand"
"io/ioutil"
"testing"

Expand Down Expand Up @@ -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!")
}
}
28 changes: 28 additions & 0 deletions pkg/cosign/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package cosign

import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
Expand All @@ -28,6 +29,7 @@ import (
"github.com/theupdateframework/go-tuf/encrypted"

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
)

const (
Expand Down Expand Up @@ -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)
}
54 changes: 54 additions & 0 deletions pkg/cosign/keys_test.go
Original file line number Diff line number Diff line change
@@ -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!")
}
}
2 changes: 1 addition & 1 deletion test/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down

0 comments on commit 152eefb

Please sign in to comment.