Skip to content

Commit

Permalink
Default generated PEM labels to SIGSTORE (sigstore#2735)
Browse files Browse the repository at this point in the history
This change adds SIGSTORE PEM label and accepts both the old
COSIGN label and the new one. Newly generated keys are now created
with SIGSTORE label

Signed-off-by: Ivana Atanasova <iyovcheva@iyovcheva7MD6R.vmware.com>
Co-authored-by: Ivana Atanasova <iyovcheva@iyovcheva7MD6R.vmware.com>
  • Loading branch information
2 people authored and dmitris committed Mar 24, 2023
1 parent 479486a commit faaefbe
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 9 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,12 +459,12 @@ Note: different registries might expect different formats for the "repository."
Generated private keys are stored in PEM format.
The keys encrypted under a password using scrypt as a KDF and nacl/secretbox for encryption.
They have a PEM header of `ENCRYPTED COSIGN PRIVATE KEY`:
They have a PEM header of `ENCRYPTED SIGSTORE PRIVATE KEY`:
```shell
-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
...
-----END ENCRYPTED COSIGN PRIVATE KEY-----
-----END ENCRYPTED SIGSTORE PRIVATE KEY-----
```
Public keys are stored on disk in PEM-encoded standard PKIX format with a header of `PUBLIC KEY`.
Expand Down
19 changes: 13 additions & 6 deletions pkg/cosign/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ import (
)

const (
CosignPrivateKeyPemType = "ENCRYPTED COSIGN PRIVATE KEY"
CosignPrivateKeyPemType = "ENCRYPTED COSIGN PRIVATE KEY"
SigstorePrivateKeyPemType = "ENCRYPTED SIGSTORE PRIVATE KEY"
// PEM-encoded PKCS #1 RSA private key
RSAPrivateKeyPemType = "RSA PRIVATE KEY"
// PEM-encoded ECDSA private key
Expand Down Expand Up @@ -134,10 +135,10 @@ func ImportKeyPair(keyPath string, pf PassFunc) (*KeysBytes, error) {
default:
return nil, fmt.Errorf("unsupported private key")
}
return marshalKeyPair(Keys{pk, pk.Public()}, pf)
return marshalKeyPair(p.Type, Keys{pk, pk.Public()}, pf)
}

func marshalKeyPair(keypair Keys, pf PassFunc) (key *KeysBytes, err error) {
func marshalKeyPair(ptype string, keypair Keys, pf PassFunc) (key *KeysBytes, err error) {
x509Encoded, err := x509.MarshalPKCS8PrivateKey(keypair.private)
if err != nil {
return nil, fmt.Errorf("x509 encoding private key: %w", err)
Expand All @@ -156,10 +157,15 @@ func marshalKeyPair(keypair Keys, pf PassFunc) (key *KeysBytes, err error) {
return nil, err
}

// default to SIGSTORE, but keep support of COSIGN
if ptype != CosignPrivateKeyPemType {
ptype = SigstorePrivateKeyPemType
}

// store in PEM format
privBytes := pem.EncodeToMemory(&pem.Block{
Bytes: encBytes,
Type: CosignPrivateKeyPemType,
Type: ptype,
})

// Now do the public key
Expand All @@ -182,7 +188,8 @@ func GenerateKeyPair(pf PassFunc) (*KeysBytes, error) {
return nil, err
}

return marshalKeyPair(Keys{priv, priv.Public()}, pf)
// Emit SIGSTORE keys by default
return marshalKeyPair(SigstorePrivateKeyPemType, Keys{priv, priv.Public()}, pf)
}

// TODO(jason): Move this to an internal package.
Expand All @@ -205,7 +212,7 @@ func LoadPrivateKey(key []byte, pass []byte) (signature.SignerVerifier, error) {
if p == nil {
return nil, errors.New("invalid pem block")
}
if p.Type != CosignPrivateKeyPemType {
if p.Type != CosignPrivateKeyPemType && p.Type != SigstorePrivateKeyPemType {
return nil, fmt.Errorf("unsupported pem type: %s", p.Type)
}

Expand Down
61 changes: 61 additions & 0 deletions pkg/cosign/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,32 @@ const ed25519key = `-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIALEbo1EFnWFqBK/wC+hhypG/8hXEerwdNetAoFoFVdv
-----END PRIVATE KEY-----`

// COSIGN labeled key
const pemcosignkey = `-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
OCwicCI6MX0sInNhbHQiOiJ4WWdoc09JTUxUWGNOT0RsclNIOUNKc1FlOVFnZmN1
cmUrMXlLdHh1TlkwPSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
Iiwibm9uY2UiOiI0cS9PSlVmaXJkSUkrUjZ0ajZBMmcyQ0JqL25xdFNicCJ9LCJj
aXBoZXJ0ZXh0IjoiKzB4Q3NzcFN0WStBczdKanJpOWtsbHBWd2JhcUI4ZWJNdWto
eS9aVE1MSXRsL3B1YS9jWVJvbytLRGxMWWdmOW1kSjk4K1FnQW9oTktoYnJPMTcw
MHdBY1JTMjFDOE4zQUNJRUVZaWpOMllBNnMraGJSbkhjUnd4eGhDMDFtb2FvL0dO
Y1pmbEJheXZMV3pXblo4d2NDZ2ZpT1o1VXlRTEFJMHh0dnR6dEh3cTdDV1Vhd3V4
RlhlNDZzck9TUE9SNHN6bytabWErUGovSFE9PSJ9
-----END ENCRYPTED COSIGN PRIVATE KEY-----`

// SIGSTORE labeled key
const pemsigstorekey = `-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
OCwicCI6MX0sInNhbHQiOiI3T3VGd2VsbWZZNXVId2NoaURSc210anNwZ2ZlZjFG
Mk5lOGFDTjVLYVpZPSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
Iiwibm9uY2UiOiJQNHk4OGhCb3ZTa09MbXN0bFVBaGJwdDJ0K2xTNUxQSCJ9LCJj
aXBoZXJ0ZXh0IjoiMnB1QzdyZldJOWh3bnJlQ2s4aUZDRlVwQlRrSzRJNlIvbFBF
cnBDekpXUGpJWXl4eGVIL1A2VW52cFJHdVhla1NNb3JMdGhLamdoQ1JlNy82NDVH
QWtoVm1LRC92eEF0S2EvbE1abENSQ3FlekJGUFd1dzNpeFRtZ2xhb2J1ZFVSbUVs
bmNGOGlZbzBTMVl6Y1ZOMVFwY2J2c0dNcUlYRzVlbmdteGp5dCtBcXlyZTF0Q0Y0
V01tU1BlaEljNlBqd2h1Q2xHaVpJUWRvTGc9PSJ9
-----END ENCRYPTED SIGSTORE PRIVATE KEY-----`

func pass(s string) PassFunc {
return func(_ bool) ([]byte, error) {
return []byte(s), nil
Expand Down Expand Up @@ -290,6 +316,41 @@ func TestLoadECDSAPrivateKey(t *testing.T) {
}
}

func TestReadingPrivatePemTypes(t *testing.T) {
testCases := []struct {
pemType string
pemData []byte
expected error
}{
{
pemType: "COSIGN PEM Type",
pemData: []byte(pemcosignkey),
expected: nil,
},
{
pemType: "SISTORE PEM Type",
pemData: []byte(pemsigstorekey),
expected: nil,
},
}

for _, tc := range testCases {
t.Run(tc.pemType, func(t *testing.T) {
_, err := LoadPrivateKey(tc.pemData, []byte("hello"))
require.Equal(t, tc.expected, err)
})
}
}

func TestWritingPrivatePemTypes(t *testing.T) {
keys, err := GenerateKeyPair(pass("hello"))
if err != nil {
t.Fatal(err)
}

require.Contains(t, string(keys.PrivateBytes), SigstorePrivateKeyPemType)
}

func TestImportPrivateKey(t *testing.T) {
testCases := []struct {
fileName string
Expand Down

0 comments on commit faaefbe

Please sign in to comment.