package sm2a import ( "io" "math/big" "xdx.jelly/xgcl/gmath" "xdx.jelly/xgcl/sm/sm2" "xdx.jelly/xgcl/sm/sm3" ) type ClientSignContext struct { pk *sm2.PublicKey k1 *big.Int rand io.Reader } func NewClientSignContext(pk *sm2.PublicKey, r io.Reader) *ClientSignContext { c := &ClientSignContext{ pk: sm2.NewPublicKey(), k1: new(big.Int), rand: r, } c.pk.Set(pk) return c } // Initial 客户端签名第一步,初始化,输入预处理后的待签名数据e,输出协同计算中间数据给服务端 // 输出 = e || [k_1](P+G) func (c *ClientSignContext) Initial(e []byte) ([]byte, error) { buf := make([]byte, sm2.ByteSize()) if n, err := c.rand.Read(buf); n != len(buf) || err != nil { return nil, err } c.k1.SetBytes(buf) c.k1.Mod(c.k1, sm2.OrderN()) x, y := sm2.Curve().Add(c.pk.X, c.pk.Y, sm2.BaseX(), sm2.BaseY()) x, y = sm2.Curve256.ScalarMult(x, y, c.k1.Bytes()) out := make([]byte, sm3.Size+2*sm2.ByteSize()) pos := copy(out, e) pos += copy(out[pos:], gmath.BigIntToNByte(x, sm2.ByteSize())) copy(out[pos:], gmath.BigIntToNByte(y, sm2.ByteSize())) return out, nil } // Final 客户端根据服务端协同计算结果,计算签名值 // in = r || s1 func (c *ClientSignContext) Final(clientKey *sm2.PrivateKey, in []byte) (*sm2.Signature, error) { sig := sm2.NewSignature() sig.R.SetBytes(in[:sm2.ByteSize()]) s1 := new(big.Int) s1.SetBytes(in[sm2.ByteSize():]) sig.S.Mul(sig.R, clientKey.D) sig.S.Add(sig.S, c.k1) sig.S.Add(sig.S, s1) sig.S.Sub(sig.S, sig.R) sig.S.Mod(sig.S, sm2.OrderN()) sig.R.Mod(sig.R, sm2.OrderN()) return sig, nil }