...

Source file src/github.com/tjfoc/gmsm/pkcs12/pkcs8.go

Documentation: github.com/tjfoc/gmsm/pkcs12

     1  // Copyright 2015 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 pkcs12
     6  
     7  import (
     8  	"crypto/ecdsa"
     9  	"crypto/elliptic"
    10  	"crypto/rsa"
    11  	"crypto/x509"
    12  	"crypto/x509/pkix"
    13  	"encoding/asn1"
    14  	"errors"
    15  	"github.com/tjfoc/gmsm/sm2"
    16  	"fmt"
    17  	"math/big"
    18  )
    19  
    20  type pkcs8 struct { // Duplicated from x509 package
    21  	Version    int
    22  	Algo       pkix.AlgorithmIdentifier
    23  	PrivateKey []byte
    24  }
    25  
    26  var ( // Duplicated from x509 package
    27  	oidPublicKeyRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
    28  	oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
    29  )
    30  
    31  var ( // Duplicated from x509 package
    32  	oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
    33  	oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
    34  	oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
    35  	oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
    36  	oidNamedCurveP256SM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301} // I get the SM2 ID through parsing the pem file generated by gmssl
    37  )
    38  
    39  func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { // Duplicated from x509 package
    40  	switch curve {
    41  	case elliptic.P224():
    42  		return oidNamedCurveP224, true
    43  	case elliptic.P256():
    44  		return oidNamedCurveP256, true
    45  	case elliptic.P384():
    46  		return oidNamedCurveP384, true
    47  	case elliptic.P521():
    48  		return oidNamedCurveP521, true
    49  	case sm2.P256Sm2():
    50  		return oidNamedCurveP256SM2, true
    51  	}
    52  
    53  	return nil, false
    54  }
    55  func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
    56  	switch {
    57  	case oid.Equal(oidNamedCurveP224):
    58  		return elliptic.P224()
    59  	case oid.Equal(oidNamedCurveP256):
    60  		return elliptic.P256()
    61  	case oid.Equal(oidNamedCurveP384):
    62  		return elliptic.P384()
    63  	case oid.Equal(oidNamedCurveP521):
    64  		return elliptic.P521()
    65  	case  oid.Equal(oidNamedCurveP256SM2):
    66  		return sm2.P256Sm2()
    67  	}
    68  	return nil
    69  }
    70  func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
    71  	var privKey pkcs8
    72  	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
    73  		return nil, err
    74  	}
    75  	switch {
    76  	case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
    77  		bytes := privKey.Algo.Parameters.FullBytes
    78  		namedCurveOID := new(asn1.ObjectIdentifier)
    79  		if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
    80  			namedCurveOID = nil
    81  		}
    82  		key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
    83  		if err != nil {
    84  			return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
    85  		}
    86  		return key, nil
    87  
    88  	default:
    89  		return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
    90  	}
    91  }
    92  func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
    93  	var privKey ecPrivateKey
    94  	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
    95  		return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
    96  	}
    97  	if privKey.Version != 1 {
    98  		return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
    99  	}
   100  
   101  	var curve elliptic.Curve
   102  	if namedCurveOID != nil {
   103  		curve = namedCurveFromOID(*namedCurveOID)
   104  	} else {
   105  		curve = namedCurveFromOID(privKey.NamedCurveOID)
   106  	}
   107  	if curve == nil {
   108  		return nil, errors.New("x509: unknown elliptic curve")
   109  	}
   110  
   111  	k := new(big.Int).SetBytes(privKey.PrivateKey)
   112  	curveOrder := curve.Params().N
   113  	if k.Cmp(curveOrder) >= 0 {
   114  		return nil, errors.New("x509: invalid elliptic curve private key value")
   115  	}
   116  	priv := new(ecdsa.PrivateKey)
   117  	priv.Curve = curve
   118  	priv.D = k
   119  
   120  	privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
   121  
   122  	// Some private keys have leading zero padding. This is invalid
   123  	// according to [SEC1], but this code will ignore it.
   124  	for len(privKey.PrivateKey) > len(privateKey) {
   125  		if privKey.PrivateKey[0] != 0 {
   126  			return nil, errors.New("x509: invalid private key length")
   127  		}
   128  		privKey.PrivateKey = privKey.PrivateKey[1:]
   129  	}
   130  
   131  	// Some private keys remove all leading zeros, this is also invalid
   132  	// according to [SEC1] but since OpenSSL used to do this, we ignore
   133  	// this too.
   134  	copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
   135  	priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
   136  
   137  	return priv, nil
   138  }
   139  func marshalPKCS8PrivateKey(key interface{}) (der []byte, err error) {
   140  	var privKey pkcs8
   141  	switch key := key.(type) {
   142  	case *rsa.PrivateKey:
   143  		privKey.Algo.Algorithm = oidPublicKeyRSA
   144  		// This is a NULL parameters value which is technically
   145  		// superfluous, but most other code includes it.
   146  		privKey.Algo.Parameters = asn1.RawValue{
   147  			Tag: 5,
   148  		}
   149  		privKey.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
   150  	case *ecdsa.PrivateKey:
   151  		privKey.Algo.Algorithm = oidPublicKeyECDSA
   152  		namedCurveOID, ok := oidFromNamedCurve(key.Curve)
   153  		if !ok {
   154  			return nil, errors.New("go-pkcs12: unknown elliptic curve")
   155  		}
   156  		if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil {
   157  			return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error())
   158  		}
   159  		if privKey.PrivateKey, err =x509.MarshalECPrivateKey(key); err != nil {
   160  			return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error())
   161  		}
   162  	case *sm2.PrivateKey:
   163  		privKey.Algo.Algorithm = oidPublicKeyECDSA
   164  		namedCurveOID, ok := oidFromNamedCurve(key.Curve)
   165  		if !ok {
   166  			return nil, errors.New("go-pkcs12: unknown elliptic curve")
   167  		}
   168  		if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil {
   169  			return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error())
   170  		}
   171  		if privKey.PrivateKey, err = MarshalECPrivateKey(key); err != nil {
   172  			return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error())
   173  		}
   174  	default:
   175  		return nil, errors.New("go-pkcs12: only RSA and ECDSA private keys supported")
   176  	}
   177  	return asn1.Marshal(privKey)
   178  }
   179  func MarshalECPrivateKey(key *sm2.PrivateKey) ([]byte, error) {
   180  	oid, ok := oidFromNamedCurve(key.Curve)
   181  	if !ok {
   182  		return nil, errors.New("x509: unknown elliptic curve")
   183  	}
   184  
   185  	return MarshalPrivateKey(key, oid)
   186  }
   187  func MarshalPrivateKey(key *sm2.PrivateKey, oid asn1.ObjectIdentifier)([]byte,error){
   188  	privateKeyBytes := key.D.Bytes()
   189  	paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
   190  	copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
   191  	return asn1.Marshal(ecPrivateKey{
   192  		Version:       1,
   193  		PrivateKey:    paddedPrivateKey,
   194  		NamedCurveOID: oid,
   195  		PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
   196  	})
   197  }
   198  type ecPrivateKey struct {
   199  	Version       int
   200  	PrivateKey    []byte
   201  	NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
   202  	PublicKey     asn1.BitString        `asn1:"optional,explicit,tag:1"`
   203  }

View as plain text