1// Copyright 2015 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 5package pkcs12 6 7import ( 8 "crypto/ecdsa" 9 "crypto/elliptic" 10 "crypto/rsa" 11 "crypto/x509" 12 "crypto/x509/pkix" 13 "encoding/asn1" 14 "errors" 15) 16 17type pkcs8 struct { // Duplicated from x509 package 18 Version int 19 Algo pkix.AlgorithmIdentifier 20 PrivateKey []byte 21} 22 23var ( // Duplicated from x509 package 24 oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} 25 oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} 26) 27 28var ( // Duplicated from x509 package 29 oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} 30 oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} 31 oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} 32 oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} 33) 34 35func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { // Duplicated from x509 package 36 switch curve { 37 case elliptic.P224(): 38 return oidNamedCurveP224, true 39 case elliptic.P256(): 40 return oidNamedCurveP256, true 41 case elliptic.P384(): 42 return oidNamedCurveP384, true 43 case elliptic.P521(): 44 return oidNamedCurveP521, true 45 } 46 47 return nil, false 48} 49 50func marshalPKCS8PrivateKey(key interface{}) (der []byte, err error) { 51 var privKey pkcs8 52 switch key := key.(type) { 53 case *rsa.PrivateKey: 54 privKey.Algo.Algorithm = oidPublicKeyRSA 55 // This is a NULL parameters value which is technically 56 // superfluous, but most other code includes it. 57 privKey.Algo.Parameters = asn1.RawValue{ 58 Tag: 5, 59 } 60 privKey.PrivateKey = x509.MarshalPKCS1PrivateKey(key) 61 case *ecdsa.PrivateKey: 62 privKey.Algo.Algorithm = oidPublicKeyECDSA 63 namedCurveOID, ok := oidFromNamedCurve(key.Curve) 64 if !ok { 65 return nil, errors.New("pkcs12: unknown elliptic curve") 66 } 67 if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil { 68 return nil, errors.New("pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error()) 69 } 70 if privKey.PrivateKey, err = x509.MarshalECPrivateKey(key); err != nil { 71 return nil, errors.New("pkcs12: failed to embed EC private key in PKCS#8: " + err.Error()) 72 } 73 default: 74 return nil, errors.New("pkcs12: only RSA and ECDSA private keys supported") 75 } 76 return asn1.Marshal(privKey) 77} 78