init: v1.0.0
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package concentration
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
"xdx.jelly/xgcl/sm/sm3"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrClientGenerateAgreementData = fmt.Errorf("client GenerateAgreementData error")
|
||||
)
|
||||
|
||||
type ClientKeyGenContext struct {
|
||||
ks *sm2.PrivateKey
|
||||
ppub *sm2.PublicKey
|
||||
clientPub *sm2.PublicKey
|
||||
}
|
||||
|
||||
func NewClientKeyGenContext() *ClientKeyGenContext {
|
||||
return &ClientKeyGenContext{}
|
||||
}
|
||||
|
||||
// GenerateTempKGC output data, and send to server
|
||||
// in: serverData, server临时公钥U
|
||||
// out: []byte, ppub_x || ppub_y || W_x || W_y || t || check
|
||||
func (c *ClientKeyGenContext) GenerateAgreementData(serverData []byte, clientID []byte) ([]byte, *sm2.PublicKey, error) {
|
||||
var data []byte
|
||||
var err error
|
||||
|
||||
serverTempPubkey := sm2.NewPublicKey()
|
||||
if err = serverTempPubkey.UnmarshalBinary(serverData); err != nil {
|
||||
return []byte{}, nil, ErrClientGenerateAgreementData
|
||||
}
|
||||
|
||||
if c.ks, err = sm2.GenPrivateKey(grand.GetRandom(sm2.ByteSize())); err != nil {
|
||||
return []byte{}, nil, ErrClientGenerateAgreementData
|
||||
}
|
||||
c.ppub = sm2.GenPublicKey(c.ks)
|
||||
data = make([]byte, 0, 128+32+4)
|
||||
data = append(data, gmath.BigIntToNByte(c.ppub.X, 32)...)
|
||||
data = append(data, gmath.BigIntToNByte(c.ppub.Y, 32)...)
|
||||
|
||||
w, err := sm2.GenPrivateKey(grand.GetRandom(sm2.ByteSize()))
|
||||
if err != nil {
|
||||
return []byte{}, nil, ErrClientGenerateAgreementData
|
||||
}
|
||||
W := sm2.GenPublicKey(w)
|
||||
data = append(data, gmath.BigIntToNByte(W.X, 32)...)
|
||||
data = append(data, gmath.BigIntToNByte(W.Y, 32)...)
|
||||
|
||||
// FIXME: W.X.Bytes() may not 32-bytes
|
||||
digest := sm3.Sum(W.Bytes(), sm2.PreComputeWithIdAndPubkey(clientID, c.ppub))
|
||||
// digest := sm3.Sum(W.X.Bytes(), W.Y.Bytes(), sm2.PreComputeWithIdAndPubkey(clientID, c.ppub))
|
||||
t := new(big.Int)
|
||||
t.SetBytes(digest[:])
|
||||
t.Mul(t, c.ks.D)
|
||||
t.Add(t, w.D)
|
||||
t.Mod(t, sm2.OrderN())
|
||||
data = append(data, gmath.BigIntToNByte(t, sm2.ByteSize())...)
|
||||
|
||||
checkSum := crc32.ChecksumIEEE(data)
|
||||
buf := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(buf, checkSum)
|
||||
data = append(data, buf...)
|
||||
|
||||
x, y := sm2.Curve256.ScalarBaseMult(t.Bytes())
|
||||
x, y = sm2.Curve().Add(x, y, serverTempPubkey.X, serverTempPubkey.Y)
|
||||
pk := &sm2.PublicKey{
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
c.clientPub = sm2.NewPublicKey()
|
||||
c.clientPub.X.Set(x)
|
||||
c.clientPub.Y.Set(y)
|
||||
return data, pk, nil
|
||||
}
|
||||
|
||||
type ClientSignContext struct {
|
||||
k *sm2.PrivateKey
|
||||
r *big.Int
|
||||
}
|
||||
|
||||
func NewClientSignContext() *ClientSignContext {
|
||||
return &ClientSignContext{}
|
||||
}
|
||||
|
||||
// GenerateSignData 生成签名中间数据和r
|
||||
func (c *ClientSignContext) GenerateSignData(serverData []byte, e []byte) (dataToServer []byte, r []byte, err error) {
|
||||
c.k = sm2.NewPrivateKey()
|
||||
c.k.Random(grand.Reader)
|
||||
c.r = new(big.Int)
|
||||
c.r.SetBytes(e)
|
||||
tempPK := sm2.NewPublicKey()
|
||||
tempPK.X.SetBytes(serverData[:32])
|
||||
tempPK.Y.SetBytes(serverData[32:])
|
||||
x, _ := sm2.Curve256.ScalarMult(tempPK.X, tempPK.Y, c.k.Bytes())
|
||||
c.r.Add(c.r, x)
|
||||
c.r.Mod(c.r, sm2.OrderN())
|
||||
|
||||
return gmath.BigIntToNByte(c.k.D, 32), gmath.BigIntToNByte(c.r, 32), nil
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# 合并签名
|
||||
|
||||
## 密钥生成流程
|
||||
|
||||
## 签名流程
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package concentration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
fmt.Println("============= 生成密钥 =============")
|
||||
clientID := []byte("Teacher Tony")
|
||||
serverKeyGenCTX := NewServerKeyGenContext()
|
||||
clientKeyGenCTX := NewClientKeyGenContext()
|
||||
|
||||
// 1 server调用密码机获取32字节随机数。 GenerateAgreementData传出数据发送给客户端。
|
||||
data, err := serverKeyGenCTX.GenerateAgreementData(grand.GetRandom(sm2.ByteSize()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
//2 client 调用生成数据和公钥
|
||||
data, clientPK, err := clientKeyGenCTX.GenerateAgreementData(data, clientID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 3 server 计算密钥对
|
||||
sk, serverPK, err := serverKeyGenCTX.ComputeKeyPair(data, clientID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 服务端清除敏感信息
|
||||
serverKeyGenCTX.Clear()
|
||||
|
||||
if !serverPK.Equals(clientPK) {
|
||||
panic("clientPK != serverPK")
|
||||
}
|
||||
fmt.Println("server pubkey: ", serverPK)
|
||||
fmt.Println("client pubkey: ", clientPK)
|
||||
fmt.Printf("sk: %02x\n", sk)
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("============= 签名 =============")
|
||||
e := grand.GetRandom(32)
|
||||
serverSignCTX := NewServerSignContext()
|
||||
clientSignCTX := NewClientSignContext()
|
||||
|
||||
data, err = serverSignCTX.GenerateSignData(grand.GetRandom(32))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
data, clientR, err := clientSignCTX.GenerateSignData(data, e)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sig, err := serverSignCTX.Sign(data, e, sk)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sk.Clear()
|
||||
fmt.Println("sig: ", sig)
|
||||
fmt.Printf("client's r: %02x\n", clientR)
|
||||
fmt.Println("serverPK verify: ", sm2.Verify(e, serverPK, sig))
|
||||
fmt.Println("clientPK verify: ", sm2.Verify(e, clientPK, sig))
|
||||
if (bytes.Compare(clientR, gmath.BigIntToNByte(sig.R, 32))) != 0 {
|
||||
panic("client r != server r")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
ctx := NewServerSignContext()
|
||||
ctx.k1 = sm2.NewPrivateKey().Random(grand.Reader)
|
||||
ctx.u = sm2.NewPublicKey().Generate(ctx.k1)
|
||||
ctx.clientPPub = sm2.NewPublicKey().Generate(sm2.NewPrivateKey().Random(grand.Reader))
|
||||
buf, err := ctx.MarshalBinary()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Printf("%x\n\n", buf)
|
||||
|
||||
ctx1 := NewServerSignContext()
|
||||
err = ctx1.UnmarshalBinary(buf)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
buf, err = ctx1.MarshalBinary()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Printf("%x\n\n", buf)
|
||||
|
||||
if ctx1.k1.D.Cmp(ctx.k1.D) != 0 {
|
||||
t.Log()
|
||||
t.Fail()
|
||||
}
|
||||
if !ctx1.u.Equals(ctx.u) {
|
||||
t.Log()
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if !ctx1.clientPPub.Equals(ctx.clientPPub) {
|
||||
t.Log()
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package concentration
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrServerKeyGen = fmt.Errorf("GenerateAgreementData error")
|
||||
ErrInputDataInvalid = fmt.Errorf("input data invalid")
|
||||
ErrServerSignError = fmt.Errorf("server sign error")
|
||||
)
|
||||
|
||||
type ServerKeyGenContext struct {
|
||||
d *sm2.PrivateKey
|
||||
u *sm2.PublicKey
|
||||
clientPPub *sm2.PublicKey
|
||||
|
||||
//sk *sm2.PrivateKey
|
||||
//pk *sm2.PublicKey
|
||||
}
|
||||
|
||||
func NewServerKeyGenContext() *ServerKeyGenContext {
|
||||
return &ServerKeyGenContext{
|
||||
d: sm2.NewPrivateKey(),
|
||||
u: sm2.NewPublicKey(),
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateAgreementData 根据客户端发送的数据生成临时数据并发送给客户度
|
||||
func (s *ServerKeyGenContext) GenerateAgreementData(rnd32 []byte) ([]byte, error) {
|
||||
var data []byte
|
||||
var err error
|
||||
|
||||
if len(rnd32) < sm2.ByteSize() {
|
||||
rnd32 = grand.GetRandom(sm2.ByteSize())
|
||||
}
|
||||
if s.d, err = sm2.GenPrivateKey(rnd32); err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
s.u = sm2.GenPublicKey(s.d)
|
||||
if data, err = s.u.MarshalBinary(); err != nil {
|
||||
return []byte{}, ErrServerKeyGen
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ComputeKeyPair clientData = ppub_x || ppub_y || W_x || W_y || t || check
|
||||
// out key pair
|
||||
func (s *ServerKeyGenContext) ComputeKeyPair(clientData []byte, clientID []byte) (*sm2.PrivateKey, *sm2.PublicKey, error) {
|
||||
if len(clientData) < 64+64+32+4 {
|
||||
return nil, nil, ErrInputDataInvalid
|
||||
}
|
||||
checkSumShouldBe := crc32.ChecksumIEEE(clientData[:64+64+32])
|
||||
checkSum := binary.BigEndian.Uint32(clientData[128+32:])
|
||||
if checkSum != checkSumShouldBe {
|
||||
return nil, nil, ErrInputDataInvalid
|
||||
}
|
||||
|
||||
sk := sm2.NewPrivateKey()
|
||||
sk.SetBytes(clientData[128 : 128+32])
|
||||
sk.D.Add(sk.D, s.d.D)
|
||||
sk.D.Mod(sk.D, sm2.OrderN())
|
||||
if gmath.IsBigInt0(sk.D) {
|
||||
return nil, nil, ErrServerKeyGen
|
||||
}
|
||||
pk := sm2.GenPublicKey(sk)
|
||||
//
|
||||
//ppub := sm2.NewPublicKey()
|
||||
//if err := ppub.UnmarshalBinary(clientData); err != nil{
|
||||
// return nil, nil, ErrServerKeyGen
|
||||
//}
|
||||
//
|
||||
//digest := sm3.Sum(clientData[64:128],sm2.PreComputeWithIdAndPubkey(clientID, ppub))
|
||||
//PublicKey := sm2.Curve256.ScalarMult(ppub.X, ppub.Y, digest[:])
|
||||
return sk, pk, nil
|
||||
}
|
||||
|
||||
func (s *ServerKeyGenContext) Clear() {
|
||||
s.d.Clear()
|
||||
}
|
||||
|
||||
type ServerSignContext struct {
|
||||
k1 *sm2.PrivateKey
|
||||
u *sm2.PublicKey
|
||||
clientPPub *sm2.PublicKey
|
||||
}
|
||||
|
||||
func NewServerSignContext() *ServerSignContext {
|
||||
return &ServerSignContext{
|
||||
sm2.NewPrivateKey(),
|
||||
sm2.NewPublicKey(),
|
||||
sm2.NewPublicKey(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ServerSignContext) MarshalBinary() ([]byte, error) {
|
||||
if s.k1 == nil {
|
||||
s.k1 = sm2.NewPrivateKey()
|
||||
}
|
||||
if s.u == nil {
|
||||
s.u = sm2.NewPublicKey()
|
||||
}
|
||||
|
||||
if s.clientPPub == nil {
|
||||
s.clientPPub = sm2.NewPublicKey()
|
||||
}
|
||||
|
||||
r := make([]byte, 0, 3*4+(4+sm2.ECCRefMaxLen)+(4+2*sm2.ECCRefMaxLen)+(4+2*sm2.ECCRefMaxLen))
|
||||
var buf []byte
|
||||
var uintBuf = make([]byte, 4)
|
||||
var err error
|
||||
|
||||
if buf, err = s.k1.MarshalBinary(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
binary.BigEndian.PutUint32(uintBuf, uint32(len(buf)))
|
||||
r = append(r, uintBuf...)
|
||||
r = append(r, buf...)
|
||||
|
||||
if buf, err = s.u.MarshalBinary(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
binary.BigEndian.PutUint32(uintBuf, uint32(len(buf)))
|
||||
r = append(r, uintBuf...)
|
||||
r = append(r, buf...)
|
||||
|
||||
if buf, err = s.clientPPub.MarshalBinary(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
binary.BigEndian.PutUint32(uintBuf, uint32(len(buf)))
|
||||
r = append(r, uintBuf...)
|
||||
r = append(r, buf...)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (s *ServerSignContext) UnmarshalBinary(data []byte) error {
|
||||
|
||||
if s.k1 == nil {
|
||||
s.k1 = sm2.NewPrivateKey()
|
||||
}
|
||||
if s.u == nil {
|
||||
s.u = sm2.NewPublicKey()
|
||||
}
|
||||
|
||||
if s.clientPPub == nil {
|
||||
s.clientPPub = sm2.NewPublicKey()
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if len(data) < 4 {
|
||||
return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary")
|
||||
}
|
||||
size := binary.BigEndian.Uint32(data)
|
||||
data = data[4:]
|
||||
if uint32(len(data)) < size {
|
||||
return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary")
|
||||
}
|
||||
if err = s.k1.UnmarshalBinary(data[:size]); err != nil {
|
||||
return err
|
||||
}
|
||||
data = data[size:]
|
||||
|
||||
if len(data) < 4 {
|
||||
return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary")
|
||||
}
|
||||
size = binary.BigEndian.Uint32(data)
|
||||
data = data[4:]
|
||||
if uint32(len(data)) < size {
|
||||
return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary")
|
||||
}
|
||||
if err = s.u.UnmarshalBinary(data[:size]); err != nil {
|
||||
return err
|
||||
}
|
||||
data = data[size:]
|
||||
|
||||
if len(data) < 4 {
|
||||
return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary")
|
||||
}
|
||||
size = binary.BigEndian.Uint32(data)
|
||||
data = data[4:]
|
||||
if uint32(len(data)) < size {
|
||||
return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary")
|
||||
}
|
||||
if err = s.clientPPub.UnmarshalBinary(data[:size]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ServerSignContext) GenerateSignData(rnd32 []byte) ([]byte, error) {
|
||||
var data []byte = make([]byte, 0, 64)
|
||||
var err error
|
||||
|
||||
if len(rnd32) < sm2.ByteSize() {
|
||||
rnd32 = grand.GetRandom(sm2.ByteSize())
|
||||
}
|
||||
if s.k1, err = sm2.GenPrivateKey(rnd32); err != nil {
|
||||
|
||||
}
|
||||
s.u = sm2.GenPublicKey(s.k1)
|
||||
data = append(data, gmath.BigIntToNByte(s.u.X, 32)...)
|
||||
data = append(data, gmath.BigIntToNByte(s.u.Y, 32)...)
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// Sign generate signature
|
||||
// input: clientData 32 bytes
|
||||
func (ssc *ServerSignContext) Sign(clientData []byte, e []byte, sk *sm2.PrivateKey) (*sm2.Signature, error) {
|
||||
k := new(big.Int)
|
||||
k.SetBytes(clientData)
|
||||
k.Mul(k, ssc.k1.D)
|
||||
k.Mod(k, sm2.OrderN())
|
||||
x, _ := sm2.Curve256.ScalarBaseMult(k.Bytes())
|
||||
r := new(big.Int)
|
||||
r.SetBytes(e)
|
||||
r.Add(x, r)
|
||||
r.Mod(r, sm2.OrderN())
|
||||
|
||||
s := new(big.Int)
|
||||
s.Set(sk.D)
|
||||
s.Add(s, gmath.BigInt1)
|
||||
s.ModInverse(s, sm2.OrderN())
|
||||
k.Add(k, r)
|
||||
s.Mul(s, k)
|
||||
s.Sub(s, r)
|
||||
s.Mod(s, sm2.OrderN())
|
||||
sig := &sm2.Signature{
|
||||
R: r,
|
||||
S: s,
|
||||
}
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func (ssc *ServerSignContext) Clear() {
|
||||
ssc.k1.Clear()
|
||||
}
|
||||
Reference in New Issue
Block a user