package sm2m import ( "crypto/rand" "errors" "io" "math/big" "xdx.jelly/xgcl/grand" "xdx.jelly/xgcl/he/paillier" "xdx.jelly/xgcl/sm/sm2" "xdx.jelly/xgcl/sm/sm2/ec256" ) // clientBlindSignContext 只能使用NewClientBlindSignContext来生成. type clientBlindSignContext struct { k1 *big.Int rand io.Reader paillierPrivateKey *paillier.PrivateKey } // NewClientSignContext 生成客户端协同签名上下文 // pk没有用,可以传nil, rnd是随机数发生器. paillierPrivateKey可以临时产生密钥,也可以产生长期的保存在客户端. // 注: pk实际是用来验证完成后的签名. 这里由调用者自己验证即可. func NewClientBlindSignContext(pk *sm2.PublicKey, paillierPrivateKey *paillier.PrivateKey, r io.Reader) *clientBlindSignContext { c := &clientBlindSignContext{ k1: new(big.Int), rand: r, paillierPrivateKey: paillierPrivateKey, } return c } // Initial 客户端第一步, 返回e的同态密文和临时点P, 将他们同同态公钥一起发送给服务端. // // 客户端生成选择随机数k1 in [1, n - 1],计算e = SM3(Z || M), P = [k1]G, // 其中Z为32字节杂凑值,G为基点,向服务端发送签名请求并将 Enc_paillier(e), P, 发送给服务端。 // 注: 同态公钥可以使用客户端的部分私钥对应的公钥签名,服务端验证. func (c *clientBlindSignContext) Initial(e []byte) (ecipher *paillier.Cipher, p *sm2.PublicKey, err error) { if c.rand == nil { c.rand = grand.Reader } if c.k1 == nil { c.k1 = new(big.Int) } buf := make([]byte, sm2.ByteSize()) if n, err := c.rand.Read(buf); n != len(buf) || err != nil { return nil, nil, err } c.k1.SetBytes(buf) c.k1.Mod(c.k1, sm2.OrderN()) x, y := sm2.Curve256.ScalarMult(sm2.BaseX(), sm2.BaseY(), c.k1.Bytes()) p = &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y} paillierPublicKey := c.paillierPrivateKey.Public() ecipher, err = paillierPublicKey.Encrypt(new(big.Int).SetBytes(e), c.rand) if err != nil { return nil, nil, err } return ecipher, p, nil } // ServerSign 服务端计算. serverKey是服务端的部分密钥, pcipher,p和ppublickey是客户端发送过来的数据. // // 服务端生成随机数k2, k3, k4 in [1,n-1],(k = k1 * k2 + k3) // 计算(x1,y1)=[k2]P+[k3]G, // rcipher = Enc(r) = Enc(e)*Enc(x1) // s1 = k2*d2 mod n // s2cipher = Enc(s2) = (Enc(r)*E(k_3))^ds * Enc(k4*n) = Enc(ds*(r+k3)+k4*n). // 返回rcipher, s1, s2cipher, 并发送给客户端 func ServerBlindSign(serverKey *sm2.PrivateKey, ecipher *paillier.Cipher, p *sm2.PublicKey, ppublickey *paillier.PublicKey, rnd io.Reader) (rcipher *paillier.Cipher, s1 *big.Int, s2cipher *paillier.Cipher, err error) { var k2, k3, k4 *big.Int for { k2, err = rand.Int(rnd, sm2.OrderN()) if err != nil { return nil, nil, nil, err } if k2.Sign() == 0 { continue } k3, err = rand.Int(rnd, sm2.OrderN()) if err != nil { return nil, nil, nil, err } if k3.Sign() == 0 { continue } k4, err = rand.Int(rnd, sm2.OrderN()) if err != nil { return nil, nil, nil, err } if k4.Sign() == 0 { continue } break } x1, _ := ec256.CombinedMult(p.X, p.Y, k3.Bytes(), k2.Bytes()) x1cipher, err := ppublickey.Encrypt(x1, rnd) if err != nil { return nil, nil, nil, err } rcipher = x1cipher.HomomorphicAdd(x1cipher, ecipher, ppublickey) s1 = new(big.Int) s1.Mul(k2, serverKey.D) s1.Mod(s1, sm2.OrderN()) s2cipher, err = ppublickey.Encrypt(k3, rnd) if err != nil { return nil, nil, nil, err } s2cipher.HomomorphicAdd(s2cipher, rcipher, ppublickey) s2cipher.HomomorphicScalarMul(s2cipher, serverKey.D, ppublickey) k4.Mul(k4, sm2.OrderN()) k4Cipher, err := ppublickey.Encrypt(k4, rnd) if err != nil { return nil, nil, nil, err } s2cipher.HomomorphicAdd(s2cipher, k4Cipher, ppublickey) return rcipher, s1, s2cipher, nil } // Final 客户端计算签名 // // 客户端解密rcipher, s2cipher得到r, s2, // 计算s = d1*(k1*s1+s2)-r mod n,并检查s,r+s是否为0 mod q。 // 对消息M的签名为(r,s),客户端可验证签名是否正确. func (c *clientBlindSignContext) Final(clientKey *sm2.PrivateKey, rcipher *paillier.Cipher, s1 *big.Int, s2cipher *paillier.Cipher) (*sm2.Signature, error) { r, err := c.paillierPrivateKey.Decrypt(rcipher) if err != nil { return nil, err } r.Mod(r, sm2.OrderN()) if r.Sign() == 0 { return nil, errors.New("Blind sign failed, r = 0") } s2, err := c.paillierPrivateKey.Decrypt(s2cipher) s2.Mod(s2, sm2.OrderN()) s := c.k1.Mul(c.k1, s1) s.Add(s, s2).Mod(s, sm2.OrderN()).Mul(s, clientKey.D).Sub(s, r).Mod(s, sm2.OrderN()) if s.Sign() == 0 { return nil, errors.New("Blind sign failed, s = 0") } c.k1 = nil return &sm2.Signature{R: r, S: s}, nil }