108 lines
3.0 KiB
Go
108 lines
3.0 KiB
Go
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
|
|
}
|