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 }