...

Source file src/crypto/x509/pkcs8.go

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

View as plain text