...

Source file src/pkg/crypto/x509/pkcs8.go

     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 an RSA 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