Files
xgcl/tpc/sm2/sm2a/keyexchange_client.go
2026-05-27 23:03:00 +08:00

184 lines
6.0 KiB
Go

package sm2a
import (
"fmt"
"xdx.jelly/xgcl/gmath"
"xdx.jelly/xgcl/grand"
"xdx.jelly/xgcl/sm/sm2"
)
type ClientSponsor struct {
mixPoint *sm2.PublicKey
KeyBits uint32
z []byte
r *sm2.PrivateKey // sponsor's temp private key
clientKey *sm2.PrivateKey
publicKey *sm2.PublicKey
tempKeyOfSponsor *sm2.PublicKey
tempKeyOfResponsor *sm2.PublicKey
}
func NewClientSponsor(id []byte, clientKey *sm2.PrivateKey, publicKey *sm2.PublicKey) *ClientSponsor {
return &ClientSponsor{
z: sm2.PreComputeWithIdAndPubkey(id, publicKey),
clientKey: sm2.NewPrivateKey().Set(clientKey),
publicKey: sm2.NewPublicKey().Set(publicKey),
tempKeyOfSponsor: sm2.NewPublicKey(),
tempKeyOfResponsor: sm2.NewPublicKey(),
}
}
// GenerateAgreementData 发起方客户端计算密钥交换数据
func (c *ClientSponsor) GenerateAgreementData(rnd []byte) (tempKeyOfSponsor *sm2.PublicKey, err error) {
if len(rnd) < sm2.ByteSize() {
rnd = make([]byte, sm2.ByteSize())
if _, err := grand.GenerateRandom(rnd); err != nil {
return nil, err
}
}
c.r, _ = sm2.GenPrivateKey(rnd[:sm2.ByteSize()])
tempKeyOfSponsor = sm2.GenPublicKey(c.r)
c.tempKeyOfSponsor.Set(tempKeyOfSponsor)
return tempKeyOfSponsor, nil
}
// GenerateKey_1of2 发起方客户端计算密钥第一步
func (c *ClientSponsor) GenerateKey_1of2(pubkeyOfResponsor, tempKeyOfResponsor *sm2.PublicKey) ([]byte, error) {
if !pubkeyOfResponsor.IsValid() || !tempKeyOfResponsor.IsValid() {
return nil, fmt.Errorf("Input Public Key are not valid")
}
c.mixPoint = mixPoint(pubkeyOfResponsor, tempKeyOfResponsor) // P+[x_R]·R
return marshalPoint(c.mixPoint), nil
}
// GenerateKey_2of2 发起方客户端计算密钥第二步
func (c *ClientSponsor) GenerateKey_2of2(keyLength int, idOfResponsor []byte, fromServer []byte, pubkeyOfResponsor *sm2.PublicKey, clientKey *sm2.PrivateKey) (key []byte, err error) {
if len(fromServer) < 2*sm2.ByteSize() {
return nil, fmt.Errorf("Input Public Key are not valid")
}
tempKeyOfServer := unmarshalPoint(fromServer)
if !tempKeyOfServer.IsValid() || !pubkeyOfResponsor.IsValid() {
return nil, fmt.Errorf("Input Public Key are not valid")
}
// U = [d_c + d_s + \bar{x_1} * r_A]*MixPointB
// = [d_s]*MixPointB + [d_c + \bar{x_1} * r_A]*MixPointB
w := sm2.XBar(c.tempKeyOfSponsor.X)
w.Mul(w, c.r.D)
w.Add(w, clientKey.D)
w.Mod(w, sm2.OrderN())
x, y := sm2.Curve256.ScalarMult(c.mixPoint.X, c.mixPoint.Y, w.Bytes())
x, y = sm2.Curve().Add(x, y, tempKeyOfServer.X, tempKeyOfServer.Y) // U = (x,y)
// printLog("U= %x\n", append(append([]byte{}, x.Bytes()...), y.Bytes()...))
if gmath.IsBigInt0(x) && gmath.IsBigInt0(y) {
return nil, fmt.Errorf("U is zero")
}
key = make([]byte, keyLength)
sm2.Kdf(key,
gmath.BigIntToNByte(x, sm2.ByteSize()),
gmath.BigIntToNByte(y, sm2.ByteSize()),
c.z,
sm2.PreComputeWithIdAndPubkey(idOfResponsor, pubkeyOfResponsor))
return key, nil
}
type ClientResponsor struct {
z []byte
clientKey *sm2.PrivateKey
publicKey *sm2.PublicKey
mixPoint *sm2.PublicKey
}
// NewResponsor return a responsor's instance
func NewClientResponsor(id []byte, clientKey *sm2.PrivateKey, publicKey *sm2.PublicKey) *ClientResponsor {
return &ClientResponsor{
z: sm2.PreComputeWithIdAndPubkey(id, publicKey),
clientKey: sm2.NewPrivateKey().Set(clientKey),
publicKey: sm2.NewPublicKey().Set(publicKey),
}
}
// GenerateAgreementDataAndKey_1of2 响应方客户端生成数据和密钥第一步
func (cr *ClientResponsor) GenerateAgreementDataAndKey_1of2(pubkeyOfSponsor, tempKeyOfSponsor *sm2.PublicKey) (toServer []byte, err error) {
if !pubkeyOfSponsor.IsValid() || !tempKeyOfSponsor.IsValid() {
return nil, fmt.Errorf("Input Public Key are not valid")
}
cr.mixPoint = mixPoint(pubkeyOfSponsor, tempKeyOfSponsor)
return marshalPoint(cr.mixPoint), nil
}
// GenerateAgreementDataAndKey_1of2 响应方客户端生成数据和密钥第二步
func (cr *ClientResponsor) GenerateAgreementDataAndKey_2of2(keyLength int, idOfSponsor []byte, pubkeyOfSponsor *sm2.PublicKey, fromServer []byte, rnd []byte) (key []byte, tempKeyOfResponsor *sm2.PublicKey, err error) {
if len(fromServer) < 2*sm2.ByteSize() {
return nil, nil, fmt.Errorf("Input Public Key are not valid")
}
tempKeyOfServer := unmarshalPoint(fromServer)
if !pubkeyOfSponsor.IsValid() || !tempKeyOfServer.IsValid() {
return nil, nil, fmt.Errorf("Input Public Key are not valid")
}
if len(rnd) < sm2.ByteSize() {
rnd = make([]byte, sm2.ByteSize())
if _, err := grand.GenerateRandom(rnd); err != nil {
return nil, nil, err
}
}
rb, _ := sm2.GenPrivateKey(rnd[:sm2.ByteSize()])
tempKeyOfResponsor = sm2.GenPublicKey(rb)
w := sm2.XBar(tempKeyOfResponsor.X)
w.Mul(w, rb.D)
w.Add(w, cr.clientKey.D)
w.Mod(w, sm2.OrderN())
x, y := sm2.Curve256.ScalarMult(cr.mixPoint.X, cr.mixPoint.Y, w.Bytes())
x, y = sm2.Curve().Add(x, y, tempKeyOfServer.X, tempKeyOfServer.Y) // V = (x,y)
// printLog("V=", append(append([]byte{}, x.Bytes()...), y.Bytes()...))
if gmath.IsBigInt0(x) && gmath.IsBigInt0(y) {
return nil, nil, fmt.Errorf("U is zero")
}
key = make([]byte, keyLength)
sm2.Kdf(key,
gmath.BigIntToNByte(x, sm2.ByteSize()),
gmath.BigIntToNByte(y, sm2.ByteSize()),
sm2.PreComputeWithIdAndPubkey(idOfSponsor, pubkeyOfSponsor),
cr.z,
)
return key, tempKeyOfResponsor, nil
}
// mixPoint return p+[x_r]·r
func mixPoint(p, r *sm2.PublicKey) *sm2.PublicKey {
xBar := sm2.XBar(r.X)
x, y := sm2.Curve256.ScalarMult(r.X, r.Y, xBar.Bytes())
x, y = sm2.Curve().Add(x, y, p.X, p.Y)
return &sm2.PublicKey{X: x, Y: y}
}
func marshalPoint(p *sm2.PublicKey) []byte {
out := make([]byte, 0, 2*sm2.ByteSize())
out = append(out, gmath.BigIntToNByte(p.X, sm2.ByteSize())...)
out = append(out, gmath.BigIntToNByte(p.Y, sm2.ByteSize())...)
return out
}
func unmarshalPoint(b []byte) *sm2.PublicKey {
ret := sm2.NewPublicKey()
ret.X.SetBytes(b[:sm2.ByteSize()])
ret.Y.SetBytes(b[sm2.ByteSize() : 2*sm2.ByteSize()])
return ret
}