init: v1.0.0
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
package sm9m
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/grand/drng"
|
||||
"xdx.jelly/xgcl/sm/sm3"
|
||||
"xdx.jelly/xgcl/sm/sm9"
|
||||
)
|
||||
|
||||
func TestAuditSign(t *testing.T) {
|
||||
uid := []byte("Alice")
|
||||
|
||||
ks, pubs, err := sm9.GenerateMastSignPrivateKey(drng.SM3Rng) // use SM3 DRNG
|
||||
assert.Nil(t, err)
|
||||
fmt.Printf("签名主公私钥: %x\n", ks.Bytes())
|
||||
fmt.Printf("签名主公钥: %x\n", pubs.Bytes())
|
||||
|
||||
ds, err := ks.GenerateUserSignKey(uid)
|
||||
assert.Nil(t, err)
|
||||
|
||||
clientSignKey, serverSignKey, err := GenerateSignKeys(ds, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
fmt.Printf("签名公钥: %x\n", uid)
|
||||
fmt.Printf("客户端密钥: %x\n", clientSignKey.p.Marshal())
|
||||
fmt.Printf("服务端密钥: %x\n", serverSignKey.k.Bytes())
|
||||
|
||||
// SM9签名输入SM3摘要
|
||||
msg := grand.GetRandom(32)
|
||||
fmt.Printf("签名原文: %x\n", msg)
|
||||
hash := sm3.Sum(msg)
|
||||
|
||||
// 客户端第一步
|
||||
clientCTX := &ClientSignContext{}
|
||||
param, err := clientCTX.GenerateParam(clientSignKey, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
b, err := param.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 服务端
|
||||
param = &ClientSignParam{}
|
||||
assert.Nil(t, param.UnmarshalBinary(b))
|
||||
serverParam, err := ServerSign(hash[:], param, serverSignKey, pubs, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
b, err = serverParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 客户端第二步
|
||||
serverParam = &ServerSignParam{}
|
||||
assert.Nil(t, serverParam.UnmarshalBinary(b))
|
||||
sig, err := clientCTX.GenerateSignature(serverParam)
|
||||
assert.Nil(t, err)
|
||||
fmt.Printf("签名结果: %x\n", sig.Bytes())
|
||||
|
||||
assert.True(t, sm9.Verify(sig, uid, hash[:], pubs))
|
||||
}
|
||||
|
||||
func TestAuditDec(t *testing.T) {
|
||||
|
||||
uid := []byte("Alice")
|
||||
|
||||
ke, pube, err := sm9.GenerateMastEncPrivateKey(drng.SM3Rng) // use SM3 DRNG
|
||||
assert.Nil(t, err)
|
||||
fmt.Printf("加密主公私钥: %x\n", ke.Bytes())
|
||||
fmt.Printf("加密主公钥: %x\n", pube.Bytes())
|
||||
|
||||
de, err := ke.GenerateUserEncKey(uid)
|
||||
assert.Nil(t, err)
|
||||
|
||||
clientEncKey, serverEncKey, err := GenerateEncKeys(de, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
fmt.Printf("签名公钥: %x\n", uid)
|
||||
fmt.Printf("客户端密钥: %x\n", clientEncKey.p.Marshal())
|
||||
fmt.Printf("服务端密钥: %x\n", serverEncKey.p.Marshal())
|
||||
{
|
||||
|
||||
fmt.Println("===== SM9协同解密 =====")
|
||||
msg := grand.GetRandom(32)
|
||||
fmt.Printf("原文: %x\n", msg)
|
||||
cipher, err := sm9.Encrypt(sm9.EncTypeKDF, pube, uid, msg, drng.SM3Rng, nil)
|
||||
assert.Nil(t, err)
|
||||
b, _ := cipher.MarshalBinary()
|
||||
fmt.Printf("加密密文: %x\n", b)
|
||||
|
||||
// 1
|
||||
clientCTX := &ClientDecContext{}
|
||||
clientParam, err := clientCTX.GenerateParam(cipher)
|
||||
assert.Nil(t, err)
|
||||
b, err = clientParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 2
|
||||
clientParam = &ClientDecParam{}
|
||||
assert.Nil(t, clientParam.UnmarshalBinary(b))
|
||||
serverParam, err := ServerDecrypt(clientParam, serverEncKey)
|
||||
assert.Nil(t, err)
|
||||
b, err = serverParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3
|
||||
serverParam = &ServerDecParam{}
|
||||
assert.Nil(t, serverParam.UnmarshalBinary(b))
|
||||
msg1, err := clientCTX.DecryptFinal(uid, clientEncKey, serverParam)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, msg, msg1)
|
||||
fmt.Printf("解密明文: %x\n", msg1)
|
||||
}
|
||||
|
||||
fmt.Println("===== SM9协同解封装 =====")
|
||||
|
||||
{
|
||||
keylen := 48
|
||||
pack, key0, err := sm9.KeyEncapsulate(uid, keylen, pube, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
fmt.Printf("封装密文: %x\n", pack.Marshal())
|
||||
fmt.Printf("封装密钥: %x\n", key0)
|
||||
|
||||
// 1
|
||||
clientCTX := &ClientDecapsulateContext{}
|
||||
clientParam, err := clientCTX.GenerateParam(pack)
|
||||
assert.Nil(t, err)
|
||||
b, err := clientParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 2
|
||||
clientParam = &ClientDecapsulateParam{}
|
||||
assert.Nil(t, clientParam.UnmarshalBinary(b))
|
||||
serverParam, err := ServerDecapsulate(clientParam, serverEncKey)
|
||||
assert.Nil(t, err)
|
||||
b, err = serverParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3
|
||||
serverParam = &ServerDecapsulateParam{}
|
||||
assert.Nil(t, serverParam.UnmarshalBinary(b))
|
||||
key1, err := clientCTX.DecapsulateFinal(uid, keylen, clientEncKey, serverParam)
|
||||
assert.Nil(t, err)
|
||||
|
||||
fmt.Printf("解封装密钥: %x\n", key1)
|
||||
|
||||
assert.Equal(t, key0, key1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package sm9m
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
|
||||
"xdx.jelly/xgcl/sm/sm9"
|
||||
)
|
||||
|
||||
type ClientDecContext struct {
|
||||
cipher *sm9.Cipher
|
||||
}
|
||||
|
||||
type ClientDecParam struct {
|
||||
c1 sm9.G1 // cipher.C1
|
||||
}
|
||||
|
||||
type ServerDecParam struct {
|
||||
e sm9.GT // e(C, Ks)
|
||||
}
|
||||
|
||||
func (ctx *ClientDecContext) GenerateParam(c *sm9.Cipher) (*ClientDecParam, error) {
|
||||
if !c.C1.IsValid() {
|
||||
return nil, ErrInvalidCipherC1
|
||||
}
|
||||
ctx.cipher = c
|
||||
param := &ClientDecParam{}
|
||||
param.c1.Set(&c.C1)
|
||||
return param, nil
|
||||
}
|
||||
|
||||
func (ctx *ClientDecContext) DecryptFinal(id []byte, clientEncKey *EncKeyClient, param *ServerDecParam) ([]byte, error) {
|
||||
w := sm9.Pairing(&ctx.cipher.C1, &clientEncKey.p)
|
||||
w.Mul(w, ¶m.e) // e = e(C1, de)
|
||||
|
||||
c := ctx.cipher
|
||||
keylen, f, err := sm9.DecryptParams(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := make([]byte, keylen)
|
||||
_ = sm9.Kdf(key, c.C1.Marshal(), w.Marshal(), id)
|
||||
return sm9.DecodeCipher(c, key, f)
|
||||
}
|
||||
|
||||
func ServerDecrypt(clientParam *ClientDecParam, serverEncKey *EncKeyServer) (*ServerDecParam, error) {
|
||||
if !clientParam.c1.IsValid() {
|
||||
return nil, ErrInvalidCipherC1
|
||||
}
|
||||
|
||||
w := sm9.Pairing(&clientParam.c1, &serverEncKey.p)
|
||||
return &ServerDecParam{e: *w}, nil
|
||||
}
|
||||
|
||||
var _ encoding.BinaryMarshaler = &ClientDecParam{}
|
||||
var _ encoding.BinaryUnmarshaler = &ClientDecParam{}
|
||||
|
||||
var _ encoding.BinaryMarshaler = &ServerDecParam{}
|
||||
var _ encoding.BinaryUnmarshaler = &ServerDecParam{}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (p *ClientDecParam) MarshalBinary() (data []byte, err error) {
|
||||
return p.c1.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (p *ClientDecParam) UnmarshalBinary(data []byte) error {
|
||||
_, err := p.c1.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (p *ServerDecParam) MarshalBinary() (data []byte, err error) {
|
||||
return p.e.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (p *ServerDecParam) UnmarshalBinary(data []byte) error {
|
||||
_, err := p.e.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package sm9m
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
|
||||
"xdx.jelly/xgcl/sm/sm9"
|
||||
)
|
||||
|
||||
// SM9协同密钥解封装
|
||||
|
||||
type ClientDecapsulateContext struct {
|
||||
pack *sm9.KeyPackage
|
||||
}
|
||||
|
||||
type ClientDecapsulateParam struct {
|
||||
c sm9.G1
|
||||
}
|
||||
|
||||
type ServerDecapsulateParam struct {
|
||||
e sm9.GT // e(C, Ks)
|
||||
}
|
||||
|
||||
func (ctx *ClientDecapsulateContext) GenerateParam(pack *sm9.KeyPackage) (*ClientDecapsulateParam, error) {
|
||||
if !pack.G1.IsValid() {
|
||||
return nil, ErrInvalidCipherC1
|
||||
}
|
||||
ctx.pack = pack
|
||||
param := &ClientDecapsulateParam{}
|
||||
param.c.Set(&pack.G1)
|
||||
return param, nil
|
||||
}
|
||||
|
||||
func (ctx *ClientDecapsulateContext) DecapsulateFinal(id []byte, keylen int, clientEncKey *EncKeyClient, param *ServerDecapsulateParam) ([]byte, error) {
|
||||
w := sm9.Pairing(&ctx.pack.G1, &clientEncKey.p)
|
||||
w.Mul(w, ¶m.e) // e = e(C1, de)
|
||||
|
||||
key := make([]byte, keylen)
|
||||
_ = sm9.Kdf(key, ctx.pack.G1.Marshal(), w.Marshal(), id)
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func ServerDecapsulate(clientParam *ClientDecapsulateParam, serverEncKey *EncKeyServer) (*ServerDecapsulateParam, error) {
|
||||
if !clientParam.c.IsValid() {
|
||||
return nil, ErrInvalidCipherC1
|
||||
}
|
||||
|
||||
w := sm9.Pairing(&clientParam.c, &serverEncKey.p)
|
||||
return &ServerDecapsulateParam{e: *w}, nil
|
||||
}
|
||||
|
||||
var _ encoding.BinaryMarshaler = &ClientDecapsulateParam{}
|
||||
var _ encoding.BinaryUnmarshaler = &ClientDecapsulateParam{}
|
||||
|
||||
var _ encoding.BinaryMarshaler = &ServerDecapsulateParam{}
|
||||
var _ encoding.BinaryUnmarshaler = &ServerDecapsulateParam{}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (p *ClientDecapsulateParam) MarshalBinary() (data []byte, err error) {
|
||||
return p.c.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (p *ClientDecapsulateParam) UnmarshalBinary(data []byte) error {
|
||||
_, err := p.c.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (p *ServerDecapsulateParam) MarshalBinary() (data []byte, err error) {
|
||||
return p.e.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (p *ServerDecapsulateParam) UnmarshalBinary(data []byte) error {
|
||||
_, err := p.e.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package sm9m
|
||||
|
||||
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 (
|
||||
ErrRandomFaile ErrorCode = 0x01011000 + iota //生成随机数失败
|
||||
ErrInvalidInput //输入不合法
|
||||
ErrKeyTooBig //密钥太大(>=N)
|
||||
ErrKeyIsZero //密钥为0
|
||||
ErrInvalidCipherC1 //密文不合法(C1不是合法的曲线上的点)
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
// Code generated by "stringer -type=ErrorCode -linecomment -output=errors_string.go errors.go"; DO NOT EDIT.
|
||||
|
||||
package sm9m
|
||||
|
||||
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[ErrRandomFaile-16846848]
|
||||
_ = x[ErrInvalidInput-16846849]
|
||||
_ = x[ErrKeyTooBig-16846850]
|
||||
_ = x[ErrKeyIsZero-16846851]
|
||||
_ = x[ErrInvalidCipherC1-16846852]
|
||||
}
|
||||
|
||||
const _ErrorCode_name = "生成随机数失败输入不合法密钥太大(>=N)密钥为0密文不合法(C1不是合法的曲线上的点)"
|
||||
|
||||
var _ErrorCode_index = [...]uint8{0, 21, 36, 53, 63, 112}
|
||||
|
||||
func (i ErrorCode) String() string {
|
||||
i -= 16846848
|
||||
if i >= ErrorCode(len(_ErrorCode_index)-1) {
|
||||
return "ErrorCode(" + strconv.FormatInt(int64(i+16846848), 10) + ")"
|
||||
}
|
||||
return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]]
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package sm9m
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/sm/sm9"
|
||||
)
|
||||
|
||||
// 一、签名密钥分割方式,ds= [Ks] * Kc,
|
||||
// 客户端掌握Kc, 服务端掌握 Ks \in G1
|
||||
|
||||
// SignKeyClient 客户端部分签名密钥
|
||||
type SignKeyClient struct {
|
||||
p sm9.G1
|
||||
}
|
||||
|
||||
// SignKeyServer 服务端部分签名密钥
|
||||
type SignKeyServer struct {
|
||||
k big.Int
|
||||
}
|
||||
|
||||
// GenerateKeys 从完整的SM9用户密钥ds生成客户端和服务端部分密钥。
|
||||
// ds为KGC下发的用户密钥,应在调用完成后清除。
|
||||
func GenerateSignKeys(ds *sm9.UserSignKey, rnd io.Reader) (*SignKeyClient, *SignKeyServer, error) {
|
||||
i, j, err := generatePairInt(rnd, sm9.N)
|
||||
if err != nil {
|
||||
return nil, nil, gerrors.WithAnnotating(err, "GenerateSignKeys failed")
|
||||
}
|
||||
kc := &SignKeyClient{}
|
||||
ks := &SignKeyServer{}
|
||||
ks.k.Set(i)
|
||||
kc.p.ScalarMult(&ds.G1, j)
|
||||
return kc, ks, nil
|
||||
}
|
||||
|
||||
// 二、加密密钥分割方式,de= Kc + Ks,
|
||||
// 客户端掌握Kc, 服务端掌握 Ks
|
||||
|
||||
// EncKeyClient 客户端部分签名密钥
|
||||
type EncKeyClient struct {
|
||||
p sm9.G2
|
||||
}
|
||||
|
||||
// EncKeyServer 服务端部分签名密钥
|
||||
type EncKeyServer struct {
|
||||
p sm9.G2
|
||||
}
|
||||
|
||||
// GenerateEncKeys 从完整的SM9用户密钥de生成客户端和服务端部分密钥。
|
||||
// de为KGC下发的用户密钥,应在调用完成后清除。
|
||||
func GenerateEncKeys(de *sm9.UserEncKey, rnd io.Reader) (*EncKeyClient, *EncKeyServer, error) {
|
||||
var k *big.Int
|
||||
var err error
|
||||
for {
|
||||
k, err = rand.Int(rnd, sm9.N)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if k.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
kc := &EncKeyClient{}
|
||||
ks := &EncKeyServer{}
|
||||
kc.p.ScalarBaseMult(k)
|
||||
ks.p.Neg(&kc.p)
|
||||
ks.p.Add(&de.G2, &ks.p)
|
||||
return kc, ks, nil
|
||||
}
|
||||
|
||||
// generatePairInt 生成k,s满足k * s = 1 mod n, 0 < k,s < n.
|
||||
func generatePairInt(rnd io.Reader, n *big.Int) (k *big.Int, s *big.Int, err error) {
|
||||
for {
|
||||
k, err = rand.Int(rnd, n)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if k.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
s = new(big.Int).ModInverse(k, n)
|
||||
return k, s, nil
|
||||
}
|
||||
|
||||
var _ encoding.BinaryMarshaler = &EncKeyClient{}
|
||||
var _ encoding.BinaryUnmarshaler = &EncKeyClient{}
|
||||
var _ encoding.BinaryMarshaler = &EncKeyServer{}
|
||||
var _ encoding.BinaryUnmarshaler = &EncKeyServer{}
|
||||
|
||||
var _ encoding.BinaryMarshaler = &SignKeyClient{}
|
||||
var _ encoding.BinaryUnmarshaler = &SignKeyClient{}
|
||||
var _ encoding.BinaryMarshaler = &SignKeyServer{}
|
||||
var _ encoding.BinaryUnmarshaler = &SignKeyServer{}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (k *EncKeyServer) UnmarshalBinary(data []byte) error {
|
||||
_, err := k.p.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (k *EncKeyServer) MarshalBinary() (data []byte, err error) {
|
||||
return k.p.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (k *EncKeyClient) UnmarshalBinary(data []byte) error {
|
||||
_, err := k.p.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (k *EncKeyClient) MarshalBinary() (data []byte, err error) {
|
||||
return k.p.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (k *SignKeyClient) UnmarshalBinary(data []byte) error {
|
||||
_, err := k.p.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (k *SignKeyClient) MarshalBinary() (data []byte, err error) {
|
||||
return k.p.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (k *SignKeyServer) UnmarshalBinary(data []byte) error {
|
||||
if len(data) > sm9.ByteSize() {
|
||||
return ErrInvalidInput
|
||||
}
|
||||
k.k.SetBytes(data)
|
||||
if k.k.Cmp(sm9.N) >= 0 {
|
||||
return ErrKeyTooBig
|
||||
}
|
||||
if k.k.Sign() == 0 {
|
||||
return ErrKeyIsZero
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
func (k *SignKeyServer) MarshalBinary() (data []byte, err error) {
|
||||
data = make([]byte, sm9.ByteSize())
|
||||
if err := gmath.FillBytes(&k.k, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package sm9m
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
"xdx.jelly/xgcl/sm/sm9"
|
||||
)
|
||||
|
||||
// 签名流程
|
||||
// 1. 客户端生成随机数r, U = [r]*Kc, 发送m, U
|
||||
// 2. 服务端使用[ks]U作为完整用户私钥签名得到(h, S')
|
||||
// 3. 客户端计算S = [r^-1]S', 输出签名(h,S)
|
||||
|
||||
type ClientSignContext struct {
|
||||
r big.Int
|
||||
}
|
||||
|
||||
type ClientSignParam struct {
|
||||
p sm9.G1
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface
|
||||
func (cp *ClientSignParam) MarshalBinary() (data []byte, err error) {
|
||||
return cp.p.Marshal(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
|
||||
func (cp *ClientSignParam) UnmarshalBinary(data []byte) error {
|
||||
_, err := cp.p.Unmarshal(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// GenerateParam 客户端第一步
|
||||
func (c *ClientSignContext) GenerateParam(clientSignKey *SignKeyClient, rnd io.Reader) (*ClientSignParam, error) {
|
||||
r, rInv, err := generatePairInt(rnd, sm9.N)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientParam := &ClientSignParam{}
|
||||
clientParam.p.ScalarMult(&clientSignKey.p, rInv)
|
||||
|
||||
c.r.Set(r)
|
||||
return clientParam, nil
|
||||
}
|
||||
|
||||
// GenerateParam 客户端第二步
|
||||
func (c *ClientSignContext) GenerateSignature(param *ServerSignParam) (*sm9.Signature, error) {
|
||||
param.sig.S.ScalarMult(¶m.sig.S, &c.r)
|
||||
return ¶m.sig, nil
|
||||
}
|
||||
|
||||
type ServerSignParam struct {
|
||||
sig sm9.Signature
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface
|
||||
func (sp *ServerSignParam) MarshalBinary() (data []byte, err error) {
|
||||
return sp.sig.MarshalBinary()
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
|
||||
func (sp *ServerSignParam) UnmarshalBinary(data []byte) error {
|
||||
return sp.sig.UnmarshalBinary(data)
|
||||
}
|
||||
|
||||
// ServerSign 服务端生成协同签名数据
|
||||
func ServerSign(hashed []byte, clientParam *ClientSignParam, serverSignKey *SignKeyServer, pubs *sm9.MastSignPublicKey, rnd io.Reader) (*ServerSignParam, error) {
|
||||
ds := &sm9.UserSignKey{}
|
||||
ds.G1.Set(&clientParam.p)
|
||||
preSig, err := sm9.Sign(hashed, ds, pubs, rnd)
|
||||
if err != nil {
|
||||
return nil, gerrors.WithAnnotating(err, "ServerSign failed")
|
||||
}
|
||||
preSig.S.ScalarMult(&preSig.S, &serverSignKey.k)
|
||||
param := &ServerSignParam{}
|
||||
param.sig.Set(preSig)
|
||||
return param, nil
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package sm9m
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand/drng"
|
||||
"xdx.jelly/xgcl/sm/sm3"
|
||||
"xdx.jelly/xgcl/sm/sm9"
|
||||
)
|
||||
|
||||
func TestSignKeyGen(t *testing.T) {
|
||||
uid := []byte("Alice")
|
||||
ks, pubs, err := sm9.GenerateMastSignPrivateKey(drng.SM3Rng) // use SM3 DRNG
|
||||
assert.Nil(t, err)
|
||||
_ = pubs
|
||||
|
||||
ds, err := ks.GenerateUserSignKey(uid)
|
||||
assert.Nil(t, err)
|
||||
|
||||
clientSignKey, serverSignKey, err := GenerateSignKeys(ds, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Check generated keys are valid
|
||||
assert.True(t, clientSignKey.p.ScalarMult(&clientSignKey.p, &serverSignKey.k).Equal(&ds.G1))
|
||||
}
|
||||
|
||||
func TestEncKeyGen(t *testing.T) {
|
||||
uid := []byte("Alice")
|
||||
ke, _, err := sm9.GenerateMastEncPrivateKey(drng.SM3Rng) // use SM3 DRNG
|
||||
assert.Nil(t, err)
|
||||
|
||||
de, err := ke.GenerateUserEncKey(uid)
|
||||
assert.Nil(t, err)
|
||||
|
||||
clientEncKey, serverEncKey, err := GenerateEncKeys(de, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Check generated keys are valid
|
||||
assert.True(t, serverEncKey.p.Add(&serverEncKey.p, &clientEncKey.p).Equal(&de.G2))
|
||||
}
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
uid := []byte("Alice")
|
||||
ks, pubs, err := sm9.GenerateMastSignPrivateKey(drng.SM3Rng) // use SM3 DRNG
|
||||
assert.Nil(t, err)
|
||||
|
||||
ds, err := ks.GenerateUserSignKey(uid)
|
||||
assert.Nil(t, err)
|
||||
|
||||
clientSignKey, serverSignKey, err := GenerateSignKeys(ds, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// SM9签名输入SM3摘要
|
||||
hash := sm3.Sum([]byte("abc"))
|
||||
|
||||
// 客户端第一步
|
||||
clientCTX := &ClientSignContext{}
|
||||
param, err := clientCTX.GenerateParam(clientSignKey, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
b, err := param.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 服务端
|
||||
param = &ClientSignParam{}
|
||||
assert.Nil(t, param.UnmarshalBinary(b))
|
||||
serverParam, err := ServerSign(hash[:], param, serverSignKey, pubs, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
b, err = serverParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 客户端第二步
|
||||
serverParam = &ServerSignParam{}
|
||||
assert.Nil(t, serverParam.UnmarshalBinary(b))
|
||||
sig, err := clientCTX.GenerateSignature(serverParam)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, sm9.Verify(sig, uid, hash[:], pubs))
|
||||
}
|
||||
|
||||
func TestDecryption(t *testing.T) {
|
||||
id := []byte("Alice")
|
||||
ke, pube, err := sm9.GenerateMastEncPrivateKey(drng.SM3Rng) // use SM3 DRNG
|
||||
assert.Nil(t, err)
|
||||
|
||||
de, err := ke.GenerateUserEncKey(id)
|
||||
assert.Nil(t, err)
|
||||
|
||||
msg := []byte("Chinese IBE standard")
|
||||
cipher, err := sm9.Encrypt(sm9.EncTypeKDF, pube, id, msg, drng.SM3Rng, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
clientEncKey, serverEncKey, err := GenerateEncKeys(de, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 1
|
||||
clientCTX := &ClientDecContext{}
|
||||
clientParam, err := clientCTX.GenerateParam(cipher)
|
||||
assert.Nil(t, err)
|
||||
b, err := clientParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 2
|
||||
clientParam = &ClientDecParam{}
|
||||
assert.Nil(t, clientParam.UnmarshalBinary(b))
|
||||
serverParam, err := ServerDecrypt(clientParam, serverEncKey)
|
||||
assert.Nil(t, err)
|
||||
b, err = serverParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3
|
||||
serverParam = &ServerDecParam{}
|
||||
assert.Nil(t, serverParam.UnmarshalBinary(b))
|
||||
msg1, err := clientCTX.DecryptFinal(id, clientEncKey, serverParam)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, msg, msg1)
|
||||
}
|
||||
|
||||
func TestDecapsulate(t *testing.T) {
|
||||
id := []byte("Alice")
|
||||
ke, pube, err := sm9.GenerateMastEncPrivateKey(drng.SM3Rng) // use SM3 DRNG
|
||||
assert.Nil(t, err)
|
||||
|
||||
de, err := ke.GenerateUserEncKey(id)
|
||||
assert.Nil(t, err)
|
||||
|
||||
clientEncKey, serverEncKey, err := GenerateEncKeys(de, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
|
||||
keylen := 48
|
||||
pack, key0, err := sm9.KeyEncapsulate(id, keylen, pube, drng.SM3Rng)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 1
|
||||
clientCTX := &ClientDecapsulateContext{}
|
||||
clientParam, err := clientCTX.GenerateParam(pack)
|
||||
assert.Nil(t, err)
|
||||
b, err := clientParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 2
|
||||
clientParam = &ClientDecapsulateParam{}
|
||||
assert.Nil(t, clientParam.UnmarshalBinary(b))
|
||||
serverParam, err := ServerDecapsulate(clientParam, serverEncKey)
|
||||
assert.Nil(t, err)
|
||||
b, err = serverParam.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 3
|
||||
serverParam = &ServerDecapsulateParam{}
|
||||
assert.Nil(t, serverParam.UnmarshalBinary(b))
|
||||
key1, err := clientCTX.DecapsulateFinal(id, keylen, clientEncKey, serverParam)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, key0, key1)
|
||||
}
|
||||
Reference in New Issue
Block a user