...

Source file src/github.com/google/certificate-transparency-go/x509/pkcs8.go

Documentation: github.com/google/certificate-transparency-go/x509

     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  	"errors"
    11  	"fmt"
    12  
    13  	"github.com/google/certificate-transparency-go/asn1"
    14  	"github.com/google/certificate-transparency-go/x509/pkix"
    15  
    16  	// TODO(robpercival): change this to crypto/ed25519 when Go 1.13 is min version
    17  	"golang.org/x/crypto/ed25519"
    18  )
    19  
    20  // pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
    21  // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
    22  // and RFC 5208.
    23  type pkcs8 struct {
    24  	Version    int
    25  	Algo       pkix.AlgorithmIdentifier
    26  	PrivateKey []byte
    27  	// optional attributes omitted.
    28  }
    29  
    30  // ParsePKCS8PrivateKey parses an unencrypted private key in PKCS#8, ASN.1 DER form.
    31  //
    32  // It returns a *rsa.PrivateKey, a *ecdsa.PrivateKey, or a ed25519.PrivateKey.
    33  // More types might be supported in the future.
    34  //
    35  // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY".
    36  func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
    37  	var privKey pkcs8
    38  	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
    39  		if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil {
    40  			return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)")
    41  		}
    42  		if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil {
    43  			return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)")
    44  		}
    45  		return nil, err
    46  	}
    47  	switch {
    48  	case privKey.Algo.Algorithm.Equal(OIDPublicKeyRSA):
    49  		key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
    50  		if err != nil {
    51  			return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
    52  		}
    53  		return key, nil
    54  
    55  	case privKey.Algo.Algorithm.Equal(OIDPublicKeyECDSA):
    56  		bytes := privKey.Algo.Parameters.FullBytes
    57  		namedCurveOID := new(asn1.ObjectIdentifier)
    58  		if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
    59  			namedCurveOID = nil
    60  		}
    61  		key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
    62  		if err != nil {
    63  			return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
    64  		}
    65  		return key, nil
    66  
    67  	case privKey.Algo.Algorithm.Equal(OIDPublicKeyEd25519):
    68  		if l := len(privKey.Algo.Parameters.FullBytes); l != 0 {
    69  			return nil, errors.New("x509: invalid Ed25519 private key parameters")
    70  		}
    71  		var curvePrivateKey []byte
    72  		if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil {
    73  			return nil, fmt.Errorf("x509: invalid Ed25519 private key: %v", err)
    74  		}
    75  		if l := len(curvePrivateKey); l != ed25519.SeedSize {
    76  			return nil, fmt.Errorf("x509: invalid Ed25519 private key length: %d", l)
    77  		}
    78  		return ed25519.NewKeyFromSeed(curvePrivateKey), nil
    79  
    80  	default:
    81  		return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
    82  	}
    83  }
    84  
    85  // MarshalPKCS8PrivateKey converts a private key to PKCS#8, ASN.1 DER form.
    86  //
    87  // The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey
    88  // and ed25519.PrivateKey. Unsupported key types result in an error.
    89  //
    90  // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY".
    91  func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) {
    92  	var privKey pkcs8
    93  
    94  	switch k := key.(type) {
    95  	case *rsa.PrivateKey:
    96  		privKey.Algo = pkix.AlgorithmIdentifier{
    97  			Algorithm:  OIDPublicKeyRSA,
    98  			Parameters: asn1.NullRawValue,
    99  		}
   100  		privKey.PrivateKey = MarshalPKCS1PrivateKey(k)
   101  
   102  	case *ecdsa.PrivateKey:
   103  		oid, ok := OIDFromNamedCurve(k.Curve)
   104  		if !ok {
   105  			return nil, errors.New("x509: unknown curve while marshaling to PKCS#8")
   106  		}
   107  
   108  		oidBytes, err := asn1.Marshal(oid)
   109  		if err != nil {
   110  			return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
   111  		}
   112  
   113  		privKey.Algo = pkix.AlgorithmIdentifier{
   114  			Algorithm: OIDPublicKeyECDSA,
   115  			Parameters: asn1.RawValue{
   116  				FullBytes: oidBytes,
   117  			},
   118  		}
   119  
   120  		if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil {
   121  			return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
   122  		}
   123  
   124  	case ed25519.PrivateKey:
   125  		privKey.Algo = pkix.AlgorithmIdentifier{
   126  			Algorithm: OIDPublicKeyEd25519,
   127  		}
   128  		curvePrivateKey, err := asn1.Marshal(k.Seed())
   129  		if err != nil {
   130  			return nil, fmt.Errorf("x509: failed to marshal private key: %v", err)
   131  		}
   132  		privKey.PrivateKey = curvePrivateKey
   133  
   134  	default:
   135  		return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key)
   136  	}
   137  
   138  	return asn1.Marshal(privKey)
   139  }
   140  

View as plain text