init: v1.0.0
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
func TestAuditSign(t *testing.T) {
|
||||
|
||||
rnd := make([]byte, 32)
|
||||
clientKey, clientTempKey, _ := ClientGenSignKey_one(nil)
|
||||
_, _ = grand.GenerateRandom(rnd)
|
||||
serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, rnd)
|
||||
err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
|
||||
if err != nil {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
|
||||
d := realPrivateKey(serverKey, clientKey)
|
||||
if !publicKey.Equals(&d.PublicKey) {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
fmt.Printf("客户端密钥分量: %x\n", clientKey.Bytes())
|
||||
fmt.Printf("服务端密钥分量: %x\n", serverKey.Bytes())
|
||||
fmt.Printf("公钥: %x\n", publicKey.Bytes())
|
||||
|
||||
c := new(ClientSignContext)
|
||||
e := make([]byte, 32)
|
||||
grand.GenerateRandom(e)
|
||||
fmt.Printf("签名数据e: %x\n", e)
|
||||
out, err := c.Initial(e)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, err = ServerSign(serverKey, out, grand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sig, err := c.Final(clientKey, out)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fmt.Printf("签名结果: %x\n", sig.Bytes())
|
||||
|
||||
if !sm2.Verify(e, publicKey, sig) {
|
||||
t.Fatal("verify failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuditDec(t *testing.T) {
|
||||
|
||||
rnd := make([]byte, 32)
|
||||
grand.ReaderOne.Read(rnd)
|
||||
clientKey, clientTempKey, _ := ClientGenSignKey_one(rnd)
|
||||
// _, _ = grand.GenerateRandom(rnd)
|
||||
grand.ReaderTwo.Read(rnd)
|
||||
serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, rnd)
|
||||
err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
|
||||
if err != nil {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
|
||||
d := realPrivateKey(serverKey, clientKey)
|
||||
if !publicKey.Equals(&d.PublicKey) {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
fmt.Printf("客户端密钥分量: %x\n", clientKey.Bytes())
|
||||
fmt.Printf("服务端密钥分量: %x\n", serverKey.Bytes())
|
||||
fmt.Printf("公钥: %x\n", publicKey.Bytes())
|
||||
|
||||
msg := []byte("1234567890123456")
|
||||
fmt.Printf("明文数据: %x\n", msg)
|
||||
|
||||
grand.ReaderOne.Read(rnd)
|
||||
c, _ := sm2.Encrypt(publicKey, msg, rnd)
|
||||
fmt.Printf("密文数据: %x\n", c.Bytes())
|
||||
|
||||
clientCTX := NewClientDecContext()
|
||||
out, _ := clientCTX.Initial(c)
|
||||
out, _ = ServerImportKey(serverKey, out)
|
||||
plain, _ := clientCTX.Final(clientKey, out)
|
||||
fmt.Printf("解密数据: %x\n", plain)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
// ClientGenAuthKey 生成客户端授权密钥
|
||||
// dc' = dc * r
|
||||
func ClientGenAuthKey(clientKey *sm2.PrivateKey, rnd io.Reader) (*sm2.PrivateKey, []byte, error) {
|
||||
var r *big.Int
|
||||
var err error
|
||||
for r == nil || gmath.IsBigInt0(r) {
|
||||
r, err = rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, gerrors.WithAnnotating(ErrInvalidInput, "input rnd must be nil, []byte or io.Reader")
|
||||
}
|
||||
}
|
||||
|
||||
authKey := sm2.NewPrivateKey()
|
||||
|
||||
authKey.D.Mul(clientKey.D, r)
|
||||
authKey.D.Mod(authKey.D, sm2.OrderN())
|
||||
return authKey, gmath.BigIntToNByte(r, sm2.ByteSize()), nil
|
||||
}
|
||||
|
||||
// ServerGenAuthKey 生成服务端授权密钥
|
||||
// // ds' = ds / r
|
||||
func ServerGenAuthKey(serverKey *sm2.PrivateKey, r []byte) (*sm2.PrivateKey, error) {
|
||||
bigR := new(big.Int).SetBytes(r)
|
||||
if gmath.IsBigInt0(bigR) || bigR.Cmp(sm2.OrderN()) >= 0 {
|
||||
return nil, gerrors.WithAnnotating(ErrInvalidInput, "input r is zero or bigger than order N")
|
||||
}
|
||||
bigR.ModInverse(bigR, sm2.OrderN())
|
||||
authKey := sm2.NewPrivateKey()
|
||||
authKey.D.Mul(serverKey.D, bigR)
|
||||
authKey.D.Mod(authKey.D, sm2.OrderN())
|
||||
return authKey, nil
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
func TestAuthKey(t *testing.T) {
|
||||
// Generate key
|
||||
clientKey, clientTempKey, err := ClientGenSignKey_one(grand.GetRandom(sm2.ByteSize()))
|
||||
if err != nil {
|
||||
t.Log()
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, grand.GetRandom(sm2.ByteSize()))
|
||||
if err != nil {
|
||||
t.Log()
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
if err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey); err != nil {
|
||||
t.Log()
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
t.Log("======= 协同密钥 =========")
|
||||
t.Logf("ClientKey=%v\nServerKey=%v\nPublicKey=%v", clientKey, serverKey, publicKey)
|
||||
|
||||
d := realPrivateKey(clientKey, serverKey)
|
||||
t.Logf("Real private key: %v", d)
|
||||
t.Logf("Real public key: %v", sm2.GenPublicKey(d))
|
||||
|
||||
t.Log("================ Signature Test==============")
|
||||
c := NewClientSignContext(publicKey, grand.Reader)
|
||||
e := grand.GetRandom(sm2.ByteSize())
|
||||
out, _ := c.Initial(e)
|
||||
out, _ = ServerSign(serverKey, out, grand.Reader)
|
||||
sig, _ := c.Final(clientKey, out)
|
||||
t.Logf("Signature: %v", sig)
|
||||
isValid := sm2.Verify(e, publicKey, sig)
|
||||
if !isValid {
|
||||
t.Log("verify success")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
t.Logf("verify = %v", isValid)
|
||||
|
||||
t.Log("========== auth key ===========")
|
||||
clientAuthKey, randomFactor, err := ClientGenAuthKey(clientKey, grand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serverAuthKey, err := ServerGenAuthKey(serverKey, randomFactor)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ad := realPrivateKey(clientAuthKey, serverAuthKey)
|
||||
if ad.D.Cmp(d.D) != 0 {
|
||||
t.Log("auth key generate failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
t.Logf("Real auth private key: %v", ad)
|
||||
t.Logf("Real auth public key: %v", sm2.GenPublicKey(ad))
|
||||
t.Log("================ Signature Test (auth key)==============")
|
||||
c = NewClientSignContext(publicKey, grand.Reader)
|
||||
e = grand.GetRandom(sm2.ByteSize())
|
||||
out, _ = c.Initial(e)
|
||||
out, _ = ServerSign(serverAuthKey, out, grand.Reader)
|
||||
sig, _ = c.Final(clientAuthKey, out)
|
||||
t.Logf("Signature: %v", sig)
|
||||
isValid = sm2.Verify(e, publicKey, sig)
|
||||
if !isValid {
|
||||
t.Log("verify success")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
t.Logf("verify = %v", isValid)
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
func TestBlindSign(t *testing.T) {
|
||||
// 生成协同密钥
|
||||
rnd := make([]byte, 32)
|
||||
clientKey, clientTempKey, err := ClientGenSignKey_one(nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
_, _ = grand.GenerateRandom(rnd)
|
||||
serverKey, serverTempKey, publicKey, err := ServerGenSignKey(clientTempKey, rnd)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 生成paillier密钥
|
||||
psk, ppk, err := paillier.GenerateKey(2048)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 盲协同签名
|
||||
e := make([]byte, 32)
|
||||
|
||||
c := NewClientBlindSignContext(publicKey, psk, grand.Reader)
|
||||
ecipher, p, err := c.Initial(e)
|
||||
assert.Nil(t, err)
|
||||
|
||||
rcipher, s1, s2cipher, err := ServerBlindSign(serverKey, ecipher, p, ppk, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
sig, err := c.Final(clientKey, rcipher, s1, s2cipher)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, sm2.Verify(e, publicKey, sig))
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrIndataError = fmt.Errorf("data input error")
|
||||
)
|
||||
|
||||
type ClientDecContext struct {
|
||||
cipher sm2.Cipher
|
||||
}
|
||||
|
||||
func NewClientDecContext() *ClientDecContext {
|
||||
return &ClientDecContext{cipher: *sm2.NewCipher()}
|
||||
}
|
||||
|
||||
// Initial 客户端解密,将密文中的C1发送给服务端
|
||||
func (c *ClientDecContext) Initial(cipher *sm2.Cipher) (out []byte, err error) {
|
||||
c.cipher.Set(cipher)
|
||||
out = make([]byte, 0, 2*sm2.ByteSize())
|
||||
out = append(out, gmath.BigIntToNByte(cipher.X, sm2.ByteSize())...)
|
||||
out = append(out, gmath.BigIntToNByte(cipher.Y, sm2.ByteSize())...)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Final 客户端解密得到密文
|
||||
func (c *ClientDecContext) Final(clientKey *sm2.PrivateKey, in []byte) ([]byte, error) {
|
||||
if len(in) < 2*sm2.ByteSize() {
|
||||
return []byte{}, ErrIndataError
|
||||
}
|
||||
// d*C1 = dc^(-1)*ds^(-1)*C1 - C1
|
||||
x := new(big.Int)
|
||||
x.SetBytes(in[:sm2.ByteSize()])
|
||||
y := new(big.Int)
|
||||
y.SetBytes(in[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
cInv := new(big.Int)
|
||||
cInv.Set(clientKey.D)
|
||||
cInv.ModInverse(cInv, sm2.OrderN())
|
||||
|
||||
x, y = sm2.Curve256.ScalarMult(x, y, cInv.Bytes())
|
||||
gx := new(big.Int)
|
||||
gy := new(big.Int)
|
||||
gx.Set(c.cipher.X)
|
||||
gy.Set(c.cipher.Y)
|
||||
gy.Sub(sm2.Prime(), gy)
|
||||
x, y = sm2.Curve().Add(x, y, gx, gy)
|
||||
|
||||
return sm2.Decrypt_aux(x, y, &c.cipher)
|
||||
}
|
||||
|
||||
func ServerDec(serverKey *sm2.PrivateKey, in []byte) ([]byte, error) {
|
||||
return ServerImportKey(serverKey, in)
|
||||
}
|
||||
|
||||
// 将加密密钥拆分为服务端和客户端的密钥分量
|
||||
func SplitDecryptKey(de *sm2.PrivateKey, rnd io.Reader) (*sm2.PrivateKey, *sm2.PrivateKey, error) {
|
||||
dc := new(big.Int).Add(de.D, gmath.BigInt1)
|
||||
if dc.Cmp(sm2.OrderN()) == 0 {
|
||||
return &sm2.PrivateKey{D: big.NewInt(0)}, &sm2.PrivateKey{D: big.NewInt(0)}, nil
|
||||
}
|
||||
|
||||
var ds *big.Int
|
||||
var err error
|
||||
for {
|
||||
ds, err = rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if ds.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
dc.Mul(dc, ds)
|
||||
dc.Mod(dc, sm2.OrderN())
|
||||
dc.ModInverse(dc, sm2.OrderN())
|
||||
|
||||
skc := &sm2.PrivateKey{D: dc}
|
||||
sks := &sm2.PrivateKey{D: ds}
|
||||
return skc, sks, nil
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
Package sm2m is the two-parts compute of Sm2
|
||||
*/
|
||||
package sm2m
|
||||
|
||||
/*
|
||||
Package sm2 is the two-parts compute of Sm2
|
||||
SM2双方联合计算
|
||||
密钥分割方式:
|
||||
*/
|
||||
@@ -0,0 +1,17 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=ErrorCode -linecomment -output=errors_string.go errors.go
|
||||
type ErrorCode gerrors.ErrorCode
|
||||
|
||||
func (e ErrorCode) Error() string {
|
||||
return gerrors.Format(uint32(e), e.String())
|
||||
}
|
||||
|
||||
// error codes
|
||||
const (
|
||||
ErrInvalidInput ErrorCode = 0x0100f000 + iota //输入不合法
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
// Code generated by "stringer -type=ErrorCode -linecomment -output=errors_string.go errors.go"; DO NOT EDIT.
|
||||
|
||||
package sm2m
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[ErrInvalidInput-16838656]
|
||||
}
|
||||
|
||||
const _ErrorCode_name = "输入不合法"
|
||||
|
||||
var _ErrorCode_index = [...]uint8{0, 15}
|
||||
|
||||
func (i ErrorCode) String() string {
|
||||
i -= 16838656
|
||||
if i >= ErrorCode(len(_ErrorCode_index)-1) {
|
||||
return "ErrorCode(" + strconv.FormatInt(int64(i+16838656), 10) + ")"
|
||||
}
|
||||
return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]]
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
/*
|
||||
服务端和用户端的秘钥生成
|
||||
秘钥关系式: (1 + d)^(-1)= d1 * d2
|
||||
|
||||
签名(加密)秘钥双方生成流程
|
||||
a0 客户端初始化context
|
||||
a1 客户端(), 向服务端发送数据。
|
||||
|
||||
b1 服务端结收数据计算并发回数据()
|
||||
|
||||
a2 客户端接收数据并计算,输出签名
|
||||
a3 客户端清理context
|
||||
*/
|
||||
|
||||
// clientKey = d1
|
||||
// clientTempPublicKey = [d1^(-1)]*G
|
||||
func ClientGenSignKey_one(rnd any) (clientKey *sm2.PrivateKey, clientTempPublicKey *sm2.PublicKey, err error) {
|
||||
if rnd == nil {
|
||||
rnd = grand.Reader
|
||||
}
|
||||
switch rnd := rnd.(type) {
|
||||
case io.Reader:
|
||||
clientKey, err := sm2.GenerateKey(sm2.Curve(), rnd)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
clientTempPublicKey := &clientKey.PublicKey
|
||||
clientKey.D.ModInverse(clientKey.D, sm2.OrderN())
|
||||
return clientKey, clientTempPublicKey, nil
|
||||
case []byte:
|
||||
if rnd == nil || len(rnd) < 32 {
|
||||
return nil, nil, gerrors.WithAnnotating(ErrInvalidInput, "input rnd must be as 32 bytes")
|
||||
}
|
||||
clientKey = sm2.NewPrivateKey()
|
||||
_ = clientKey.SetBytes(rnd)
|
||||
clientTempPublicKey = sm2.GenPublicKey(clientKey)
|
||||
clientKey.D.ModInverse(clientKey.D, sm2.OrderN())
|
||||
err = nil
|
||||
return
|
||||
default:
|
||||
return nil, nil, errors.New("parameter rnd can only be nil, io.Reader or []byte (with length >= 32)")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
serverkey = d2 in [1, n - 1],
|
||||
publicKey = [d2^(-1)]clientTempPublicKey - G,用户签名公钥P
|
||||
serverTempPublicKey = [d2^(-1)]G,
|
||||
*/
|
||||
func ServerGenSignKey(clientTempPublicKey *sm2.PublicKey, rnd []byte) (
|
||||
serverKey *sm2.PrivateKey,
|
||||
serverTempPublicKey *sm2.PublicKey,
|
||||
publicKey *sm2.PublicKey,
|
||||
err error) {
|
||||
|
||||
if rnd == nil || len(rnd) < 32 {
|
||||
return nil, nil, nil, gerrors.WithAnnotating(ErrInvalidInput, "input rnd must be as 32 bytes")
|
||||
}
|
||||
|
||||
serverKey = sm2.NewPrivateKey()
|
||||
_ = serverKey.SetBytes(rnd)
|
||||
|
||||
serverTempPublicKey = sm2.GenPublicKey(serverKey)
|
||||
x, y := sm2.Curve256.ScalarMult(clientTempPublicKey.X, clientTempPublicKey.Y, serverKey.D.Bytes())
|
||||
y.Sub(sm2.Curve().Params().P, y)
|
||||
x, y = sm2.Curve().Add(x, y, sm2.Curve().Params().Gx, sm2.Curve().Params().Gy)
|
||||
y.Sub(sm2.Curve().Params().P, y)
|
||||
publicKey = &sm2.PublicKey{X: x, Y: y}
|
||||
serverKey.D.ModInverse(serverKey.D, sm2.OrderN())
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
// ClientGenSignKey_two 客户端对服务端发送来的公钥publicKey和根据clientKey,serverTempPublicKey计算出来的公钥比较。
|
||||
// 若两者一致,则秘钥生成成功。
|
||||
func ClientGenSignKey_two(clientKey *sm2.PrivateKey, serverTempPublicKey *sm2.PublicKey, publicKey *sm2.PublicKey) error {
|
||||
|
||||
d1Inv := new(big.Int).ModInverse(clientKey.D, sm2.OrderN())
|
||||
x, y := sm2.Curve256.ScalarMult(serverTempPublicKey.X, serverTempPublicKey.Y, d1Inv.Bytes())
|
||||
y.Sub(sm2.Curve().Params().P, y)
|
||||
x, y = sm2.Curve().Add(x, y, sm2.Curve().Params().Gx, sm2.Curve().Params().Gy)
|
||||
y.Sub(sm2.Curve().Params().P, y)
|
||||
|
||||
if x.Cmp(publicKey.X) != 0 || y.Cmp(publicKey.Y) != 0 {
|
||||
return fmt.Errorf("generate key failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// realPrivateKey compute the real private key, for test
|
||||
func realPrivateKey(clientKey, serverKey *sm2.PrivateKey) *sm2.PrivateKey {
|
||||
|
||||
d := new(big.Int).Mul(serverKey.D, clientKey.D)
|
||||
d.ModInverse(d, sm2.OrderN())
|
||||
d.Sub(d, gmath.BigInt1)
|
||||
sk := &sm2.PrivateKey{
|
||||
D: d,
|
||||
}
|
||||
sm2.GenPublicKey(sk)
|
||||
return sk
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
/*
|
||||
导入加密密钥de,由sm2签名密钥来解密sm2加密密钥保护结构。
|
||||
解密de后拆分也同签名密钥拆分
|
||||
(1+de)^{-1} = de_c*de_s
|
||||
为了加解密函数一致
|
||||
*/
|
||||
|
||||
// ServerDec 服务端计算(serverKey)^(-1)*C1,使用签名密钥解密加密密钥保护结构
|
||||
func ServerImportKey(serverKey *sm2.PrivateKey, in []byte) ([]byte, error) {
|
||||
if len(in) < 2*sm2.ByteSize() {
|
||||
return []byte{}, ErrIndataError
|
||||
}
|
||||
|
||||
x := new(big.Int)
|
||||
x.SetBytes(in[:sm2.ByteSize()])
|
||||
y := new(big.Int)
|
||||
y.SetBytes(in[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
|
||||
sInv := new(big.Int)
|
||||
sInv.Set(serverKey.D)
|
||||
sInv.ModInverse(sInv, sm2.OrderN())
|
||||
|
||||
x, y = sm2.Curve256.ScalarMult(x, y, sInv.Bytes())
|
||||
out := make([]byte, 0, 2*sm2.ByteSize())
|
||||
out = append(out, gmath.BigIntToNByte(x, sm2.ByteSize())...)
|
||||
out = append(out, gmath.BigIntToNByte(y, sm2.ByteSize())...)
|
||||
|
||||
return out, nil
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
func TestDec(t *testing.T) {
|
||||
rnd := make([]byte, 32)
|
||||
if _, err := grand.GenerateRandom(rnd); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
clientKey, clientTempKey, _ := ClientGenSignKey_one(rnd)
|
||||
if _, err := grand.GenerateRandom(rnd); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serverKey, serverTempKey, pk, _ := ServerGenSignKey(clientTempKey, rnd)
|
||||
_ = ClientGenSignKey_two(clientKey, serverTempKey, pk)
|
||||
|
||||
d := new(big.Int).Mul(serverKey.D, clientKey.D)
|
||||
d.ModInverse(d, sm2.OrderN())
|
||||
d.Sub(d, gmath.BigInt1)
|
||||
|
||||
msg := []byte("1234567890123456")
|
||||
c, _ := sm2.Encrypt(pk, msg, grand.GetRandom(32))
|
||||
sk := sm2.NewPrivateKey()
|
||||
sk.D = d
|
||||
msg2, _ := sm2.Decrypt(sk, c)
|
||||
fmt.Println(string(msg2))
|
||||
clientCTX := NewClientDecContext()
|
||||
out, _ := clientCTX.Initial(c)
|
||||
out, _ = ServerImportKey(serverKey, out)
|
||||
plain, _ := clientCTX.Final(clientKey, out)
|
||||
t.Log(string(plain))
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
/*
|
||||
============================= 生成授权密钥 ===============================
|
||||
客户端 服务端
|
||||
|
||||
---------------------------request-------------------------->
|
||||
|
||||
Enc(pailliar, dc'),
|
||||
虎符服务端公钥pk加密R: Enc(SM4GCM, k, R), Enc(SM2, pk, k)
|
||||
<------------------------------------------------------------
|
||||
|
||||
解密dc'
|
||||
组合授权包
|
||||
*/
|
||||
|
||||
// OSGenerateAuthKey 外包服务根据用户的授权密钥密文生成授权密钥密文,以及给虎符服务端的授权因子R
|
||||
// R由外包服务加密. (注,不能把R明文发给用户, 否则用户可以还原出自己的授权密钥)
|
||||
func OSGenerateAuthKey(encryptedKey *paillier.Cipher, evalKey *paillier.PublicKey, rnd io.Reader) (*paillier.Cipher, []byte, error) {
|
||||
var r *big.Int
|
||||
var err error
|
||||
for r == nil || gmath.IsBigInt0(r) {
|
||||
r, err = rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("generate random number failed")
|
||||
}
|
||||
}
|
||||
c := (&paillier.Cipher{}).HomomorphicScalarMul(encryptedKey, r, evalKey)
|
||||
rBytes := make([]byte, sm2.ByteSize())
|
||||
r.FillBytes(rBytes)
|
||||
return c, rBytes, nil
|
||||
}
|
||||
|
||||
// ClientDecryptAuthKey 客户端解密授权密钥密文, 小程序中实现.
|
||||
func ClientDecryptAuthKey(encryptedAuthKey *paillier.Cipher, decKey *paillier.PrivateKey) (*sm2.PrivateKey, error) {
|
||||
d, err := decKey.Decrypt(encryptedAuthKey)
|
||||
if err != nil {
|
||||
return nil, gerrors.WithAnnotating(err, "ClientDecryptAuthKey decrypt failed")
|
||||
}
|
||||
d.Mod(d, sm2.OrderN())
|
||||
return (&sm2.PrivateKey{}).SetBigInt(d), nil
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
"xdx.jelly/xgcl/sm/sm3"
|
||||
"xdx.jelly/xgcl/tpc/sm2/sm2m"
|
||||
)
|
||||
|
||||
func BenchmarkOS(b *testing.B) {
|
||||
// O、客户端生成paillier密钥
|
||||
salt := grand.GetRandom(16)
|
||||
paiPrivKey, err := paillier.GenerateKeyFromPassword(2048, []byte("password123"), salt, 1024)
|
||||
assert.Nil(b, err)
|
||||
paiPubKey := paiPrivKey.Public()
|
||||
|
||||
// 一、密钥生成
|
||||
|
||||
// 1)客户端第一步, a1, a2 发外包服务器
|
||||
clientKeyGen := &ClientKeyGenerator{}
|
||||
a1, a2, err := clientKeyGen.Step1(paiPubKey, grand.Reader)
|
||||
assert.Nil(b, err)
|
||||
|
||||
// 2) 外包服务器第一步
|
||||
// 保存encryptedClientKey1,encryptedClientKey2,
|
||||
// 把 P 发客户端
|
||||
// encryptedClientKey1 -签名用
|
||||
// encryptedClientKey2 -解密加密密钥保护结构用
|
||||
osKenGen := &OSKeyGenerator{}
|
||||
encryptedClientKey1, _, P, err := osKenGen.Step1(a1, a2, paiPubKey, grand.Reader)
|
||||
assert.Nil(b, err)
|
||||
|
||||
// 3) 客户端第二步
|
||||
// clientTempKey发协同签名服务端
|
||||
clientTempKey, err := clientKeyGen.Step2(P)
|
||||
|
||||
// 4)协同签名服务器
|
||||
// serverTempKey 发客户端,保存serverKey-服务端密钥分量
|
||||
serverKey, serverTempKey, publicKey, _ := sm2m.ServerGenSignKey(clientTempKey, grand.GetRandom(32))
|
||||
|
||||
// 5)客户端第三步
|
||||
// 把(serverTempKey,S)发送给外包服务器
|
||||
S, err := clientKeyGen.Step3(serverTempKey)
|
||||
assert.Nil(b, err)
|
||||
|
||||
// 6)外包服务器第二步
|
||||
// 把T, osPublicKey发给客户端。保存osPublicKey为用户签名公钥
|
||||
T, osPublicKey, err := osKenGen.Step2(serverTempKey, S)
|
||||
assert.Nil(b, err)
|
||||
|
||||
// 7)客户端第四步
|
||||
// clientPublicKey, 客户端生成的公钥,如果没有返错,则应与ocPublicKey一致。
|
||||
|
||||
clientPublicKey, err := clientKeyGen.Step4(T)
|
||||
assert.Nil(b, err)
|
||||
assert.True(b, clientPublicKey.Equals(osPublicKey))
|
||||
|
||||
e := grand.GetRandom(32)
|
||||
// 签名
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
// 1)客户端发起请求
|
||||
|
||||
// 2)外包方计算
|
||||
b.StartTimer()
|
||||
outsourcintCtx := new(OSSignContext)
|
||||
PPrime, err := outsourcintCtx.Step1(grand.Reader) // P'
|
||||
assert.Nil(b, err)
|
||||
|
||||
// outsourcintCtx把PPrime发给客户端,保存outsourcintCtx.Marshal()
|
||||
|
||||
// 3) 客户端组合数据data = (e,p)=e||px||py并发送给协同服务端
|
||||
b.StopTimer()
|
||||
data := make([]byte, sm3.Size+2*sm2.ByteSize())
|
||||
pos := copy(data, e)
|
||||
pos += copy(data[pos:], gmath.BigIntToNByte(PPrime.X, sm2.ByteSize()))
|
||||
copy(data[pos:], gmath.BigIntToNByte(PPrime.Y, sm2.ByteSize()))
|
||||
|
||||
// 4) 协同服务端计算,发回data
|
||||
b.StartTimer()
|
||||
data, err = sm2m.ServerSign(serverKey, data, grand.Reader)
|
||||
assert.Nil(b, err)
|
||||
|
||||
// 5) 客户端解析data = r || s1 || s2, 把s1, s2发给外包服务器。
|
||||
b.StopTimer()
|
||||
r := new(big.Int)
|
||||
r.SetBytes(data[:sm2.ByteSize()])
|
||||
s1 := new(big.Int).SetBytes(data[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
s2 := new(big.Int).SetBytes(data[2*sm2.ByteSize():])
|
||||
|
||||
// 6) 外包服务器解析data并计算c,把c发送给客户端
|
||||
b.StartTimer()
|
||||
c, err := outsourcintCtx.Step2(s1, s2, encryptedClientKey1, paiPubKey)
|
||||
assert.Nil(b, err)
|
||||
|
||||
// 7) 客户端计算签名值
|
||||
b.StopTimer()
|
||||
s, _ := paillier.Decrypt(c, paiPrivKey)
|
||||
s.Sub(s, r)
|
||||
s.Mod(s, sm2.OrderN())
|
||||
sig := &sm2.Signature{
|
||||
R: r,
|
||||
S: s,
|
||||
}
|
||||
// 8) 客户端验证签名
|
||||
assert.True(b, sm2.Verify(e, publicKey, sig))
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
// osBlindSignContext 外包服务盲协同签名上下文. 使用NewOSBlindSignContext生成.
|
||||
|
||||
// 与盲签名外包服务端一致
|
||||
type OSBlindSignContext struct {
|
||||
OSSignContext
|
||||
}
|
||||
|
||||
func NewOSBlindSignContext() *OSBlindSignContext {
|
||||
return new(OSBlindSignContext)
|
||||
}
|
||||
|
||||
// 盲签名客户端(与JS一致)
|
||||
type clientBlindSignContext struct {
|
||||
pprivateKey *paillier.PrivateKey
|
||||
r *big.Int
|
||||
k1pp *big.Int
|
||||
rnd io.Reader
|
||||
}
|
||||
|
||||
// NewClientBlindSignContext simple factory for creating clientBlindSignContext
|
||||
func NewClientBlindSignContext(pprivateKey *paillier.PrivateKey, rnd io.Reader) *clientBlindSignContext {
|
||||
ctx := &clientBlindSignContext{
|
||||
pprivateKey: pprivateKey,
|
||||
rnd: rnd,
|
||||
}
|
||||
if rnd == nil {
|
||||
ctx.rnd = grand.Reader
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
// Step1 客户端签名第一步 收到外包服务返回的pp, 返回ecipher, p给虎符服务端
|
||||
//
|
||||
// pp是外包服务第一步返回的P'=k1p*G
|
||||
// 返回ecipher = Enc_paillier(e), p = k1p * k2pp * G
|
||||
func (c *clientBlindSignContext) Step1(e []byte, pp *sm2.PublicKey) (ecipher *paillier.Cipher, p *sm2.PublicKey, err error) {
|
||||
c.k1pp, err = rand.Int(c.rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
x, y := sm2.Curve256.ScalarMult(pp.X, pp.Y, c.k1pp.Bytes())
|
||||
|
||||
p = &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}
|
||||
|
||||
ecipher, err = c.pprivateKey.Encrypt(new(big.Int).SetBytes(e), c.rnd)
|
||||
|
||||
return ecipher, p, err
|
||||
}
|
||||
|
||||
// Step2 客户端签名第二步, 收到虎符服务端盲签名接口ServerBlindSign返回的rcipher, s1, s2cipher, 计算s1p, 把s1p, s2p给外包服务
|
||||
func (c *clientBlindSignContext) Step2(rcipher *paillier.Cipher, s1 *big.Int, s2cipher *paillier.Cipher) (s1p *big.Int, s2p *big.Int, err error) {
|
||||
c.r, err = c.pprivateKey.Decrypt(rcipher)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
c.r.Mod(c.r, sm2.OrderN())
|
||||
if c.r.Sign() == 0 {
|
||||
return nil, nil, errors.New("Outsource sign failed, r = 0")
|
||||
}
|
||||
s1p = c.k1pp
|
||||
c.k1pp = nil
|
||||
s1p.Mul(s1p, s1).Mod(s1p, sm2.OrderN())
|
||||
s2p, err = c.pprivateKey.Decrypt(s2cipher)
|
||||
s2p.Mod(s2p, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return s1p, s2p, nil
|
||||
}
|
||||
|
||||
// Step3 客户端签名第三步, 收到外包服务返回的w = Enc(s+r), 输出签名
|
||||
func (c *clientBlindSignContext) Step3(w *paillier.Cipher) (*sm2.Signature, error) {
|
||||
s, err := c.pprivateKey.Decrypt(w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.Sign() == 0 {
|
||||
return nil, errors.New("Outsource sign failed, s = 0")
|
||||
}
|
||||
s.Sub(s, c.r).Mod(s, sm2.OrderN())
|
||||
r := c.r
|
||||
c.r = nil
|
||||
return &sm2.Signature{R: r, S: s}, nil
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
"xdx.jelly/xgcl/tpc/sm2/sm2m"
|
||||
)
|
||||
|
||||
// 外包盲签名流程示例
|
||||
func TestOSBlindSign(t *testing.T) {
|
||||
//O、客户端生成paillier密钥
|
||||
var err error
|
||||
rnd := grand.Reader
|
||||
paiPrivKey, paiPubKey, encryptedClientKey1, _, serverKey, publicKey := osGenerateKey(t)
|
||||
|
||||
e := make([]byte, 32)
|
||||
rnd.Read(e)
|
||||
|
||||
clientCtx := NewClientBlindSignContext(paiPrivKey, rnd)
|
||||
// 1) client -> os
|
||||
|
||||
// 2)os -> client
|
||||
osServerCtx := NewOSBlindSignContext()
|
||||
pp, err := osServerCtx.Step1(rnd) // P'
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3) client -> hfserver
|
||||
ecipher, p, err := clientCtx.Step1(e, pp)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 4) hfserver -> client
|
||||
rcipher, s1, s2cipher, err := sm2m.ServerBlindSign(serverKey, ecipher, p, paiPubKey, rnd)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 5) clinet -> os
|
||||
s1p, s2p, err := clientCtx.Step2(rcipher, s1, s2cipher)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 6) 外包服务器解析data并计算c,把c发送给客户端
|
||||
w, err := osServerCtx.Step2(s1p, s2p, encryptedClientKey1, paiPubKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 7) 客户端计算签名值
|
||||
sig, err := clientCtx.Step3(w)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 8) 客户端验证签名
|
||||
assert.True(t, sm2.Verify(e, publicKey, sig))
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
var nGx = new(big.Int).Set(sm2.BaseX())
|
||||
var nGy = new(big.Int).Sub(sm2.Prime(), sm2.BaseY())
|
||||
|
||||
// OSDecrypt 外包服务器使用签名密钥解密, C1 = (x,y)
|
||||
func OSDecrypt(encryptedKey *paillier.Cipher, paiPubKey *paillier.PublicKey, xC1 *big.Int, yC1 *big.Int, rnd io.Reader) (*paillier.Cipher, *big.Int, *big.Int, error) {
|
||||
var k1, k2 *big.Int
|
||||
var err error
|
||||
for {
|
||||
k1, err = rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if k1.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
for {
|
||||
k2, err = rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if k2.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
xF, yF := sm2.Curve256.ScalarMult(xC1, yC1, k1.Bytes())
|
||||
k1.ModInverse(k1, sm2.OrderN())
|
||||
blind, err := paiPubKey.Encrypt(k2.Mul(k2, sm2.OrderN()), rnd)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
E := new(paillier.Cipher).HomomorphicScalarMul(encryptedKey, k1, paiPubKey)
|
||||
E.HomomorphicAdd(E, blind, paiPubKey)
|
||||
return E, xF, yF, nil
|
||||
}
|
||||
|
||||
type ClientDecContext struct {
|
||||
}
|
||||
|
||||
// 客户端先把(x,y) = C1发送给外包服务器
|
||||
func (*ClientDecContext) Step1(E *paillier.Cipher, xF, yF *big.Int, paiPrivKey *paillier.PrivateKey) (*big.Int, *big.Int, error) {
|
||||
e, err := paiPrivKey.Decrypt(E)
|
||||
e.Mod(e, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
x, y := sm2.Curve256.ScalarMult(xF, yF, e.Bytes())
|
||||
return x, y, nil
|
||||
}
|
||||
|
||||
func (*ClientDecContext) Step2(cipher *sm2.Cipher, x, y *big.Int) ([]byte, error) {
|
||||
ny := new(big.Int).Sub(sm2.Prime(), cipher.Y)
|
||||
xJ, yJ := sm2.Curve256.Add(x, y, cipher.X, ny)
|
||||
return sm2.Decrypt_aux(xJ, yJ, cipher)
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/he/elgamal"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
"xdx.jelly/xgcl/sm/sm3"
|
||||
"xdx.jelly/xgcl/tpc/sm2/sm2m"
|
||||
)
|
||||
|
||||
// 示例ElGamal 不能加入盲化因子。弃用。
|
||||
func TestOutsourceWithElGamal(t *testing.T) {
|
||||
clientKey, clientTempKey, _ := sm2m.ClientGenSignKey_one(grand.Reader)
|
||||
serverKey, serverTempKey, publicKey, _ := sm2m.ServerGenSignKey(clientTempKey, grand.GetRandom(32))
|
||||
err := sm2m.ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
|
||||
if err != nil {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
e := grand.GetRandom(32)
|
||||
|
||||
sk, pk, err := elgamal.GenerateKey(grand.Reader, elgamal.P1024)
|
||||
assert.Nil(t, err)
|
||||
|
||||
encryptedClientKey, err := pk.Encryption(clientKey.D, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 受托方计算
|
||||
k1, err := rand.Int(grand.Reader, sm2.OrderN())
|
||||
assert.Nil(t, err)
|
||||
px, py := sm2.Curve256.ScalarMult(sm2.BaseX(), sm2.BaseY(), k1.Bytes())
|
||||
|
||||
data := make([]byte, sm3.Size+2*sm2.ByteSize())
|
||||
pos := copy(data, e)
|
||||
pos += copy(data[pos:], gmath.BigIntToNByte(px, sm2.ByteSize()))
|
||||
copy(data[pos:], gmath.BigIntToNByte(py, sm2.ByteSize()))
|
||||
|
||||
// data = (e,p) => 协同服务端
|
||||
// 协同服务端计算
|
||||
data, err = sm2m.ServerSign(serverKey, data, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// data = (r||s1||s2)
|
||||
r := new(big.Int)
|
||||
r.SetBytes(data[:sm2.ByteSize()])
|
||||
s1 := new(big.Int).SetBytes(data[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
s2 := new(big.Int).SetBytes(data[2*sm2.ByteSize():])
|
||||
|
||||
// s1, s2 => 受托方
|
||||
s := big.NewInt(0).Mul(k1, s1)
|
||||
s.Add(s, s2)
|
||||
s.Mod(s, sm2.OrderN())
|
||||
|
||||
// 计算 c = Enc(dc*(k1*s1+s2))
|
||||
S, err := pk.Encryption(s, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
c := &elgamal.Cipher{}
|
||||
c, err = c.HomoMap(encryptedClientKey, S)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 加入随机因子?HOW.
|
||||
// k, err := rand.Int(grand.Reader, pk.Param.Q)
|
||||
// assert.Nil(t, err)
|
||||
// nminus1 := new(big.Int).Set(sm2.OrderN())
|
||||
|
||||
// k.Mul(k, nminus1)
|
||||
// k.Mod(k, pk.Param.Q)
|
||||
// k.Exp(pk.Param.G, k, pk.Param.P)
|
||||
// c1, err := pk.Encryption(k, grand.Reader)
|
||||
// assert.Nil(t, err)
|
||||
|
||||
// c.HomoMap(c, c1) // c = Enc(dc*(k1*s1+s2) * g^{K(N-1)})
|
||||
|
||||
// c 发送给委托方
|
||||
// 委托方计算
|
||||
s, err = sk.Decryption(c)
|
||||
assert.Nil(t, err)
|
||||
|
||||
s.Sub(s, r)
|
||||
s.Mod(s, sm2.OrderN())
|
||||
sig := &sm2.Signature{
|
||||
R: r,
|
||||
S: s,
|
||||
}
|
||||
|
||||
if !sm2.Verify(e, publicKey, sig) {
|
||||
t.Fatal("verify failed")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
// 客户端加密clientKey^{-1}给外包服务器保存,用作同态解密密钥
|
||||
func EncryptClientDecKey(clientKey *sm2.PrivateKey, k *paillier.PublicKey, rnd io.Reader) (*paillier.Cipher, error) {
|
||||
d := clientKey.D
|
||||
di := new(big.Int).ModInverse(d, sm2.OrderN())
|
||||
return k.Encrypt(di, rnd)
|
||||
}
|
||||
|
||||
type ClientKeyGenerator struct {
|
||||
dc1, dc1Inv *big.Int
|
||||
}
|
||||
|
||||
// NewClientKeyGen 客户端第一步
|
||||
// 返回数据发送给OS服务端
|
||||
func (c *ClientKeyGenerator) Step1(k *paillier.PublicKey, rnd io.Reader) (*paillier.Cipher, *paillier.Cipher, error) {
|
||||
var d *big.Int
|
||||
var err error
|
||||
for {
|
||||
d, err = rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if d.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
di := new(big.Int).ModInverse(d, sm2.OrderN())
|
||||
c.dc1 = d
|
||||
c.dc1Inv = di
|
||||
|
||||
a1, err := k.Encrypt(d, rnd)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
a2, err := k.Encrypt(di, rnd)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return a1, a2, nil
|
||||
|
||||
}
|
||||
|
||||
// GenerateDataToServer 客户端第二步
|
||||
// 返回的sm2.PublicKey发送给协同签名服务端。
|
||||
func (c *ClientKeyGenerator) Step2(P *sm2.PublicKey) (*sm2.PublicKey, error) {
|
||||
x, y := sm2.Curve256.ScalarMult(P.X, P.Y, c.dc1Inv.Bytes())
|
||||
return &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}, nil
|
||||
}
|
||||
|
||||
// GenerateDataToServer 客户端第三步
|
||||
// 收到协同签名服务端返回数据
|
||||
func (c *ClientKeyGenerator) Step3(R *sm2.PublicKey) (*sm2.PublicKey, error) {
|
||||
x, y := sm2.Curve256.ScalarMult(R.X, R.Y, c.dc1Inv.Bytes())
|
||||
return &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}, nil
|
||||
}
|
||||
|
||||
// GenerateDataToServer 客户端第四步
|
||||
// 收到协同签名服务端返回数据
|
||||
func (c *ClientKeyGenerator) Step4(T1 *sm2.PublicKey) (*sm2.PublicKey, error) {
|
||||
x, y := sm2.Curve256.ScalarMult(T1.X, T1.Y, c.dc1Inv.Bytes())
|
||||
x, y = sm2.Curve256.Add(x, y, nGx, nGy)
|
||||
return &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}, nil
|
||||
}
|
||||
|
||||
// OS服务端
|
||||
type OSKeyGenerator struct {
|
||||
dc2, dc2Inv *big.Int
|
||||
}
|
||||
|
||||
func (o *OSKeyGenerator) Marshal() ([]byte, error) {
|
||||
data := make([]byte, 64)
|
||||
if o.dc2 != nil {
|
||||
gmath.FillBytes(o.dc2, data)
|
||||
}
|
||||
|
||||
if o.dc2Inv != nil {
|
||||
gmath.FillBytes(o.dc2, data[32:])
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (o *OSKeyGenerator) Unmarshal(b []byte) error {
|
||||
if len(b) < 64 {
|
||||
return errors.New("input too short")
|
||||
}
|
||||
o.dc2 = new(big.Int).SetBytes(b[:32])
|
||||
o.dc2Inv = new(big.Int).SetBytes(b[32:64])
|
||||
return nil
|
||||
}
|
||||
|
||||
// OSGenerateKey 外包服务器计算, 返回B1, B2, P
|
||||
// 其中,保存B1, B2, B1用于签名,B2用于解密加密密钥保护结构。
|
||||
// P发送给客户端。
|
||||
func (o *OSKeyGenerator) Step1(a1 *paillier.Cipher, a2 *paillier.Cipher, pk *paillier.PublicKey, rnd io.Reader) (*paillier.Cipher, *paillier.Cipher, *sm2.PublicKey, error) {
|
||||
var d *big.Int
|
||||
var err error
|
||||
for {
|
||||
d, err = rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if d.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
di := new(big.Int).ModInverse(d, sm2.OrderN())
|
||||
o.dc2 = d
|
||||
o.dc2Inv = di
|
||||
|
||||
x, y := sm2.Curve256.ScalarBaseMult(di.Bytes())
|
||||
b1 := new(paillier.Cipher).HomomorphicScalarMul(a1, d, pk)
|
||||
b2 := new(paillier.Cipher).HomomorphicScalarMul(a2, di, pk)
|
||||
return b1, b2, &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}, nil
|
||||
}
|
||||
|
||||
func (o *OSKeyGenerator) Step2(R *sm2.PublicKey, S *sm2.PublicKey) (*sm2.PublicKey, *sm2.PublicKey, error) {
|
||||
x1, y1 := sm2.Curve256.ScalarMult(R.X, R.Y, o.dc2Inv.Bytes())
|
||||
x2, y2 := sm2.Curve256.ScalarMult(S.X, S.Y, o.dc2Inv.Bytes())
|
||||
x, y := sm2.Curve256.Add(x2, y2, nGx, nGy)
|
||||
return &sm2.PublicKey{Curve: sm2.Curve(), X: x1, Y: y1}, &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}, nil
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
// 外包服务计算
|
||||
|
||||
type OSSignContext struct {
|
||||
k1p *big.Int
|
||||
}
|
||||
|
||||
func NewOSSignContext() *OSSignContext {
|
||||
return &OSSignContext{}
|
||||
}
|
||||
|
||||
// Step1 需要临时保存k1
|
||||
func (o *OSSignContext) Step1(rnd io.Reader) (pp *sm2.PublicKey, err error) {
|
||||
for {
|
||||
k, err := rand.Int(rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if k.Sign() == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
x, y := sm2.Curve256.ScalarBaseMult(k.Bytes())
|
||||
|
||||
o.k1p = k
|
||||
pp = &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}
|
||||
return pp, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Step2 input s1 in [1, N-1]
|
||||
func (o *OSSignContext) Step2(s1 *big.Int, s2 *big.Int, encryptedKey *paillier.Cipher, evalKey *paillier.PublicKey) (w *paillier.Cipher, err error) {
|
||||
if o.k1p == nil || o.k1p.Sign() == 0 {
|
||||
return nil, errors.New("call Prepare first")
|
||||
}
|
||||
if s1 == nil || s2 == nil {
|
||||
return nil, errors.New("s1 or s2 is nil")
|
||||
}
|
||||
|
||||
// s1, s2不能为0 mod n, 否则外包服务可能被套取到用户的密钥.
|
||||
if s1.Sign() <= 0 || s1.Cmp(sm2.OrderN()) >= 0 || s2.Sign() <= 0 || s2.Cmp(sm2.OrderN()) >= 0 {
|
||||
return nil, errors.New("s1 or s2 not in range [1, N-1]")
|
||||
}
|
||||
|
||||
s := new(big.Int).Mul(o.k1p, s1)
|
||||
s.Add(s, s2).Mod(s, sm2.OrderN()) // s = k*s1 + s2 mod N
|
||||
|
||||
// check s = 0?
|
||||
|
||||
// 计算 w = encryptedClientKey^s mod n^2 = Enc(ds * s)
|
||||
w = (&paillier.Cipher{}).HomomorphicScalarMul(encryptedKey, s, evalKey)
|
||||
|
||||
// blind the result
|
||||
if true {
|
||||
k, err := rand.Int(grand.Reader, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k.Mul(k, sm2.OrderN())
|
||||
w.HomomorphicAddInt(w, k, evalKey)
|
||||
} else {
|
||||
kn, err := rand.Int(grand.Reader, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kn.Mul(kn, sm2.OrderN())
|
||||
blind, err := paillier.Encrypt(kn, evalKey, grand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.HomomorphicAdd(w, blind, evalKey) // c = Enc(dc*(k1*s1+s2) + k*N)
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// outsourcingContext 需要序列化后保存到redis中
|
||||
func (o *OSSignContext) Marshal() ([]byte, error) {
|
||||
buf := make([]byte, sm2.ByteSize())
|
||||
return o.k1p.FillBytes(buf), nil
|
||||
}
|
||||
|
||||
func (o *OSSignContext) Unmarshal(b []byte) error {
|
||||
if len(b) != sm2.ByteSize() {
|
||||
return errors.New("input data invalid")
|
||||
}
|
||||
if o.k1p == nil {
|
||||
o.k1p = new(big.Int)
|
||||
}
|
||||
o.k1p.SetBytes(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clientSignContext 外包服务客户端(与JS的outsource.ClientSigner一致)
|
||||
type clientSignContext struct {
|
||||
pprivateKey *paillier.PrivateKey
|
||||
r *big.Int
|
||||
k1pp *big.Int
|
||||
rnd io.Reader
|
||||
}
|
||||
|
||||
// NewClientSignContext simple factory for creating clientSignContext.
|
||||
func NewClientSignContext(pprivateKey *paillier.PrivateKey, rnd io.Reader) *clientSignContext {
|
||||
ctx := &clientSignContext{
|
||||
pprivateKey: pprivateKey,
|
||||
rnd: rnd,
|
||||
}
|
||||
if rnd == nil {
|
||||
ctx.rnd = grand.Reader
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
// Step1 客户端签名第一步 返回p给虎符服务端
|
||||
//
|
||||
// pp是外包服务第一步返回的P'=k1p*G
|
||||
// 返回p = k1p * k2pp * G
|
||||
func (c *clientSignContext) Step1(e []byte, pp *sm2.PublicKey) (p *sm2.PublicKey, err error) {
|
||||
c.k1pp, err = rand.Int(c.rnd, sm2.OrderN())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x, y := sm2.Curve256.ScalarMult(pp.X, pp.Y, c.k1pp.Bytes())
|
||||
|
||||
p = &sm2.PublicKey{Curve: sm2.Curve(), X: x, Y: y}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Step2 客户端签名第二步, 收到虎符服务端返回的r, s1, s2, 计算s1p, 把s1p, s2p给外包服务
|
||||
func (c *clientSignContext) Step2(r *big.Int, s1 *big.Int, s2 *big.Int) (s1p *big.Int, s2p *big.Int, err error) {
|
||||
c.r = r
|
||||
if r.Sign() == 0 {
|
||||
return nil, nil, errors.New("Outsource sign failed, r = 0")
|
||||
}
|
||||
s1p = c.k1pp
|
||||
c.k1pp = nil
|
||||
s1p.Mul(s1p, s1).Mod(s1p, sm2.OrderN())
|
||||
s2p = s2
|
||||
return s1p, s2p, nil
|
||||
}
|
||||
|
||||
// Step3 客户端签名第三步, 收到外包服务返回的w = Enc(s+r), 输出签名
|
||||
func (c *clientSignContext) Step3(w *paillier.Cipher) (*sm2.Signature, error) {
|
||||
s, err := c.pprivateKey.Decrypt(w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.Sign() == 0 {
|
||||
return nil, errors.New("Outsource sign failed, s = 0")
|
||||
}
|
||||
s.Sub(s, c.r).Mod(s, sm2.OrderN())
|
||||
r := c.r
|
||||
c.r = nil
|
||||
return &sm2.Signature{R: r, S: s}, nil
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
package outsource
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/he/paillier"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
"xdx.jelly/xgcl/sm/sm3"
|
||||
"xdx.jelly/xgcl/tpc/sm2/sm2m"
|
||||
)
|
||||
|
||||
// osGenerateKey 客户端,外包,服务端协同密钥生成
|
||||
func osGenerateKey(t *testing.T) (*paillier.PrivateKey, *paillier.PublicKey, *paillier.Cipher, *paillier.Cipher, *sm2.PrivateKey, *sm2.PublicKey) {
|
||||
rnd := grand.Reader
|
||||
salt := []byte("12345678")
|
||||
paiPrivKey, err := paillier.GenerateKeyFromPassword(2048, []byte("password123"), salt, 1024)
|
||||
assert.Nil(t, err)
|
||||
paiPubKey := paiPrivKey.Public()
|
||||
|
||||
// 一、密钥生成
|
||||
|
||||
// 1)客户端第一步, a1, a2 发 外包服务器
|
||||
clientKeyGen := &ClientKeyGenerator{}
|
||||
a1, a2, err := clientKeyGen.Step1(paiPubKey, rnd)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 2) 外包服务器第一步
|
||||
// 保存encryptedClientKey1,encryptedClientKey2,
|
||||
// 把 P 发客户端
|
||||
// encryptedClientKey1 -签名用
|
||||
// encryptedClientKey2 -解密加密密钥保护结构用
|
||||
osKenGen := &OSKeyGenerator{}
|
||||
encryptedClientKey1, encryptedClientKey2, P, err := osKenGen.Step1(a1, a2, paiPubKey, rnd)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3) 客户端第二步
|
||||
// clientTempKey发协同签名服务端
|
||||
clientTempKey, err := clientKeyGen.Step2(P)
|
||||
|
||||
// 4)协同签名服务器
|
||||
// serverTempKey 发客户端,保存serverKey-服务端密钥分量
|
||||
b := make([]byte, 32)
|
||||
rnd.Read(b)
|
||||
serverKey, serverTempKey, publicKey, _ := sm2m.ServerGenSignKey(clientTempKey, b)
|
||||
|
||||
// 5)客户端第三步
|
||||
// 把(serverTempKey,S)发送给外包服务器
|
||||
S, err := clientKeyGen.Step3(serverTempKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 6)外包服务器第二步
|
||||
// 把T, osPublicKey发给客户端。保存osPublicKey为用户签名公钥
|
||||
T, osPublicKey, err := osKenGen.Step2(serverTempKey, S)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 7)客户端第四步
|
||||
// clientPublicKey, 客户端生成的公钥,如果没有返错,则应与ocPublicKey一致。
|
||||
clientPublicKey, err := clientKeyGen.Step4(T)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, clientPublicKey.Equals(osPublicKey))
|
||||
|
||||
return paiPrivKey, paiPubKey, encryptedClientKey1, encryptedClientKey2, serverKey, publicKey
|
||||
}
|
||||
|
||||
// 外包签名流程
|
||||
func TestOSSign(t *testing.T) {
|
||||
//O、生成密钥
|
||||
var err error
|
||||
rnd := grand.Reader
|
||||
paiPrivKey, paiPubKey, encryptedClientKey1, _, serverKey, publicKey := osGenerateKey(t)
|
||||
|
||||
e := make([]byte, 32)
|
||||
rnd.Read(e)
|
||||
|
||||
clientCtx := NewClientSignContext(paiPrivKey, rnd)
|
||||
// 1) client -> os
|
||||
|
||||
// 2)os -> client
|
||||
osServerCtx := NewOSSignContext()
|
||||
pp, err := osServerCtx.Step1(rnd) // P'
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3) client -> hfserver
|
||||
p, err := clientCtx.Step1(e, pp)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 组合数据data = (e,p)=e||px||py并发送给协同服务端
|
||||
data := make([]byte, sm3.Size+2*sm2.ByteSize())
|
||||
pos := copy(data, e)
|
||||
pos += copy(data[pos:], gmath.BigIntToNByte(p.X, sm2.ByteSize()))
|
||||
copy(data[pos:], gmath.BigIntToNByte(p.Y, sm2.ByteSize()))
|
||||
|
||||
// 4) hfserver -> client
|
||||
data, err = sm2m.ServerSign(serverKey, data, rnd)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 5) clinet -> os
|
||||
// 解析数据
|
||||
r := new(big.Int).SetBytes(data[:sm2.ByteSize()])
|
||||
s1 := new(big.Int).SetBytes(data[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
s2 := new(big.Int).SetBytes(data[2*sm2.ByteSize():])
|
||||
|
||||
s1p, s2p, err := clientCtx.Step2(r, s1, s2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 6) 外包服务器解析data并计算c,把c发送给客户端
|
||||
w, err := osServerCtx.Step2(s1p, s2p, encryptedClientKey1, paiPubKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 7) 客户端计算签名值
|
||||
sig, err := clientCtx.Step3(w)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 8) 客户端验证签名
|
||||
assert.True(t, sm2.Verify(e, publicKey, sig))
|
||||
}
|
||||
|
||||
// 外包计算完整流程示例
|
||||
// deprecated: 签名的客户端第3和第5步有遗失. 签名见上面的流程TestOSSign. 相当于客户端选择了随机数k1” = 1.
|
||||
func TestOutsourceWithPaillier(t *testing.T) {
|
||||
//O、客户端生成paillier密钥
|
||||
var err error
|
||||
paiPrivKey, paiPubKey, encryptedClientKey1, encryptedClientKey2, serverKey, publicKey := osGenerateKey(t)
|
||||
|
||||
// 外包服务收到客户端发来的同态公钥
|
||||
paiPubKeyClientData, _ := paiPubKey.Marshal()
|
||||
paiPubKey = new(paillier.PublicKey)
|
||||
err = paiPubKey.Unmarshal(paiPubKeyClientData)
|
||||
|
||||
// 外包服务将公钥数据paiPubKeyServerData存储数据库中, 包括预计算数据.
|
||||
paiPubKeyServerData, _ := paiPubKey.MarshalExt()
|
||||
|
||||
// 外包服务从数据库中恢复用户的同态公钥, 用于外包同态计算.
|
||||
_ = paiPubKey.UnmarshalExt(paiPubKeyServerData)
|
||||
|
||||
rnd := grand.Reader
|
||||
|
||||
_, _ = encryptedClientKey1, rnd
|
||||
/*
|
||||
// 二、签名
|
||||
|
||||
// 1)客户端发起请求
|
||||
e := make([]byte, 32)
|
||||
rnd.Read(e)
|
||||
|
||||
// 2)外包方计算
|
||||
outsourcintCtx := new(OSSignContext)
|
||||
PPrime, err := outsourcintCtx.Step1(rnd) // P'
|
||||
assert.Nil(t, err)
|
||||
|
||||
// outsourcintCtx把PPrime发给客户端,保存outsourcintCtx.Marshal()
|
||||
|
||||
// 3) 客户端组合数据data = (e,p)=e||px||py并发送给协同服务端
|
||||
data := make([]byte, sm3.Size+2*sm2.ByteSize())
|
||||
pos := copy(data, e)
|
||||
pos += copy(data[pos:], gmath.BigIntToNByte(PPrime.X, sm2.ByteSize()))
|
||||
copy(data[pos:], gmath.BigIntToNByte(PPrime.Y, sm2.ByteSize()))
|
||||
|
||||
// 4) 协同服务端计算,发回data
|
||||
data, err = sm2m.ServerSign(serverKey, data, rnd)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 5) 客户端解析data = r || s1 || s2, 把s1, s2发给外包服务器。
|
||||
r := new(big.Int)
|
||||
r.SetBytes(data[:sm2.ByteSize()])
|
||||
s1 := new(big.Int).SetBytes(data[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
s2 := new(big.Int).SetBytes(data[2*sm2.ByteSize():])
|
||||
|
||||
// 6) 外包服务器解析data并计算c,把c发送给客户端
|
||||
c, err := outsourcintCtx.Step2(s1, s2, encryptedClientKey1, paiPubKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 7) 客户端计算签名值
|
||||
s, _ := paillier.Decrypt(c, paiPrivKey)
|
||||
s.Sub(s, r)
|
||||
s.Mod(s, sm2.OrderN())
|
||||
sig := &sm2.Signature{
|
||||
R: r,
|
||||
S: s,
|
||||
}
|
||||
|
||||
// 8) 客户端验证签名
|
||||
assert.True(t, sm2.Verify(e, publicKey, sig))
|
||||
*/
|
||||
|
||||
// 三、使用签名密钥解密
|
||||
plaintext := grand.GetRandom(16)
|
||||
cipher, err := sm2.Encrypt(publicKey, plaintext, grand.GetRandom(32))
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 1) 客户端把(x,y)=C1 发送给外包服务器
|
||||
// 2)外包服务计算, 把paiCipher, xF, yF发送给客户端
|
||||
paiCipher, xF, yF, err := OSDecrypt(encryptedClientKey2, paiPubKey, cipher.X, cipher.Y, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3) 客户端计算
|
||||
clientDecCtx := &ClientDecContext{}
|
||||
xH, yH, err := clientDecCtx.Step1(paiCipher, xF, yF, paiPrivKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 4) 协同签名服务器计算
|
||||
inData := make([]byte, 2*sm2.ByteSize())
|
||||
xH.FillBytes(inData[:sm2.ByteSize()])
|
||||
yH.FillBytes(inData[sm2.ByteSize():])
|
||||
outData, err := sm2m.ServerDec(serverKey, inData)
|
||||
|
||||
// 5) 客户端计算
|
||||
x := new(big.Int).SetBytes(outData[:sm2.ByteSize()])
|
||||
y := new(big.Int).SetBytes(outData[sm2.ByteSize():])
|
||||
decPlain, err := clientDecCtx.Step2(cipher, x, y)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, bytes.Equal(plaintext, decPlain))
|
||||
|
||||
// 四、解密密钥分拆
|
||||
// 假设客户端解密得到的解密密钥de
|
||||
de, err := sm2.GenerateKey(sm2.Curve(), grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 客户端分拆解密密钥, deServer给协同签名服务端
|
||||
deClient, deServer, err := sm2m.SplitDecryptKey(de, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 加密deClient给外包服务端保存。
|
||||
encryptedEncKey, err := EncryptClientDecKey(deClient, paiPubKey, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 五、使用解密密钥解密(同使用签名密钥解密)
|
||||
plaintext = grand.GetRandom(16)
|
||||
cipher, err = sm2.Encrypt(&de.PublicKey, plaintext, grand.GetRandom(32))
|
||||
assert.Nil(t, err)
|
||||
|
||||
// (一)对比非OS的协同解密
|
||||
clientCTX := sm2m.NewClientDecContext()
|
||||
out, _ := clientCTX.Initial(cipher)
|
||||
out, _ = sm2m.ServerDec(deServer, out)
|
||||
decPlain, _ = clientCTX.Final(deClient, out)
|
||||
assert.True(t, bytes.Equal(plaintext, decPlain))
|
||||
|
||||
// (二)OS解密
|
||||
|
||||
// 1) 客户端把(x,y)=C1 发送给外包服务器
|
||||
// 2)外包服务计算, 把paiCipher, xF, yF发送给客户端
|
||||
paiCipher, xF, yF, err = OSDecrypt(encryptedEncKey, paiPubKey, cipher.X, cipher.Y, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3) 客户端计算
|
||||
clientDecCtx = &ClientDecContext{}
|
||||
xH, yH, err = clientDecCtx.Step1(paiCipher, xF, yF, paiPrivKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 4) 协同签名服务器计算
|
||||
inData = make([]byte, 2*sm2.ByteSize())
|
||||
xH.FillBytes(inData[:sm2.ByteSize()])
|
||||
yH.FillBytes(inData[sm2.ByteSize():])
|
||||
outData, err = sm2m.ServerDec(deServer, inData)
|
||||
|
||||
// 5) 客户端计算
|
||||
x = new(big.Int).SetBytes(outData[:sm2.ByteSize()])
|
||||
y = new(big.Int).SetBytes(outData[sm2.ByteSize():])
|
||||
decPlain, err = clientDecCtx.Step2(cipher, x, y)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, bytes.Equal(plaintext, decPlain))
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
"xdx.jelly/xgcl/sm/sm2/ec256"
|
||||
"xdx.jelly/xgcl/sm/sm3"
|
||||
)
|
||||
|
||||
type ClientSignContext struct {
|
||||
k1 *big.Int
|
||||
rand io.Reader
|
||||
}
|
||||
|
||||
// NewClientSignContext 生成客户端协同签名上下文
|
||||
// pk没有用,可以传nil, rnd是随机数发生器.
|
||||
// 注: pk实际是用来验证完成后的签名. 这里由调用者自己验证即可.
|
||||
func NewClientSignContext(pk *sm2.PublicKey, rnd io.Reader) *ClientSignContext {
|
||||
c := &ClientSignContext{
|
||||
k1: new(big.Int),
|
||||
rand: rnd,
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
/*
|
||||
a) 客户端选择随机数k1 in [1, n - 1],计算e = SM3(Z || M), P = [k1]G,
|
||||
其中Z为32字节杂凑值,G为基点,向服务端发送签名请求
|
||||
同时将out = e, P加密为发送给服务端。
|
||||
*/
|
||||
func (c *ClientSignContext) Initial(e []byte) (out []byte, 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, err
|
||||
}
|
||||
c.k1.SetBytes(buf)
|
||||
c.k1.Mod(c.k1, sm2.OrderN())
|
||||
|
||||
x, y := sm2.Curve256.ScalarMult(sm2.BaseX(), sm2.BaseY(), 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
|
||||
}
|
||||
|
||||
/*
|
||||
c) 客户端计算s= d1(k1s1+s2) - r mod n,并检查s,r+s是否为0 mod q。
|
||||
对消息M的签名为(r,s),客户端可验证签名是否正确。
|
||||
*/
|
||||
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).SetBytes(in[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
s2 := new(big.Int).SetBytes(in[2*sm2.ByteSize():])
|
||||
s1.Mul(s1, c.k1)
|
||||
s1.Add(s1, s2)
|
||||
s1.Mod(s1, sm2.OrderN())
|
||||
s1.Mul(s1, clientKey.D)
|
||||
s1.Sub(s1, sig.R)
|
||||
s1.Mod(s1, sm2.OrderN())
|
||||
sig.S.Set(s1)
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
/*
|
||||
b)
|
||||
in = e || P
|
||||
服务端生成随机数k2, k3 in [1,n-1],(k = k1 * k2 + k3)
|
||||
计算(x1,y1)=[k2]P+[k3]G, r=e+x1 mod n ,
|
||||
检查r是否为0,为0则重新生成k2,重新计算。
|
||||
计算s1=k2d2 mod n, s2=d2(k3+r) mod n,
|
||||
输出 r || s1 || s2
|
||||
*/
|
||||
func ServerSign(serverKey *sm2.PrivateKey, in []byte, rand io.Reader) ([]byte, error) {
|
||||
|
||||
k2 := make([]byte, sm2.ByteSize())
|
||||
if n, err := rand.Read(k2); n != len(k2) || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k3 := make([]byte, sm2.ByteSize())
|
||||
if n, err := rand.Read(k3); n != len(k3) || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := new(big.Int).SetBytes(in[:sm2.ByteSize()])
|
||||
px := new(big.Int).SetBytes(in[sm2.ByteSize() : 2*sm2.ByteSize()])
|
||||
py := new(big.Int).SetBytes(in[2*sm2.ByteSize() : 3*sm2.ByteSize()])
|
||||
// x1, _ := sm2.Curve().CombinedMult(px, py, k3, k2)
|
||||
x1, _ := ec256.CombinedMult(px, py, k3, k2)
|
||||
|
||||
r.Add(r, x1)
|
||||
r.Mod(r, sm2.OrderN())
|
||||
|
||||
if gmath.IsBigInt0(r) {
|
||||
return nil, fmt.Errorf("rebuild")
|
||||
}
|
||||
|
||||
out := make([]byte, 0, 3*sm2.ByteSize())
|
||||
out = append(out, gmath.BigIntToNByte(r, sm2.ByteSize())...)
|
||||
|
||||
s := new(big.Int).SetBytes(k2)
|
||||
s.Mul(s, serverKey.D)
|
||||
s.Mod(s, sm2.OrderN())
|
||||
out = append(out, gmath.BigIntToNByte(s, sm2.ByteSize())...)
|
||||
|
||||
s.SetBytes(k3)
|
||||
s.Add(s, r)
|
||||
s.Mul(s, serverKey.D)
|
||||
s.Mod(s, sm2.OrderN())
|
||||
out = append(out, gmath.BigIntToNByte(s, sm2.ByteSize())...)
|
||||
|
||||
return out, nil
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package sm2m
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
|
||||
rnd := make([]byte, 32)
|
||||
clientKey, clientTempKey, _ := ClientGenSignKey_one(nil)
|
||||
_, _ = grand.GenerateRandom(rnd)
|
||||
serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, rnd)
|
||||
err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
|
||||
if err != nil {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
|
||||
d := realPrivateKey(serverKey, clientKey)
|
||||
if !publicKey.Equals(&d.PublicKey) {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
|
||||
fmt.Println("clientKey:", clientKey)
|
||||
fmt.Println("serverKey:", serverKey)
|
||||
|
||||
// c := NewClientSignContext(pk, grand.Reader)
|
||||
c := new(ClientSignContext)
|
||||
e := make([]byte, 32)
|
||||
out, err := c.Initial(e)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fmt.Printf("clientData: %x\n", out)
|
||||
out, err = ServerSign(serverKey, out, grand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("serverData: %x\n", out)
|
||||
sig, err := c.Final(clientKey, out)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fmt.Println(sig)
|
||||
|
||||
if !sm2.Verify(e, publicKey, sig) {
|
||||
t.Fatal("verify failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignFuzz(t *testing.T) {
|
||||
|
||||
rnd := make([]byte, 32)
|
||||
_, _ = grand.GenerateRandom(rnd)
|
||||
|
||||
clientKey, clientTempKey, _ := ClientGenSignKey_one(rnd)
|
||||
_, _ = grand.GenerateRandom(rnd)
|
||||
serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, rnd)
|
||||
err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
|
||||
if err != nil {
|
||||
t.Fatal("client's public key and server's public key are not equal.")
|
||||
}
|
||||
fmt.Println("clientKey:", clientKey)
|
||||
fmt.Println("serverKey:", serverKey)
|
||||
|
||||
for i := 0; i < 10000000; i++ {
|
||||
// c := NewClientSignContext(pk, grand.Reader)
|
||||
c := new(ClientSignContext)
|
||||
e := make([]byte, 32)
|
||||
_, _ = grand.GenerateRandom(e)
|
||||
|
||||
out, err := c.Initial(e)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, err = ServerSign(serverKey, out, grand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sig, err := c.Final(clientKey, out)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !sm2.Verify(e, publicKey, sig) {
|
||||
fmt.Printf("e=%x\n", e)
|
||||
t.Fatal("verify failed")
|
||||
}
|
||||
if i > 0 && i%1000 == 0 {
|
||||
fmt.Println(i, " pass")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user