github.com/emmansun/gmsm@v0.29.1/smx509/sec1.go (about) 1 package smx509 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "encoding/asn1" 7 "errors" 8 "fmt" 9 "math/big" 10 11 "github.com/emmansun/gmsm/ecdh" 12 "github.com/emmansun/gmsm/sm2" 13 ) 14 15 const ecPrivKeyVersion = 1 16 17 // ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure. 18 // References: 19 // RFC 5915 20 // SEC1 - http://www.secg.org/sec1-v2.pdf 21 // Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in 22 // most cases it is not. 23 type ecPrivateKey struct { 24 Version int 25 PrivateKey []byte 26 NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` 27 PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` 28 } 29 30 // ParseECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form. 31 // 32 // This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY". 33 func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) { 34 return parseECPrivateKey(nil, der) 35 } 36 37 // ParseSM2PrivateKey parses an SM2 private key in SEC 1, ASN.1 DER form. 38 func ParseSM2PrivateKey(der []byte) (*sm2.PrivateKey, error) { 39 key, err := parseECPrivateKey(nil, der) 40 if err != nil { 41 return nil, err 42 } 43 return new(sm2.PrivateKey).FromECPrivateKey(key) 44 } 45 46 // ParseTypedECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form. 47 // 48 // It returns a *ecdsa.PrivateKey or a *sm2.PrivateKey. 49 // 50 // This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY". 51 func ParseTypedECPrivateKey(der []byte) (any, error) { 52 key, err := parseECPrivateKey(nil, der) 53 if err != nil { 54 return nil, err 55 } 56 if key.Curve == sm2.P256() { 57 return new(sm2.PrivateKey).FromECPrivateKey(key) 58 } 59 return key, nil 60 } 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 *ecdsa.PrivateKey) ([]byte, error) { 68 oid, ok := oidFromNamedCurve(key.Curve) 69 if !ok { 70 return nil, errors.New("x509: unknown elliptic curve") 71 } 72 73 return marshalECPrivateKeyWithOID(key, oid) 74 } 75 76 // MarshalSM2PrivateKey convient method to marshal sm2 private key directly 77 func MarshalSM2PrivateKey(key *sm2.PrivateKey) ([]byte, error) { 78 return MarshalECPrivateKey(&key.PrivateKey) 79 } 80 81 // marshalECPrivateKey marshals an EC private key into ASN.1, DER format and 82 // sets the curve ID to the given OID, or omits it if OID is nil. 83 func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) { 84 if !key.Curve.IsOnCurve(key.X, key.Y) { 85 return nil, errors.New("invalid elliptic key public key") 86 } 87 privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) 88 return asn1.Marshal(ecPrivateKey{ 89 Version: 1, 90 PrivateKey: key.D.FillBytes(privateKey), 91 NamedCurveOID: oid, 92 PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, 93 }) 94 } 95 96 // parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. 97 // The OID for the named curve may be provided from another source (such as 98 // the PKCS8 container) - if it is provided then use this instead of the OID 99 // that may exist in the EC private key structure. 100 func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) { 101 var privKey ecPrivateKey 102 if _, err := asn1.Unmarshal(der, &privKey); err != nil { 103 if _, err := asn1.Unmarshal(der, &pkcs8{}); err == nil { 104 return nil, errors.New("x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)") 105 } 106 if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { 107 return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") 108 } 109 return nil, errors.New("x509: failed to parse EC private key: " + err.Error()) 110 } 111 if privKey.Version != ecPrivKeyVersion { 112 return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version) 113 } 114 115 var curve elliptic.Curve 116 if namedCurveOID != nil { 117 curve = namedCurveFromOID(*namedCurveOID) 118 } else { 119 curve = namedCurveFromOID(privKey.NamedCurveOID) 120 } 121 if curve == nil { 122 return nil, errors.New("x509: unknown elliptic curve") 123 } 124 125 k := new(big.Int).SetBytes(privKey.PrivateKey) 126 curveOrder := curve.Params().N 127 if k.Cmp(curveOrder) >= 0 { 128 return nil, errors.New("x509: invalid elliptic curve private key value") 129 } 130 priv := new(ecdsa.PrivateKey) 131 priv.Curve = curve 132 priv.D = k 133 134 privateKey := make([]byte, (curveOrder.BitLen()+7)/8) 135 136 // Some private keys have leading zero padding. This is invalid 137 // according to [SEC1], but this code will ignore it. 138 for len(privKey.PrivateKey) > len(privateKey) { 139 if privKey.PrivateKey[0] != 0 { 140 return nil, errors.New("x509: invalid private key length") 141 } 142 privKey.PrivateKey = privKey.PrivateKey[1:] 143 } 144 145 // Some private keys remove all leading zeros, this is also invalid 146 // according to [SEC1] but since OpenSSL used to do this, we ignore 147 // this too. 148 copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey) 149 priv.X, priv.Y = curve.ScalarBaseMult(privateKey) 150 151 return priv, nil 152 } 153 154 // marshalECDHPrivateKey marshals an EC private key into ASN.1, DER format 155 // suitable for SM2 curve. 156 func marshalECDHPrivateKey(key *ecdh.PrivateKey) ([]byte, error) { 157 return asn1.Marshal(ecPrivateKey{ 158 Version: 1, 159 PrivateKey: key.Bytes(), 160 PublicKey: asn1.BitString{Bytes: key.PublicKey().Bytes()}, 161 }) 162 }