184 lines
6.0 KiB
Go
184 lines
6.0 KiB
Go
package sm2a
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"xdx.jelly/xgcl/gmath"
|
|
"xdx.jelly/xgcl/grand"
|
|
"xdx.jelly/xgcl/sm/sm2"
|
|
)
|
|
|
|
type ClientSponsor struct {
|
|
mixPoint *sm2.PublicKey
|
|
KeyBits uint32
|
|
z []byte
|
|
r *sm2.PrivateKey // sponsor's temp private key
|
|
clientKey *sm2.PrivateKey
|
|
publicKey *sm2.PublicKey
|
|
tempKeyOfSponsor *sm2.PublicKey
|
|
tempKeyOfResponsor *sm2.PublicKey
|
|
}
|
|
|
|
func NewClientSponsor(id []byte, clientKey *sm2.PrivateKey, publicKey *sm2.PublicKey) *ClientSponsor {
|
|
return &ClientSponsor{
|
|
z: sm2.PreComputeWithIdAndPubkey(id, publicKey),
|
|
clientKey: sm2.NewPrivateKey().Set(clientKey),
|
|
publicKey: sm2.NewPublicKey().Set(publicKey),
|
|
tempKeyOfSponsor: sm2.NewPublicKey(),
|
|
tempKeyOfResponsor: sm2.NewPublicKey(),
|
|
}
|
|
}
|
|
|
|
// GenerateAgreementData 发起方客户端计算密钥交换数据
|
|
func (c *ClientSponsor) GenerateAgreementData(rnd []byte) (tempKeyOfSponsor *sm2.PublicKey, err error) {
|
|
if len(rnd) < sm2.ByteSize() {
|
|
rnd = make([]byte, sm2.ByteSize())
|
|
if _, err := grand.GenerateRandom(rnd); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
c.r, _ = sm2.GenPrivateKey(rnd[:sm2.ByteSize()])
|
|
tempKeyOfSponsor = sm2.GenPublicKey(c.r)
|
|
c.tempKeyOfSponsor.Set(tempKeyOfSponsor)
|
|
return tempKeyOfSponsor, nil
|
|
}
|
|
|
|
// GenerateKey_1of2 发起方客户端计算密钥第一步
|
|
func (c *ClientSponsor) GenerateKey_1of2(pubkeyOfResponsor, tempKeyOfResponsor *sm2.PublicKey) ([]byte, error) {
|
|
if !pubkeyOfResponsor.IsValid() || !tempKeyOfResponsor.IsValid() {
|
|
return nil, fmt.Errorf("Input Public Key are not valid")
|
|
}
|
|
c.mixPoint = mixPoint(pubkeyOfResponsor, tempKeyOfResponsor) // P+[x_R]·R
|
|
return marshalPoint(c.mixPoint), nil
|
|
}
|
|
|
|
// GenerateKey_2of2 发起方客户端计算密钥第二步
|
|
func (c *ClientSponsor) GenerateKey_2of2(keyLength int, idOfResponsor []byte, fromServer []byte, pubkeyOfResponsor *sm2.PublicKey, clientKey *sm2.PrivateKey) (key []byte, err error) {
|
|
if len(fromServer) < 2*sm2.ByteSize() {
|
|
return nil, fmt.Errorf("Input Public Key are not valid")
|
|
}
|
|
|
|
tempKeyOfServer := unmarshalPoint(fromServer)
|
|
if !tempKeyOfServer.IsValid() || !pubkeyOfResponsor.IsValid() {
|
|
return nil, fmt.Errorf("Input Public Key are not valid")
|
|
}
|
|
|
|
// U = [d_c + d_s + \bar{x_1} * r_A]*MixPointB
|
|
// = [d_s]*MixPointB + [d_c + \bar{x_1} * r_A]*MixPointB
|
|
w := sm2.XBar(c.tempKeyOfSponsor.X)
|
|
w.Mul(w, c.r.D)
|
|
w.Add(w, clientKey.D)
|
|
w.Mod(w, sm2.OrderN())
|
|
x, y := sm2.Curve256.ScalarMult(c.mixPoint.X, c.mixPoint.Y, w.Bytes())
|
|
x, y = sm2.Curve().Add(x, y, tempKeyOfServer.X, tempKeyOfServer.Y) // U = (x,y)
|
|
|
|
// printLog("U= %x\n", append(append([]byte{}, x.Bytes()...), y.Bytes()...))
|
|
|
|
if gmath.IsBigInt0(x) && gmath.IsBigInt0(y) {
|
|
return nil, fmt.Errorf("U is zero")
|
|
}
|
|
|
|
key = make([]byte, keyLength)
|
|
sm2.Kdf(key,
|
|
gmath.BigIntToNByte(x, sm2.ByteSize()),
|
|
gmath.BigIntToNByte(y, sm2.ByteSize()),
|
|
c.z,
|
|
sm2.PreComputeWithIdAndPubkey(idOfResponsor, pubkeyOfResponsor))
|
|
|
|
return key, nil
|
|
|
|
}
|
|
|
|
type ClientResponsor struct {
|
|
z []byte
|
|
clientKey *sm2.PrivateKey
|
|
publicKey *sm2.PublicKey
|
|
|
|
mixPoint *sm2.PublicKey
|
|
}
|
|
|
|
// NewResponsor return a responsor's instance
|
|
func NewClientResponsor(id []byte, clientKey *sm2.PrivateKey, publicKey *sm2.PublicKey) *ClientResponsor {
|
|
return &ClientResponsor{
|
|
z: sm2.PreComputeWithIdAndPubkey(id, publicKey),
|
|
clientKey: sm2.NewPrivateKey().Set(clientKey),
|
|
publicKey: sm2.NewPublicKey().Set(publicKey),
|
|
}
|
|
}
|
|
|
|
// GenerateAgreementDataAndKey_1of2 响应方客户端生成数据和密钥第一步
|
|
func (cr *ClientResponsor) GenerateAgreementDataAndKey_1of2(pubkeyOfSponsor, tempKeyOfSponsor *sm2.PublicKey) (toServer []byte, err error) {
|
|
if !pubkeyOfSponsor.IsValid() || !tempKeyOfSponsor.IsValid() {
|
|
return nil, fmt.Errorf("Input Public Key are not valid")
|
|
}
|
|
cr.mixPoint = mixPoint(pubkeyOfSponsor, tempKeyOfSponsor)
|
|
return marshalPoint(cr.mixPoint), nil
|
|
}
|
|
|
|
// GenerateAgreementDataAndKey_1of2 响应方客户端生成数据和密钥第二步
|
|
func (cr *ClientResponsor) GenerateAgreementDataAndKey_2of2(keyLength int, idOfSponsor []byte, pubkeyOfSponsor *sm2.PublicKey, fromServer []byte, rnd []byte) (key []byte, tempKeyOfResponsor *sm2.PublicKey, err error) {
|
|
if len(fromServer) < 2*sm2.ByteSize() {
|
|
return nil, nil, fmt.Errorf("Input Public Key are not valid")
|
|
}
|
|
|
|
tempKeyOfServer := unmarshalPoint(fromServer)
|
|
if !pubkeyOfSponsor.IsValid() || !tempKeyOfServer.IsValid() {
|
|
return nil, nil, fmt.Errorf("Input Public Key are not valid")
|
|
}
|
|
|
|
if len(rnd) < sm2.ByteSize() {
|
|
rnd = make([]byte, sm2.ByteSize())
|
|
if _, err := grand.GenerateRandom(rnd); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
}
|
|
|
|
rb, _ := sm2.GenPrivateKey(rnd[:sm2.ByteSize()])
|
|
tempKeyOfResponsor = sm2.GenPublicKey(rb)
|
|
|
|
w := sm2.XBar(tempKeyOfResponsor.X)
|
|
w.Mul(w, rb.D)
|
|
w.Add(w, cr.clientKey.D)
|
|
w.Mod(w, sm2.OrderN())
|
|
x, y := sm2.Curve256.ScalarMult(cr.mixPoint.X, cr.mixPoint.Y, w.Bytes())
|
|
x, y = sm2.Curve().Add(x, y, tempKeyOfServer.X, tempKeyOfServer.Y) // V = (x,y)
|
|
|
|
// printLog("V=", append(append([]byte{}, x.Bytes()...), y.Bytes()...))
|
|
|
|
if gmath.IsBigInt0(x) && gmath.IsBigInt0(y) {
|
|
return nil, nil, fmt.Errorf("U is zero")
|
|
}
|
|
|
|
key = make([]byte, keyLength)
|
|
sm2.Kdf(key,
|
|
gmath.BigIntToNByte(x, sm2.ByteSize()),
|
|
gmath.BigIntToNByte(y, sm2.ByteSize()),
|
|
sm2.PreComputeWithIdAndPubkey(idOfSponsor, pubkeyOfSponsor),
|
|
cr.z,
|
|
)
|
|
|
|
return key, tempKeyOfResponsor, nil
|
|
}
|
|
|
|
// mixPoint return p+[x_r]·r
|
|
func mixPoint(p, r *sm2.PublicKey) *sm2.PublicKey {
|
|
xBar := sm2.XBar(r.X)
|
|
x, y := sm2.Curve256.ScalarMult(r.X, r.Y, xBar.Bytes())
|
|
x, y = sm2.Curve().Add(x, y, p.X, p.Y)
|
|
return &sm2.PublicKey{X: x, Y: y}
|
|
}
|
|
|
|
func marshalPoint(p *sm2.PublicKey) []byte {
|
|
out := make([]byte, 0, 2*sm2.ByteSize())
|
|
out = append(out, gmath.BigIntToNByte(p.X, sm2.ByteSize())...)
|
|
out = append(out, gmath.BigIntToNByte(p.Y, sm2.ByteSize())...)
|
|
return out
|
|
}
|
|
|
|
func unmarshalPoint(b []byte) *sm2.PublicKey {
|
|
ret := sm2.NewPublicKey()
|
|
ret.X.SetBytes(b[:sm2.ByteSize()])
|
|
ret.Y.SetBytes(b[sm2.ByteSize() : 2*sm2.ByteSize()])
|
|
return ret
|
|
}
|