package sm2 import ( "io" "math/big" "xdx.jelly/xgcl/gerrors" "xdx.jelly/xgcl/gmath" "xdx.jelly/xgcl/grand" ) var wMask *big.Int var w int func initKeyExchange() { w = (Curve().Params().N.BitLen()+1)/2 - 1 wMask = big.NewInt(1) wMask.Lsh(wMask, uint(w)) wMask.Sub(wMask, gmath.BigInt1) } var XBar = computeXBar func computeXBar(x *big.Int) *big.Int { xBar := new(big.Int).And(x, wMask) xBar.SetBit(xBar, w, 1) return xBar } // ///////////////////////////////////// 包函数的方式,不绑定方法到struct上 type ExchgParameters struct { PrivateKey *PrivateKey // ra and Ra = [ra]·G or rb and Rb = [rb]·G IsSponsor bool } func (p *ExchgParameters) PublicKey() *PublicKey { // return p.privateKey.PublicKey.X, p.privateKey.PublicKey.Y return &p.PrivateKey.PublicKey } // SharedKey generate shared key. func (p *ExchgParameters) SharedKey(sk *PrivateKey, peerPk *PublicKey, peerPublicKey *PublicKey) (*big.Int, *big.Int, error) { xBar1 := XBar(p.PrivateKey.X) xBar2 := XBar(peerPublicKey.X) t := new(big.Int).Mul(xBar1, p.PrivateKey.D) t.Add(sk.D, t) t.Mod(t, Curve().Params().N) x, y := Curve().ScalarMult(peerPublicKey.X, peerPublicKey.Y, xBar2.Bytes()) x, y = Curve().Add(x, y, peerPk.X, peerPk.Y) x, y = Curve().ScalarMult(x, y, t.Bytes()) if gmath.IsBigInt0(x) && gmath.IsBigInt0(y) { return nil, nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "U/V is infinity point") } return x, y, nil } // GenerateAgreementData 发起方调用 func GenerateAgreementData(rand io.Reader) (*ExchgParameters, error) { r, err := GenerateKey(Curve(), rand) if err != nil { return nil, err } return &ExchgParameters{ PrivateKey: r, IsSponsor: true, }, err } // GenerateAgreementDataAndKey 响应方调用生成临时公钥及协商密钥 // Za、Zb由PreComputeWithIdAndPubkey计算 func GenerateAgreementDataAndKey( id []byte, privateKey *PrivateKey, peerId []byte, peerPublicKey *PublicKey, peerParam *PublicKey, keyLength int, rand io.Reader) ([]byte, *ExchgParameters, error) { r, err := GenerateAgreementData(rand) r.IsSponsor = false if err != nil { return nil, nil, err } key, err := GenerateSharedKey(r, id, privateKey, peerId, peerPublicKey, peerParam, keyLength) return key, r, nil } // GenerateSharedKey 发起方调用生成协商密钥。 func GenerateSharedKey( r *ExchgParameters, id []byte, privateKey *PrivateKey, peerId []byte, peerPublicKey *PublicKey, peerParam *PublicKey, keyLength int) ([]byte, error) { if !peerParam.IsValid() { return nil, gerrors.WithAnnotating(ErrInvalidPublicKey, "peer's temp param is not a valid curve point") } if !peerPublicKey.IsValid() { return nil, gerrors.WithAnnotating(ErrInvalidPublicKey, "peer's public key is not a valid curve point") } x, y, err := r.SharedKey(privateKey, peerPublicKey, peerParam) if err != nil { return nil, gerrors.ChainErrors(ErrKeyExchangeFailed, err) } key := make([]byte, keyLength) if r.IsSponsor { Kdf(key, gmath.BigIntToNByte(x, byteSize), gmath.BigIntToNByte(y, byteSize), PreComputeWithIdAndPubkey(id, &privateKey.PublicKey), PreComputeWithIdAndPubkey(peerId, peerPublicKey), ) } else { Kdf(key, gmath.BigIntToNByte(x, byteSize), gmath.BigIntToNByte(y, byteSize), PreComputeWithIdAndPubkey(peerId, peerPublicKey), PreComputeWithIdAndPubkey(id, &privateKey.PublicKey), ) } return key, nil } // Sponsor holds a sponsor's key pairs and temp key pairs, context data. // Sponsor对象可以重复使用 type Sponsor struct { KeyBits uint32 z []byte r *PrivateKey // sponsor's temp private key privateKey *PrivateKey publicKey *PublicKey tempKeyOfSponsor *PublicKey tempKeyOfResponsor *PublicKey } // NewSponsor make a copy of privateKey, so Clear will not change the input privateKey // 若id=nil, 则使用默认id。 func NewSponsor(id []byte, privateKey *PrivateKey) *Sponsor { pk := GenPublicKey(privateKey) return &Sponsor{ z: PreComputeWithIdAndPubkey(id, pk), privateKey: NewPrivateKey().Set(privateKey), publicKey: pk, tempKeyOfSponsor: NewPublicKey(), tempKeyOfResponsor: NewPublicKey(), } } // Clear 无论成功与否,最后调用Clear func (s *Sponsor) Clear() { s.privateKey.Clear() } // Responsor hold a responsor's key pairs and id // Responsor对象可以重复使用 type Responsor struct { z []byte privateKey *PrivateKey publicKey *PublicKey } // NewResponsor return a responsor's instance func NewResponsor(id []byte, privateKey *PrivateKey) *Responsor { pk := GenPublicKey(privateKey) return &Responsor{ z: PreComputeWithIdAndPubkey(id, pk), privateKey: NewPrivateKey().Set(privateKey), publicKey: pk, } } // Clear 无论成功与否,最后调用Clear func (rs *Responsor) Clear() { rs.privateKey.Clear() } // A is sponsor and B is responsor ////////////////////// // 发起方函数 // GenerateAgreementData 发起方首先调用,za先计算好 // Za、Zb由PreComputeWithIdAndPubkey计算 // 输出tempPubkey需转化为[]byte func (s *Sponsor) GenerateAgreementData(rnd []byte) (tempKeyOfSponsor *PublicKey, err error) { if len(rnd) < byteSize { rnd = make([]byte, byteSize) if _, err := grand.GenerateRandom(rnd); err != nil { return nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "generate random numbers failed") } } // return error never happen s.r, _ = GenPrivateKey(rnd[:byteSize]) tempKeyOfSponsor = GenPublicKey(s.r) s.tempKeyOfSponsor.Set(tempKeyOfSponsor) return tempKeyOfSponsor, nil } // GenerateKey 发起方调用生成协商密钥。 func (s *Sponsor) GenerateKey(idOfResponsor []byte, pubkeyOfResponsor, tempKeyOfResponsor *PublicKey, keyLength int) (outKey []byte, err error) { if !tempKeyOfResponsor.IsValid() { return nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "responsor's temp param is not a valid curve point") } if !pubkeyOfResponsor.IsValid() { return nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "responsor's public key is not a valid curve point") } xBar1 := computeXBar(s.tempKeyOfSponsor.X) xBar2 := computeXBar(tempKeyOfResponsor.X) ta := new(big.Int).Mul(xBar1, s.r.D) ta.Mod(ta, sm2Curve.Params().N) // fmt.Println("x1ra= ", ta.Text(16)) ta.Add(s.privateKey.D, ta) ta.Mod(ta, sm2Curve.Params().N) ux, uy := sm2Curve.ScalarMult(tempKeyOfResponsor.X, tempKeyOfResponsor.Y, xBar2.Bytes()) ux, uy = sm2Curve.Add(ux, uy, pubkeyOfResponsor.X, pubkeyOfResponsor.Y) // fmt.Println("x2Rb= ", ux.Text(16), uy.Text(16)) ux, uy = sm2Curve.ScalarMult(ux, uy, ta.Bytes()) // fmt.Println("发起方U= ", ux.Text(16), uy.Text(16)) // U = O? if gmath.IsBigInt0(ux) && gmath.IsBigInt0(uy) { return nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "U/V is infinity point") } outKey = make([]byte, keyLength) zb := PreComputeWithIdAndPubkey(idOfResponsor, pubkeyOfResponsor) Kdf(outKey, gmath.BigIntToNByte(ux, byteSize), gmath.BigIntToNByte(uy, byteSize), s.z, zb) return outKey, nil } // 响应方 // GenerateAgreementDataAndKey 响应方调用生成临时公钥及协商密钥 // Za、Zb由PreComputeWithIdAndPubkey计算 func (rs *Responsor) GenerateAgreementDataAndKey(idOfSponsor []byte, pubkeyOfSponsor, tempKeyOfSponsor *PublicKey, keyLength int, rnd []byte) (outKey []byte, tempKeyOfResponsor *PublicKey, err error) { if len(rnd) < byteSize { rnd = make([]byte, byteSize) if _, err := grand.GenerateRandom(rnd); err != nil { return nil, nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "generate random numbers failed") } } rb, _ := GenPrivateKey(rnd[:byteSize]) tempKeyOfResponsor = GenPublicKey(rb) if !tempKeyOfSponsor.IsValid() { return nil, nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "responsor's temp param is not a valid curve point") } if !pubkeyOfSponsor.IsValid() { return nil, nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "responsor's public key is not a valid curve point") } xBar1 := computeXBar(tempKeyOfSponsor.X) xBar2 := computeXBar(tempKeyOfResponsor.X) tb := new(big.Int).Mul(xBar2, rb.D) tb.Mod(tb, sm2Curve.Params().N) tb.Add(rs.privateKey.D, tb) tb.Mod(tb, sm2Curve.Params().N) vx, vy := sm2Curve.ScalarMult(tempKeyOfSponsor.X, tempKeyOfSponsor.Y, xBar1.Bytes()) vx, vy = sm2Curve.Add(vx, vy, pubkeyOfSponsor.X, pubkeyOfSponsor.Y) vx, vy = sm2Curve.ScalarMult(vx, vy, tb.Bytes()) // U = O? if gmath.IsBigInt0(vx) && gmath.IsBigInt0(vy) { return nil, nil, gerrors.WithAnnotating(ErrKeyExchangeFailed, "U/V is infinity point") } za := PreComputeWithIdAndPubkey(idOfSponsor, pubkeyOfSponsor) outKey = make([]byte, keyLength) Kdf(outKey, gmath.BigIntToNByte(vx, byteSize), gmath.BigIntToNByte(vy, byteSize), za, rs.z) return outKey, tempKeyOfResponsor, nil }