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  }