123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- // 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/ecdsa"
- "crypto/rsa"
- "errors"
- "fmt"
- "github.com/google/certificate-transparency-go/asn1"
- "github.com/google/certificate-transparency-go/x509/pkix"
- // TODO(robpercival): change this to crypto/ed25519 when Go 1.13 is min version
- "golang.org/x/crypto/ed25519"
- )
- // 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 private key in PKCS#8, ASN.1 DER form.
- //
- // It returns a *rsa.PrivateKey, a *ecdsa.PrivateKey, or a ed25519.PrivateKey.
- // More types might be supported in the future.
- //
- // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY".
- func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
- var privKey pkcs8
- if _, err := asn1.Unmarshal(der, &privKey); err != nil {
- if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil {
- return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)")
- }
- if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil {
- return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)")
- }
- 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
- case privKey.Algo.Algorithm.Equal(OIDPublicKeyEd25519):
- if l := len(privKey.Algo.Parameters.FullBytes); l != 0 {
- return nil, errors.New("x509: invalid Ed25519 private key parameters")
- }
- var curvePrivateKey []byte
- if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil {
- return nil, fmt.Errorf("x509: invalid Ed25519 private key: %v", err)
- }
- if l := len(curvePrivateKey); l != ed25519.SeedSize {
- return nil, fmt.Errorf("x509: invalid Ed25519 private key length: %d", l)
- }
- return ed25519.NewKeyFromSeed(curvePrivateKey), nil
- default:
- return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
- }
- }
- // MarshalPKCS8PrivateKey converts a private key to PKCS#8, ASN.1 DER form.
- //
- // The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey
- // and ed25519.PrivateKey. Unsupported key types result in an error.
- //
- // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY".
- func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) {
- var privKey pkcs8
- switch k := key.(type) {
- case *rsa.PrivateKey:
- privKey.Algo = pkix.AlgorithmIdentifier{
- Algorithm: OIDPublicKeyRSA,
- Parameters: asn1.NullRawValue,
- }
- privKey.PrivateKey = MarshalPKCS1PrivateKey(k)
- case *ecdsa.PrivateKey:
- oid, ok := OIDFromNamedCurve(k.Curve)
- if !ok {
- return nil, errors.New("x509: unknown curve while marshaling to PKCS#8")
- }
- oidBytes, err := asn1.Marshal(oid)
- if err != nil {
- return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
- }
- privKey.Algo = pkix.AlgorithmIdentifier{
- Algorithm: OIDPublicKeyECDSA,
- Parameters: asn1.RawValue{
- FullBytes: oidBytes,
- },
- }
- if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil {
- return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
- }
- case ed25519.PrivateKey:
- privKey.Algo = pkix.AlgorithmIdentifier{
- Algorithm: OIDPublicKeyEd25519,
- }
- curvePrivateKey, err := asn1.Marshal(k.Seed())
- if err != nil {
- return nil, fmt.Errorf("x509: failed to marshal private key: %v", err)
- }
- privKey.PrivateKey = curvePrivateKey
- default:
- return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key)
- }
- return asn1.Marshal(privKey)
- }
|