From d912415fe8d8ef7cbec9ccbc401865abf5760de3 Mon Sep 17 00:00:00 2001 From: Ivana Atanasova Date: Wed, 22 Feb 2023 20:44:34 +0200 Subject: [PATCH] Default generated PEM labels to SIGSTORE 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 --- README.md | 6 ++-- pkg/cosign/keys.go | 19 +++++++++---- pkg/cosign/keys_test.go | 62 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7a04d40b7ffe..21e7662f2c5c 100644 --- a/README.md +++ b/README.md @@ -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`. diff --git a/pkg/cosign/keys.go b/pkg/cosign/keys.go index 9a51e0d8c07b..1fb5899bd40c 100644 --- a/pkg/cosign/keys.go +++ b/pkg/cosign/keys.go @@ -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 @@ -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) @@ -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 @@ -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. @@ -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) } diff --git a/pkg/cosign/keys_test.go b/pkg/cosign/keys_test.go index e8586cbf0b3d..a72cbf8a447b 100644 --- a/pkg/cosign/keys_test.go +++ b/pkg/cosign/keys_test.go @@ -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 @@ -290,6 +316,42 @@ 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