Files
xgcl/tpc/sm9/sm9m/key.go
T
2026-05-27 23:03:00 +08:00

158 lines
3.9 KiB
Go

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
}