Skip to content

Commit f7a5725

Browse files
authored
Document ImportKeyPair and LoadPrivateKey functions in pkg/cosign (#3776)
Document pkg/cosign key utility functions & supported key formats Signed-off-by: Dmitry S <[email protected]>
1 parent bdcbf44 commit f7a5725

File tree

2 files changed

+70
-10
lines changed

2 files changed

+70
-10
lines changed

pkg/cosign/keys.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ type Keys struct {
5858
public crypto.PublicKey
5959
}
6060

61-
// TODO(jason): Move this to an internal package.
6261
type KeysBytes struct {
6362
PrivateBytes []byte
6463
PublicBytes []byte
@@ -69,12 +68,17 @@ func (k *KeysBytes) Password() []byte {
6968
return k.password
7069
}
7170

72-
// TODO(jason): Move this to an internal package.
71+
// GeneratePrivateKey generates an ECDSA private key with the P-256 curve.
7372
func GeneratePrivateKey() (*ecdsa.PrivateKey, error) {
7473
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
7574
}
7675

77-
// TODO(jason): Move this to the only place it's used in cmd/cosign/cli/importkeypair, and unexport it.
76+
// ImportKeyPair imports a key pair from a file containing a PEM-encoded
77+
// private key encoded with a password provided by the 'pf' function.
78+
// The private key can be in one of the following formats:
79+
// - RSA private key (PKCS #1)
80+
// - ECDSA private key
81+
// - PKCS #8 private key (RSA, ECDSA or ED25519).
7882
func ImportKeyPair(keyPath string, pf PassFunc) (*KeysBytes, error) {
7983
kb, err := os.ReadFile(filepath.Clean(keyPath))
8084
if err != nil {
@@ -180,7 +184,6 @@ func marshalKeyPair(ptype string, keypair Keys, pf PassFunc) (key *KeysBytes, er
180184
}, nil
181185
}
182186

183-
// TODO(jason): Move this to an internal package.
184187
func GenerateKeyPair(pf PassFunc) (*KeysBytes, error) {
185188
priv, err := GeneratePrivateKey()
186189
if err != nil {
@@ -191,7 +194,7 @@ func GenerateKeyPair(pf PassFunc) (*KeysBytes, error) {
191194
return marshalKeyPair(SigstorePrivateKeyPemType, Keys{priv, priv.Public()}, pf)
192195
}
193196

194-
// TODO(jason): Move this to an internal package.
197+
// PemToECDSAKey marshals and returns the PEM-encoded ECDSA public key.
195198
func PemToECDSAKey(pemBytes []byte) (*ecdsa.PublicKey, error) {
196199
pub, err := cryptoutils.UnmarshalPEMToPublicKey(pemBytes)
197200
if err != nil {
@@ -204,7 +207,8 @@ func PemToECDSAKey(pemBytes []byte) (*ecdsa.PublicKey, error) {
204207
return ecdsaPub, nil
205208
}
206209

207-
// TODO(jason): Move this to pkg/signature, the only place it's used, and unimport it.
210+
// LoadPrivateKey loads a cosign PEM private key encrypted with the given passphrase,
211+
// and returns a SignerVerifier instance. The private key must be in the PKCS #8 format.
208212
func LoadPrivateKey(key []byte, pass []byte) (signature.SignerVerifier, error) {
209213
// Decrypt first
210214
p, _ := pem.Decode(key)
@@ -219,7 +223,6 @@ func LoadPrivateKey(key []byte, pass []byte) (signature.SignerVerifier, error) {
219223
if err != nil {
220224
return nil, fmt.Errorf("decrypt: %w", err)
221225
}
222-
223226
pk, err := x509.ParsePKCS8PrivateKey(x509Encoded)
224227
if err != nil {
225228
return nil, fmt.Errorf("parsing private key: %w", err)

pkg/cosign/keys_test.go

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,35 @@ pGAaLxggvtvuncMuTrG+cdmsR9SafSFKRS92NCxhOUonQ+NP6mLskIGzJZoQ5JvQ
5353
qGzRVIDGbNkrVHM0IsAtHRpC0rYrtZY+9OwiraGcsqUMLwwQdCA=
5454
-----END RSA PRIVATE KEY-----`
5555

56+
// RSA 2048 key encoded with PCKS#1
57+
const validrsapkcs1 = `-----BEGIN RSA PRIVATE KEY-----
58+
MIIEowIBAAKCAQEAqvVkqzBrMzl4TC5VsBgXnQiCo861QcB1TqdwgGzYkrNdF6fr
59+
UisPWgjMJixolmpwHv+088rsbiSlD9hc9DmzgCJPto7wvGeTILa9cNHCGKm12q7K
60+
TFnVUTH9z6D4E3F/IsI22Pg8+cSyeDn+LKxMadTohlcXJ8jqcH75KezoGngMp5OJ
61+
vqs93lkLep+UJMspV029z7PzF9uoT8gI02Adfq5Zkfu8VmIy8gkpYgTBCpNnD01u
62+
vo6HoAYG/mHqgPYivWBwi221GPjJWmCPB1rIJHlpAYUETA5jUY2UwP1oQx54ybcj
63+
eNjMRP5J0cGyOI8MT0j9ul7/DJde3Ds5A7BA9QIDAQABAoIBAQCJ3Q5rhsZMLsI2
64+
HP943FTei+heFOnStlNjNF/jEOOtmfsugnmgb50XrBSFjDZjZj44oVjZaQE06VQ6
65+
7O44/PcmE4VY4Ph91sCtFvC6NE1j+ifuzBnTbHY73iah81tawqIV86yrV7REbzzE
66+
+29fsyqEBe/ltgG0Ua/NPHfOOYALJwZVx8ozkz7xOyU23kNxSzp3T0FBnYYIuzrI
67+
a4h7FVxGLbIJQ3xWBU5xkd4m7EqgFYkWCfSXAVoLT2z7eJSYAmITuiQXl8uDz1XY
68+
lWKgOwkRJrMVVD8hDME7Hoc/RlKmYX64IZ3lv70NuyKDPTuhmoIQRJ49mVaqdPtH
69+
v0Z9L0tBAoGBAMPFcJFaR+VdmsZ2DXQlsPQNAB064SYbIXx/pxNVoDYkHyMfZsf3
70+
vjf4gMKNsHTM4u812UpsE5762OqdVKmWXQc60mkuEk7N55iXuBJiJxSpuj6IbiLw
71+
ogV+B40UC9luOISQpDYdY1Km1ho4HRngNkXMlJ48tFuwIP3lwwz3FtFZAoGBAN+N
72+
wVssBvNhHzGfcUMxxCwJKfHCx1ANWuTe+AsDtpZRTExMcX1PH1euxUV9aII9Klg7
73+
A7FN1It78pDrQBNQJoeMON+5N53//geY6stDfhPkOoT8Zqg2VEz4WRihUgAUHESk
74+
pUVYSvEXG7J7AG5iGgn0B3P9PMvvReIHnTeQ1rz9AoGAWAR31NHrSyMniBzhdZvQ
75+
kBkcOQgU3AYMqyXVXyr7KfxZh3gBxNwMyKtQcKg1cn3/dZ8XP4+RzsNnLSxpOQni
76+
b3Kx0RomnwmSG5fy6Uj52x9oHd9G7SyVG7UK/hHKNgqJHIjPW4kg87MQxZ7+7nhQ
77+
zlbpZq9SQ3rPind3l2er+ZkCgYASFs9ZiEN7uBUlF8i7bjB4e7lYJbGpCZucP2qE
78+
waUpnqR03A6m3BsmJi8yQ0aMm1Rs1UGkPC8BpmLnVRHXPjoP58nGWJ9meotcpAQD
79+
tI9kHqiZkC7iV5sUq1fSRWN0PCxZZZU1+kH+JieIlqlfRTLkMUnVGd2shsz50DHp
80+
iB/IJQKBgAO3kRRVszif2jdo7gzDsiSQ+fSyD6yEE9eP+uNwLZw9bQhyW5wlXF+t
81+
dR5olNrc0bP542MHL5vigRnezq9hT1hbLkQg/MA2k5FrMHIZshfWITnI5B5I2sw6
82+
wu/XEVtNr8RincoHXjov4DiqgbLPWubM7FHLN5CW6nRLXhGkb4+7
83+
-----END RSA PRIVATE KEY-----`
84+
5685
// RSA 2048 key encoded with PKCS#8
5786
const validrsapkcs8 = `-----BEGIN PRIVATE KEY-----
5887
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwDtRl4McMhk4Q
@@ -257,7 +286,7 @@ const ed25519key = `-----BEGIN PRIVATE KEY-----
257286
MC4CAQAwBQYDK2VwBCIEIALEbo1EFnWFqBK/wC+hhypG/8hXEerwdNetAoFoFVdv
258287
-----END PRIVATE KEY-----`
259288

260-
// COSIGN labeled key
289+
// COSIGN labeled RSA key
261290
const pemcosignkey = `-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
262291
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
263292
OCwicCI6MX0sInNhbHQiOiJ4WWdoc09JTUxUWGNOT0RsclNIOUNKc1FlOVFnZmN1
@@ -270,6 +299,19 @@ Y1pmbEJheXZMV3pXblo4d2NDZ2ZpT1o1VXlRTEFJMHh0dnR6dEh3cTdDV1Vhd3V4
270299
RlhlNDZzck9TUE9SNHN6bytabWErUGovSFE9PSJ9
271300
-----END ENCRYPTED COSIGN PRIVATE KEY-----`
272301

302+
// COSIGN labeled EC key
303+
const pemcosigneckey = `-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
304+
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjo2NTUzNiwiciI6
305+
OCwicCI6MX0sInNhbHQiOiJHK3F5WTYrNzhNS0JzMXNGTGs1ajYwcS9kS3Z1czBW
306+
VkhlSHZybC9POTF3PSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
307+
Iiwibm9uY2UiOiJRc2JGdG13WDRDK2ttV3ZCcVRaMEFGOUFYdk1jRmg1SCJ9LCJj
308+
aXBoZXJ0ZXh0IjoiREM5T28zeldiYVQzSXYwdFVnWEdycjUxYW1samwwNlQ5MTNP
309+
VkxPbWpuMWhnK2o2WXRUbWg3SGhZSlY1N2J5eGE0Q281bE9YYmRqbTJ3aklubEd1
310+
Um5aZCt5OExnekpSNzFSeEhKVzgrWmRlcFJmYWJMTjdHbDgrSFZEcERVQ3NxQnRh
311+
VngyblpGbFEwWUl1anZwbFphblNGaUVvdERLVGkxZ3VhUXIwUHNzYU01NXZxbTRY
312+
WS9rPSJ9
313+
-----END ENCRYPTED COSIGN PRIVATE KEY-----`
314+
273315
// SIGSTORE labeled key
274316
const pemsigstorekey = `-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
275317
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
@@ -317,16 +359,22 @@ func TestLoadECDSAPrivateKey(t *testing.T) {
317359
}
318360

319361
func TestReadingPrivatePemTypes(t *testing.T) {
362+
pemECErrMsg := "parsing private key: x509: failed to parse private key (use ParseECPrivateKey instead for this key format)"
320363
testCases := []struct {
321364
pemType string
322365
pemData []byte
323366
expected error
324367
}{
325368
{
326-
pemType: "COSIGN PEM Type",
369+
pemType: "COSIGN PEM RSA Type",
327370
pemData: []byte(pemcosignkey),
328371
expected: nil,
329372
},
373+
{
374+
pemType: "COSIGN PEM EC Type",
375+
pemData: []byte(pemcosigneckey),
376+
expected: errors.New(pemECErrMsg),
377+
},
330378
{
331379
pemType: "SISTORE PEM Type",
332380
pemData: []byte(pemsigstorekey),
@@ -337,7 +385,11 @@ func TestReadingPrivatePemTypes(t *testing.T) {
337385
for _, tc := range testCases {
338386
t.Run(tc.pemType, func(t *testing.T) {
339387
_, err := LoadPrivateKey(tc.pemData, []byte("hello"))
340-
require.Equal(t, tc.expected, err)
388+
if tc.expected == nil {
389+
require.NoError(t, err)
390+
} else {
391+
require.ErrorContains(t, err, tc.expected.Error())
392+
}
341393
})
342394
}
343395
}
@@ -363,6 +415,11 @@ func TestImportPrivateKey(t *testing.T) {
363415
pemData: validrsa,
364416
expected: nil,
365417
},
418+
{
419+
fileName: "validrsapkcs1.key",
420+
pemData: validrsapkcs1,
421+
expected: nil,
422+
},
366423
{
367424
fileName: "validrsapkcs8.key",
368425
pemData: validrsapkcs8,

0 commit comments

Comments
 (0)