gitee.com/lh-her-team/common@v1.5.1/crypto/asym/sm2/pkcs8.go (about)

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