github.com/emmansun/gmsm@v0.29.1/sm2/sm2_keyexchange.go (about) 1 package sm2 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/subtle" 6 "errors" 7 "io" 8 "math/big" 9 10 "github.com/emmansun/gmsm/sm3" 11 ) 12 13 // This file contains a math/big implementation of SM2 key exchange which is deprecated, please use ecdh instead. 14 15 // KeyExchange key exchange struct, include internal stat in whole key exchange flow. 16 // Initiator's flow will be: NewKeyExchange -> InitKeyExchange -> transmission -> ConfirmResponder 17 // Responder's flow will be: NewKeyExchange -> waiting ... -> RepondKeyExchange -> transmission -> ConfirmInitiator 18 type KeyExchange struct { 19 genSignature bool // control the optional sign/verify step triggered by responsder 20 keyLength int // key length 21 privateKey *PrivateKey // owner's encryption private key 22 z []byte // owner identifiable id 23 peerPub *ecdsa.PublicKey // peer public key 24 peerZ []byte // peer identifiable id 25 r *big.Int // Ephemeral Private Key, random which will be used to compute secret 26 secret *ecdsa.PublicKey // Ephemeral Public Key, generated secret which will be passed to peer 27 peerSecret *ecdsa.PublicKey // received peer's secret, Ephemeral Public Key 28 w2 *big.Int // internal state which will be used when compute the key and signature, 2^w 29 w2Minus1 *big.Int // internal state which will be used when compute the key and signature, 2^w – 1 30 v *ecdsa.PublicKey // internal state which will be used when compute the key and signature, u/v 31 } 32 33 func destroyBigInt(n *big.Int) { 34 if n != nil { 35 n.SetInt64(0) 36 } 37 } 38 39 func destroyPublicKey(pub *ecdsa.PublicKey) { 40 if pub != nil { 41 destroyBigInt(pub.X) 42 destroyBigInt(pub.Y) 43 } 44 } 45 46 func destroyBytes(bytes []byte) { 47 for v := range bytes { 48 bytes[v] = 0 49 } 50 } 51 52 // Destroy clear all internal state and Ephemeral private/public keys. 53 func (ke *KeyExchange) Destroy() { 54 destroyBytes(ke.z) 55 destroyBytes(ke.peerZ) 56 destroyBigInt(ke.r) 57 destroyPublicKey(ke.v) 58 } 59 60 // NewKeyExchange create one new KeyExchange object 61 // 62 // 在部分场景中,在初始 KeyExchange 时暂时没有对端的公开信息(如公钥、UID),这些信息可能需要在后续的交换中得到。 63 // 这种情况下,可设置 peerPub、peerUID 参数为 nil,并在合适的时候通过 KeyExchange.SetPeerParameters 方法配置相关参数。 64 // 注意 KeyExchange.SetPeerParameters 方法必须要在 KeyExchange.RepondKeyExchange 或 KeyExchange.RepondKeyExchange 方法之前调用。 65 func NewKeyExchange(priv *PrivateKey, peerPub *ecdsa.PublicKey, uid, peerUID []byte, keyLen int, genSignature bool) (ke *KeyExchange, err error) { 66 ke = &KeyExchange{} 67 ke.genSignature = genSignature 68 69 ke.keyLength = keyLen 70 ke.privateKey = priv 71 72 one := big.NewInt(1) 73 /* compute w = [log2(n)/2 - 1] = 127 */ 74 w := (priv.Params().N.BitLen()+1)/2 - 1 75 76 /* w2 = 2^w = 0x80000000000000000000000000000000 */ 77 ke.w2 = (&big.Int{}).Lsh(one, uint(w)) 78 /* x2minus1 = 2^w - 1 = 0x7fffffffffffffffffffffffffffffff */ 79 ke.w2Minus1 = (&big.Int{}).Sub(ke.w2, one) 80 81 if len(uid) == 0 { 82 uid = defaultUID 83 } 84 ke.z, err = CalculateZA(&ke.privateKey.PublicKey, uid) 85 if err != nil { 86 return nil, err 87 } 88 89 err = ke.SetPeerParameters(peerPub, peerUID) 90 if err != nil { 91 return nil, err 92 } 93 94 ke.secret = &ecdsa.PublicKey{} 95 ke.secret.Curve = priv.PublicKey.Curve 96 97 ke.v = &ecdsa.PublicKey{} 98 ke.v.Curve = priv.PublicKey.Curve 99 100 return 101 } 102 103 // SetPeerParameters 设置对端公开信息,该方法用于某些初期状态无法取得对端公开参数的场景。 104 // 例如:在TLCP协议中,基于SM2算法ECDHE过程。 105 // 106 // 注意该方法仅在 NewKeyExchange 没有提供 peerPub、peerUID参数时允许被调用, 107 // 且该方法只能调用一次不可重复调用,若多次调用或peerPub、peerUID已经存在则会发生错误。 108 func (ke *KeyExchange) SetPeerParameters(peerPub *ecdsa.PublicKey, peerUID []byte) error { 109 if peerPub == nil { 110 return nil 111 } 112 if len(peerUID) == 0 { 113 peerUID = defaultUID 114 } 115 if ke.peerPub != nil { 116 return errors.New("sm2: 'peerPub' already exists, please do not set it") 117 } 118 119 if peerPub.Curve != ke.privateKey.Curve { 120 return errors.New("sm2: peer public key is not expected/supported") 121 } 122 123 var err error 124 ke.peerPub = peerPub 125 ke.peerZ, err = CalculateZA(ke.peerPub, peerUID) 126 if err != nil { 127 return err 128 } 129 ke.peerSecret = &ecdsa.PublicKey{} 130 ke.peerSecret.Curve = peerPub.Curve 131 return nil 132 } 133 134 func initKeyExchange(ke *KeyExchange, r *big.Int) { 135 ke.secret.X, ke.secret.Y = ke.privateKey.ScalarBaseMult(r.Bytes()) 136 ke.r = r 137 } 138 139 // InitKeyExchange is for initiator's step A1-A3, returns generated Ephemeral Public Key which will be passed to Reponder. 140 func (ke *KeyExchange) InitKeyExchange(rand io.Reader) (*ecdsa.PublicKey, error) { 141 r, err := randFieldElement(ke.privateKey, rand) 142 if err != nil { 143 return nil, err 144 } 145 initKeyExchange(ke, r) 146 return ke.secret, nil 147 } 148 149 func (ke *KeyExchange) sign(isResponder bool, prefix byte) []byte { 150 var buffer []byte 151 hash := sm3.New() 152 hash.Write(toBytes(ke.privateKey, ke.v.X)) 153 if isResponder { 154 hash.Write(ke.peerZ) 155 hash.Write(ke.z) 156 hash.Write(toBytes(ke.privateKey, ke.peerSecret.X)) 157 hash.Write(toBytes(ke.privateKey, ke.peerSecret.Y)) 158 hash.Write(toBytes(ke.privateKey, ke.secret.X)) 159 hash.Write(toBytes(ke.privateKey, ke.secret.Y)) 160 } else { 161 hash.Write(ke.z) 162 hash.Write(ke.peerZ) 163 hash.Write(toBytes(ke.privateKey, ke.secret.X)) 164 hash.Write(toBytes(ke.privateKey, ke.secret.Y)) 165 hash.Write(toBytes(ke.privateKey, ke.peerSecret.X)) 166 hash.Write(toBytes(ke.privateKey, ke.peerSecret.Y)) 167 } 168 buffer = hash.Sum(nil) 169 hash.Reset() 170 hash.Write([]byte{prefix}) 171 hash.Write(toBytes(ke.privateKey, ke.v.Y)) 172 hash.Write(buffer) 173 return hash.Sum(nil) 174 } 175 176 func (ke *KeyExchange) generateSharedKey(isResponder bool) ([]byte, error) { 177 var buffer []byte 178 buffer = append(buffer, toBytes(ke.privateKey, ke.v.X)...) 179 buffer = append(buffer, toBytes(ke.privateKey, ke.v.Y)...) 180 if isResponder { 181 buffer = append(buffer, ke.peerZ...) 182 buffer = append(buffer, ke.z...) 183 } else { 184 buffer = append(buffer, ke.z...) 185 buffer = append(buffer, ke.peerZ...) 186 } 187 return sm3.Kdf(buffer, ke.keyLength), nil 188 } 189 190 // avf is the associative value function. 191 func (ke *KeyExchange) avf(x *big.Int) *big.Int { 192 t := (&big.Int{}).And(ke.w2Minus1, x) 193 t.Add(ke.w2, t) 194 return t 195 } 196 197 // mqv implements SM2-MQV procedure 198 func (ke *KeyExchange) mqv() { 199 // implicitSig: (sPriv + avf(ePub) * ePriv) mod N 200 // Calculate x2` 201 t := ke.avf(ke.secret.X) 202 203 // Calculate tB 204 t.Mul(t, ke.r) 205 t.Add(t, ke.privateKey.D) 206 t.Mod(t, ke.privateKey.Params().N) 207 208 // new base point: peerPub + [x1](peerSecret) 209 // x1` = 2^w + (x & (2^w – 1)) 210 x1 := ke.avf(ke.peerSecret.X) 211 // Point(x, y) = peerPub + [x1](peerSecret) 212 x, y := ke.privateKey.ScalarMult(ke.peerSecret.X, ke.peerSecret.Y, x1.Bytes()) 213 x, y = ke.privateKey.Add(ke.peerPub.X, ke.peerPub.Y, x, y) 214 215 ke.v.X, ke.v.Y = ke.privateKey.ScalarMult(x, y, t.Bytes()) 216 } 217 218 func respondKeyExchange(ke *KeyExchange, rA *ecdsa.PublicKey, r *big.Int) (*ecdsa.PublicKey, []byte, error) { 219 if ke.peerPub == nil { 220 return nil, nil, errors.New("sm2: no peer public key given") 221 } 222 if !ke.privateKey.IsOnCurve(rA.X, rA.Y) { 223 return nil, nil, errors.New("sm2: invalid initiator's ephemeral public key") 224 } 225 ke.peerSecret = rA 226 // secret = RB = [r]G 227 ke.secret.X, ke.secret.Y = ke.privateKey.ScalarBaseMult(r.Bytes()) 228 ke.r = r 229 230 ke.mqv() 231 if ke.v.X.Sign() == 0 && ke.v.Y.Sign() == 0 { 232 return nil, nil, errors.New("sm2: key exchange failed, V is infinity point") 233 } 234 235 if !ke.genSignature { 236 return ke.secret, nil, nil 237 } 238 239 return ke.secret, ke.sign(true, 0x02), nil 240 } 241 242 // RepondKeyExchange is for responder's step B1-B8, returns generated Ephemeral Public Key and optional signature 243 // depends on KeyExchange.genSignature value. 244 // 245 // It will check if there are peer's public key and validate the peer's Ephemeral Public Key. 246 func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, rA *ecdsa.PublicKey) (*ecdsa.PublicKey, []byte, error) { 247 r, err := randFieldElement(ke.privateKey, rand) 248 if err != nil { 249 return nil, nil, err 250 } 251 return respondKeyExchange(ke, rA, r) 252 } 253 254 // ConfirmResponder for initiator's step A4-A10, returns keying data and optional signature. 255 // 256 // It will check if there are peer's public key and validate the peer's Ephemeral Public Key. 257 // 258 // If the peer's signature is not empty, then it will also validate the peer's 259 // signature and return generated signature depends on KeyExchange.genSignature value. 260 func (ke *KeyExchange) ConfirmResponder(rB *ecdsa.PublicKey, sB []byte) ([]byte, []byte, error) { 261 if ke.peerPub == nil { 262 return nil, nil, errors.New("sm2: no peer public key given") 263 } 264 if !ke.privateKey.IsOnCurve(rB.X, rB.Y) { 265 return nil, nil, errors.New("sm2: invalid responder's ephemeral public key") 266 } 267 ke.peerSecret = rB 268 269 ke.mqv() 270 if ke.v.X.Sign() == 0 && ke.v.Y.Sign() == 0 { 271 return nil, nil, errors.New("sm2: key exchange failed, U is infinity point") 272 } 273 274 if len(sB) > 0 { 275 buffer := ke.sign(false, 0x02) 276 if subtle.ConstantTimeCompare(buffer, sB) != 1 { 277 return nil, nil, errors.New("sm2: invalid responder's signature") 278 } 279 } 280 key, err := ke.generateSharedKey(false) 281 if err != nil { 282 return nil, nil, err 283 } 284 285 if !ke.genSignature { 286 return key, nil, nil 287 } 288 return key, ke.sign(false, 0x03), nil 289 } 290 291 // ConfirmInitiator for responder's step B10 292 func (ke *KeyExchange) ConfirmInitiator(s1 []byte) ([]byte, error) { 293 if s1 != nil { 294 buffer := ke.sign(true, 0x03) 295 if subtle.ConstantTimeCompare(buffer, s1) != 1 { 296 return nil, errors.New("sm2: invalid initiator's signature") 297 } 298 } 299 return ke.generateSharedKey(true) 300 }