init: v1.0.0

This commit is contained in:
yaole
2026-05-27 23:03:00 +08:00
commit 8d97f750eb
466 changed files with 80067 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
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
}