diff --git a/tuf/data/types.go b/tuf/data/types.go index 0f4198f95..778e0f1a0 100644 --- a/tuf/data/types.go +++ b/tuf/data/types.go @@ -38,13 +38,6 @@ func (r RoleName) Parent() RoleName { return RoleName(path.Dir(r.String())) } -// KeyWrap holds the PKCS#8 key along with Role and GUN -type KeyWrap struct { - Role RoleName - GUN GUN - Key []byte -} - // MetadataRoleMapToStringMap generates a map string of bytes from a map RoleName of bytes func MetadataRoleMapToStringMap(roles map[RoleName][]byte) map[string][]byte { metadata := make(map[string][]byte) diff --git a/tuf/utils/pkcs8.go b/tuf/utils/pkcs8.go index 562254c84..2c04c0ff4 100644 --- a/tuf/utils/pkcs8.go +++ b/tuf/utils/pkcs8.go @@ -111,6 +111,9 @@ func parsePKCS8ToTufKey(der []byte) (data.PrivateKey, error) { } if _, err := asn1.Unmarshal(der, &key); err != nil { + if _, ok := err.(asn1.StructuralError); ok { + return nil, errors.New("could not decrypt private key") + } return nil, err } diff --git a/tuf/utils/x509.go b/tuf/utils/x509.go index 0d1cce630..ba2117c3c 100644 --- a/tuf/utils/x509.go +++ b/tuf/utils/x509.go @@ -8,7 +8,6 @@ import ( "crypto/rsa" "crypto/x509" "crypto/x509/pkix" - "encoding/asn1" "encoding/pem" "errors" "fmt" @@ -149,16 +148,10 @@ func ParsePEMPrivateKey(pemBytes []byte, passphrase string) (data.PrivateKey, er return nil, fmt.Errorf("unsupported key type %q", block.Type) } case "PRIVATE ENCRYPTED KEY", "PRIVATE KEY": - var wrap data.KeyWrap - - if _, err := asn1.Unmarshal(block.Bytes, &wrap); err != nil { - return nil, errors.New("unable to unmarshal asn1 structure") - } - if passphrase == "" { - return ParsePKCS8ToTufKey(wrap.Key) + return ParsePKCS8ToTufKey(block.Bytes) } - return ParsePKCS8ToTufKey(wrap.Key, []byte(passphrase)) + return ParsePKCS8ToTufKey(block.Bytes, []byte(passphrase)) default: return nil, fmt.Errorf("unsupported key type %q", block.Type) } @@ -446,23 +439,16 @@ func ExtractPrivateKeyAttributes(pemBytes []byte) (data.RoleName, data.GUN, erro switch block.Type { case "RSA PRIVATE KEY", "EC PRIVATE KEY", "ED25519 PRIVATE KEY": if notary.FIPSEnabled { - return "", "", errors.New("unknown key format") + return "", "", errors.New("invalid key format") } - return data.RoleName(block.Headers["role"]), data.GUN(block.Headers["gun"]), nil case "PRIVATE KEY", "PRIVATE ENCRYPTED KEY": - var wrap data.KeyWrap - if _, err := asn1.Unmarshal(block.Bytes, &wrap); err != nil { - return "", "", errors.New("unable to unmarshal asn1 structure") - } - return wrap.Role, wrap.GUN, nil default: return "", "", errors.New("unknown key format") } + return data.RoleName(block.Headers["role"]), data.GUN(block.Headers["gun"]), nil } // ConvertPrivateKeyToPKCS8 converts a data.PrivateKey to PKCS#8 Format -// Since PKCS#8 doesn't allow any headers so PKCS#8 is being wrapped in another asn1 format (data.KeyWrap) -// as DER format with role and gun information. func ConvertPrivateKeyToPKCS8(key data.PrivateKey, role data.RoleName, gun data.GUN, passphrase string) ([]byte, error) { var ( err error @@ -480,16 +466,16 @@ func ConvertPrivateKeyToPKCS8(key data.PrivateKey, role data.RoleName, gun data. return nil, fmt.Errorf("unable to convert to PKCS8 key") } - b, err := asn1.Marshal(data.KeyWrap{ - Role: role, - GUN: gun, - Key: der, - }) - if err != nil { - return nil, fmt.Errorf("unable to marshal asn1 structure") + headers := make(map[string]string) + if role != "" { + headers["role"] = string(role) + } + + if gun != "" { + headers["gun"] = string(gun) } - return pem.EncodeToMemory(&pem.Block{Bytes: b, Type: blockType}), nil + return pem.EncodeToMemory(&pem.Block{Bytes: der, Type: blockType, Headers: headers}), nil } // CertToKey transforms a single input certificate into its corresponding diff --git a/tuf/utils/x509_test.go b/tuf/utils/x509_test.go index 630f690c5..1899294cb 100644 --- a/tuf/utils/x509_test.go +++ b/tuf/utils/x509_test.go @@ -6,7 +6,6 @@ import ( "crypto/rand" "crypto/rsa" "crypto/x509" - "encoding/asn1" "encoding/pem" "fmt" "io/ioutil" @@ -206,17 +205,12 @@ func TestKeyOperations(t *testing.T) { func testKeyBlockType(t *testing.T, b, password []byte, expectedKeyType string) { block, _ := pem.Decode(b) - var wrap data.KeyWrap - if _, err := asn1.Unmarshal(block.Bytes, &wrap); err != nil { - require.NoError(t, err, "unable to unmarshal key") - } - var privKey data.PrivateKey var err error if password == nil { - privKey, err = ParsePKCS8ToTufKey(wrap.Key) + privKey, err = ParsePKCS8ToTufKey(block.Bytes) } else { - privKey, err = ParsePKCS8ToTufKey(wrap.Key, password) + privKey, err = ParsePKCS8ToTufKey(block.Bytes, password) } if err != nil { require.NoError(t, err, "unable to parse to pkcs8") diff --git a/utils/keys.go b/utils/keys.go index afba9473c..2b65974a5 100644 --- a/utils/keys.go +++ b/utils/keys.go @@ -76,7 +76,6 @@ func ExportKeys(to io.Writer, s Exporter, from string) error { // parse PEM blocks if there are more than one for block, rest := pem.Decode(k); block != nil; block, rest = pem.Decode(rest) { // add from path in a header for later import - // TODO(umayr): unmarshal asn1 structure here block.Headers["path"] = from // write serialized PEM err = pem.Encode(to, block) diff --git a/utils/keys_test.go b/utils/keys_test.go index 90bd4cd5c..ee9579e2a 100644 --- a/utils/keys_test.go +++ b/utils/keys_test.go @@ -494,7 +494,7 @@ func TestEncryptedKeyImportFail(t *testing.T) { privKey, err := utils.GenerateECDSAKey(rand.Reader) require.NoError(t, err) - pemBytes, err := utils.EncryptPrivateKey(privKey, data.CanonicalRootRole, "", cannedPassphrase) + pemBytes, err := utils.ConvertPrivateKeyToPKCS8(privKey, data.CanonicalRootRole, "", cannedPassphrase) require.NoError(t, err) in := bytes.NewBuffer(pemBytes) @@ -511,7 +511,7 @@ func TestEncryptedKeyImportSuccess(t *testing.T) { originalKey := privKey.Private() require.NoError(t, err) - pemBytes, err := utils.EncryptPrivateKey(privKey, data.CanonicalSnapshotRole, "somegun", cannedPassphrase) + pemBytes, err := utils.ConvertPrivateKeyToPKCS8(privKey, data.CanonicalSnapshotRole, "somegun", cannedPassphrase) require.NoError(t, err) b, _ := pem.Decode(pemBytes) @@ -547,7 +547,7 @@ func TestEncryption(t *testing.T) { originalKey := privKey.Private() require.NoError(t, err) - pemBytes, err := utils.EncryptPrivateKey(privKey, "", "", "") + pemBytes, err := utils.ConvertPrivateKeyToPKCS8(privKey, "", "", "") require.NoError(t, err) in := bytes.NewBuffer(pemBytes)