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
+147
View File
@@ -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)
}
}
+80
View File
@@ -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, &param.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
}
+77
View File
@@ -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, &param.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
}
+21
View File
@@ -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不是合法的曲线上的点)
)
+28
View File
@@ -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]]
}
+157
View File
@@ -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
}
+80
View File
@@ -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(&param.sig.S, &c.r)
return &param.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
}
+157
View File
@@ -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)
}