| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package x509 |
| |
| import ( |
| "crypto/x509/pkix" |
| "encoding/asn1" |
| "errors" |
| "fmt" |
| ) |
| |
| // pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See |
| // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn |
| // and RFC 5208. |
| type pkcs8 struct { |
| Version int |
| Algo pkix.AlgorithmIdentifier |
| PrivateKey []byte |
| // optional attributes omitted. |
| } |
| |
| // ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. |
| // See RFC 5208. |
| func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { |
| var privKey pkcs8 |
| if _, err := asn1.Unmarshal(der, &privKey); err != nil { |
| return nil, err |
| } |
| switch { |
| case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA): |
| key, err = ParsePKCS1PrivateKey(privKey.PrivateKey) |
| if err != nil { |
| return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error()) |
| } |
| return key, nil |
| |
| case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): |
| bytes := privKey.Algo.Parameters.FullBytes |
| namedCurveOID := new(asn1.ObjectIdentifier) |
| if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { |
| namedCurveOID = nil |
| } |
| key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) |
| if err != nil { |
| return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) |
| } |
| return key, nil |
| |
| default: |
| return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) |
| } |
| } |