1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x509 6 7 import ( 8 "crypto/ecdsa" 9 "crypto/rsa" 10 "crypto/x509/pkix" 11 "encoding/asn1" 12 "errors" 13 "fmt" 14 ) 15 16 // pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See 17 // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn 18 // and RFC 5208. 19 type pkcs8 struct { 20 Version int 21 Algo pkix.AlgorithmIdentifier 22 PrivateKey []byte 23 // optional attributes omitted. 24 } 25 26 // ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. 27 // See RFC 5208. 28 func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { 29 var privKey pkcs8 30 if _, err := asn1.Unmarshal(der, &privKey); err != nil { 31 return nil, err 32 } 33 switch { 34 case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA): 35 key, err = ParsePKCS1PrivateKey(privKey.PrivateKey) 36 if err != nil { 37 return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error()) 38 } 39 return key, nil 40 41 case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): 42 bytes := privKey.Algo.Parameters.FullBytes 43 namedCurveOID := new(asn1.ObjectIdentifier) 44 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { 45 namedCurveOID = nil 46 } 47 key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) 48 if err != nil { 49 return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) 50 } 51 return key, nil 52 53 default: 54 return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) 55 } 56 } 57 58 // MarshalPKCS8PrivateKey converts a private key to PKCS#8 encoded form. 59 // The following key types are supported: *rsa.PrivateKey, *ecdsa.PublicKey. 60 // Unsupported key types result in an error. 61 // 62 // See RFC 5208. 63 func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) { 64 var privKey pkcs8 65 66 switch k := key.(type) { 67 case *rsa.PrivateKey: 68 privKey.Algo = pkix.AlgorithmIdentifier{ 69 Algorithm: oidPublicKeyRSA, 70 Parameters: asn1.NullRawValue, 71 } 72 privKey.PrivateKey = MarshalPKCS1PrivateKey(k) 73 74 case *ecdsa.PrivateKey: 75 oid, ok := oidFromNamedCurve(k.Curve) 76 if !ok { 77 return nil, errors.New("x509: unknown curve while marshalling to PKCS#8") 78 } 79 80 oidBytes, err := asn1.Marshal(oid) 81 if err != nil { 82 return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) 83 } 84 85 privKey.Algo = pkix.AlgorithmIdentifier{ 86 Algorithm: oidPublicKeyECDSA, 87 Parameters: asn1.RawValue{ 88 FullBytes: oidBytes, 89 }, 90 } 91 92 if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil { 93 return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) 94 } 95 96 default: 97 return nil, fmt.Errorf("x509: unknown key type while marshalling PKCS#8: %T", key) 98 } 99 100 return asn1.Marshal(privKey) 101 } 102