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