github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/x509/sec1.go (about)

     1  // Copyright 2012 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  /*
     8  x509/sec1.go 椭圆曲线公私钥与其SEC 1, ASN.1 DER字节数组之间的相互转换
     9  目前支持sm2, ecdsa
    10  
    11  ParseECPrivateKey : 将SEC 1, ASN.1 DER格式字节数组转为EC(椭圆曲线)私钥
    12  MarshalECPrivateKey : 将EC(椭圆曲线)私钥转为SEC 1, ASN.1 DER格式字节数组
    13  */
    14  
    15  import (
    16  	"crypto/ecdsa"
    17  	"crypto/elliptic"
    18  	"encoding/asn1"
    19  	"errors"
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/hxx258456/ccgo/sm2"
    24  )
    25  
    26  const ecPrivKeyVersion = 1
    27  
    28  // 椭圆曲线私钥结构体
    29  // ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
    30  // References:
    31  //
    32  //	RFC 5915
    33  //	SEC1 - http://www.secg.org/sec1-v2.pdf
    34  //
    35  // Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
    36  // most cases it is not.
    37  type ecPrivateKey struct {
    38  	Version       int
    39  	PrivateKey    []byte
    40  	NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
    41  	PublicKey     asn1.BitString        `asn1:"optional,explicit,tag:1"`
    42  }
    43  
    44  // ParseECPrivateKey 将SEC 1, ASN.1 DER格式字节数组转为EC(椭圆曲线)私钥
    45  // 私钥目前支持: *sm2.PrivateKey, *ecdsa.PrivateKey
    46  //
    47  // ParseECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form.
    48  // This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY".
    49  func ParseECPrivateKey(der []byte) (interface{}, error) {
    50  	return parseECPrivateKey(nil, der)
    51  }
    52  
    53  // MarshalECPrivateKey 将EC(椭圆曲线)私钥转为SEC 1, ASN.1 DER格式字节数组
    54  // 私钥目前支持: *sm2.PrivateKey, *ecdsa.PrivateKey
    55  //
    56  // MarshalECPrivateKey converts an EC private key to SEC 1, ASN.1 DER form.
    57  //
    58  // This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY".
    59  // For a more flexible key format which is not EC specific, use
    60  // MarshalPKCS8PrivateKey.
    61  func MarshalECPrivateKey(key interface{}) ([]byte, error) {
    62  	switch priv := key.(type) {
    63  	case *ecdsa.PrivateKey:
    64  		oid, ok := oidFromNamedCurve(priv.Curve)
    65  		if !ok {
    66  			return nil, errors.New("gmx509.MarshalECPrivateKey: unknown elliptic curve")
    67  		}
    68  		if oid.Equal(oidNamedCurveP256SM2) {
    69  			return nil, errors.New("gmx509.MarshalECPrivateKey: not ecdsa curves")
    70  		}
    71  		privateKey := make([]byte, (priv.Curve.Params().N.BitLen()+7)/8)
    72  		return asn1.Marshal(ecPrivateKey{
    73  			Version:       ecPrivKeyVersion,
    74  			PrivateKey:    priv.D.FillBytes(privateKey),
    75  			NamedCurveOID: oid,
    76  			PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(priv.Curve, priv.X, priv.Y)},
    77  		})
    78  	case *sm2.PrivateKey:
    79  		oid, ok := oidFromNamedCurve(priv.Curve)
    80  		if !ok {
    81  			return nil, errors.New("gmx509.MarshalECPrivateKey: unknown elliptic curve")
    82  		}
    83  		if !oid.Equal(oidNamedCurveP256SM2) {
    84  			return nil, errors.New("gmx509.MarshalECPrivateKey: not sm2 curve")
    85  		}
    86  		privateKey := make([]byte, (priv.Curve.Params().N.BitLen()+7)/8)
    87  		return asn1.Marshal(ecPrivateKey{
    88  			Version:       ecPrivKeyVersion,
    89  			PrivateKey:    priv.D.FillBytes(privateKey),
    90  			NamedCurveOID: oid,
    91  			PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(priv.Curve, priv.X, priv.Y)},
    92  		})
    93  		// var ecPriv ecPrivateKey
    94  		// ecPriv.Version = ecPrivKeyVersion
    95  		// ecPriv.NamedCurveOID = oidNamedCurveP256SM2
    96  		// ecPriv.PublicKey = asn1.BitString{Bytes: elliptic.Marshal(priv.Curve, priv.X, priv.Y)}
    97  		// ecPriv.PrivateKey = priv.D.Bytes()
    98  		// return asn1.Marshal(ecPriv)
    99  	}
   100  	return nil, errors.New("x509: failed to marshalECPrivateKeyWithOID: Unknown PrivateKey")
   101  }
   102  
   103  // parseECPrivateKey根据namedCurveOID获取对应的椭圆曲线,并将SEC 1, ASN.1 DER格式字节数组转为EC(椭圆曲线)私钥
   104  // 私钥目前支持: *sm2.PrivateKey, *ecdsa.PrivateKey
   105  //
   106  // parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
   107  // The OID for the named curve may be provided from another source (such as
   108  // the PKCS8 container) - if it is provided then use this instead of the OID
   109  // that may exist in the EC private key structure.
   110  func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key interface{}, err error) {
   111  	var privKey ecPrivateKey
   112  	// 尝试将 der 反序列化到 privKey
   113  	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
   114  		if _, err := asn1.Unmarshal(der, &pkcs8{}); err == nil {
   115  			return nil, errors.New("gmx509.parseECPrivateKey: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)")
   116  		}
   117  		if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil {
   118  			return nil, errors.New("gmx509.parseECPrivateKey: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)")
   119  		}
   120  		return nil, fmt.Errorf("gmx509.parseECPrivateKey: failed to parse EC private key: %s", err.Error())
   121  	}
   122  	// 检查版本
   123  	if privKey.Version != ecPrivKeyVersion {
   124  		return nil, fmt.Errorf("gmx509.parseECPrivateKey: unknown EC private key version %d", privKey.Version)
   125  	}
   126  	var curve elliptic.Curve
   127  	// namedCurveOID有可能为nil,因为ecdsa在其序列化(pkcs8.go的MarshalPKCS8PrivateKey)分支里并没有传入oid到序列化结构中去。
   128  	if namedCurveOID != nil {
   129  		// 根据namedCurveOID获取曲线
   130  		curve = namedCurveFromOID(*namedCurveOID)
   131  	} else {
   132  		// namedCurveOID为空则使用私钥的NamedCurveOID
   133  		curve = namedCurveFromOID(privKey.NamedCurveOID)
   134  	}
   135  	if curve == nil {
   136  		return nil, errors.New("gmx509.parseECPrivateKey: unknown elliptic curve")
   137  	}
   138  	// 检查私钥数值是否小于曲线参数N
   139  	k := new(big.Int).SetBytes(privKey.PrivateKey)
   140  	curveOrder := curve.Params().N
   141  	if k.Cmp(curveOrder) >= 0 {
   142  		return nil, errors.New("gmx509.parseECPrivateKey: invalid elliptic curve private key value")
   143  	}
   144  	// 根据曲线选择生成对应完整私钥
   145  	switch curve {
   146  	case sm2.P256Sm2():
   147  		priv := new(sm2.PrivateKey)
   148  		priv.Curve = curve
   149  		priv.D = k
   150  		privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
   151  		// Some private keys have leading zero padding. This is invalid
   152  		// according to [SEC1], but this code will ignore it.
   153  		for len(privKey.PrivateKey) > len(privateKey) {
   154  			if privKey.PrivateKey[0] != 0 {
   155  				return nil, errors.New("gmx509.parseECPrivateKey: invalid private key length")
   156  			}
   157  			privKey.PrivateKey = privKey.PrivateKey[1:]
   158  		}
   159  		// Some private keys remove all leading zeros, this is also invalid
   160  		// according to [SEC1] but since OpenSSL used to do this, we ignore
   161  		// this too.
   162  		copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
   163  		priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
   164  		return priv, nil
   165  	case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
   166  		priv := new(ecdsa.PrivateKey)
   167  		priv.Curve = curve
   168  		priv.D = k
   169  		privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
   170  		// Some private keys have leading zero padding. This is invalid
   171  		// according to [SEC1], but this code will ignore it.
   172  		for len(privKey.PrivateKey) > len(privateKey) {
   173  			if privKey.PrivateKey[0] != 0 {
   174  				return nil, errors.New("gmx509.parseECPrivateKey: invalid private key length")
   175  			}
   176  			privKey.PrivateKey = privKey.PrivateKey[1:]
   177  		}
   178  		// Some private keys remove all leading zeros, this is also invalid
   179  		// according to [SEC1] but since OpenSSL used to do this, we ignore
   180  		// this too.
   181  		copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
   182  		priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
   183  		return priv, nil
   184  	}
   185  	return nil, errors.New("gmx509.parseECPrivateKey: failed to parseECPrivateKey: Unknown curve")
   186  }
   187  
   188  // marshalECPrivateKeyWithOID根据oid将EC(椭圆曲线)私钥转为SEC 1, ASN.1 DER格式字节数组
   189  // 私钥目前支持: *sm2.PrivateKey, *ecdsa.PrivateKey
   190  //
   191  // marshalECPrivateKey marshals an EC private key into ASN.1, DER format and
   192  // sets the curve ID to the given OID, or omits it if OID is nil.
   193  func marshalECPrivateKeyWithOID(key interface{}, oid asn1.ObjectIdentifier) ([]byte, error) {
   194  	switch priv := key.(type) {
   195  	case *ecdsa.PrivateKey:
   196  		if oid.Equal(oidNamedCurveP256SM2) {
   197  			return nil, errors.New("gmx509.marshalECPrivateKeyWithOID: not ecdsa curves")
   198  		}
   199  		privateKey := make([]byte, (priv.Curve.Params().N.BitLen()+7)/8)
   200  		return asn1.Marshal(ecPrivateKey{
   201  			Version:       ecPrivKeyVersion,
   202  			PrivateKey:    priv.D.FillBytes(privateKey),
   203  			NamedCurveOID: oid,
   204  			PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(priv.Curve, priv.X, priv.Y)},
   205  		})
   206  	case *sm2.PrivateKey:
   207  		if !oid.Equal(oidNamedCurveP256SM2) {
   208  			return nil, errors.New("gmx509.marshalECPrivateKeyWithOID: not sm2 curve")
   209  		}
   210  		privateKey := make([]byte, (priv.Curve.Params().N.BitLen()+7)/8)
   211  		return asn1.Marshal(ecPrivateKey{
   212  			Version:       ecPrivKeyVersion,
   213  			PrivateKey:    priv.D.FillBytes(privateKey),
   214  			NamedCurveOID: oid,
   215  			PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(priv.Curve, priv.X, priv.Y)},
   216  		})
   217  		// var ecPriv ecPrivateKey
   218  		// ecPriv.Version = ecPrivKeyVersion
   219  		// ecPriv.NamedCurveOID = oidNamedCurveP256SM2
   220  		// ecPriv.PublicKey = asn1.BitString{Bytes: elliptic.Marshal(priv.Curve, priv.X, priv.Y)}
   221  		// ecPriv.PrivateKey = priv.D.Bytes()
   222  		// return asn1.Marshal(ecPriv)
   223  	}
   224  	return nil, errors.New("gmx509.marshalECPrivateKeyWithOID: failed to marshalECPrivateKeyWithOID: Unknown PrivateKey")
   225  }