From dff29c24c6b25f21b2553a4ee004e95347d23434 Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Fri, 10 Jun 2022 14:44:51 +0800 Subject: [PATCH] chang to use NAF method in miller loop --- sm9/bn_pair.go | 23 +++++++++++++++++------ sm9/constants.go | 2 ++ sm9/sm9_key.go | 16 ++++++++++++++-- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/sm9/bn_pair.go b/sm9/bn_pair.go index 8bce124..6a6737a 100644 --- a/sm9/bn_pair.go +++ b/sm9/bn_pair.go @@ -132,6 +132,9 @@ func miller(q *twistPoint, p *curvePoint) *gfP12 { aAffine.Set(q) aAffine.MakeAffine() + minusA := &twistPoint{} + minusA.Neg(aAffine) + bAffine := &curvePoint{} bAffine.Set(p) bAffine.MakeAffine() @@ -141,17 +144,25 @@ func miller(q *twistPoint, p *curvePoint) *gfP12 { r2 := (&gfP2{}).Square(&aAffine.y) - for i := sixUPlus2.BitLen() - 2; i >= 0; i-- { - ret.Square(ret) - retDen.Square(retDen) + for i := len(sixUPlus2NAF) - 1; i > 0; i-- { a, b, c, d, newR := lineFunctionDouble(r, bAffine) + if i != len(sixUPlus2NAF)-1 { + ret.Square(ret) + retDen.Square(retDen) + } mulLine(ret, retDen, a, b, c, d) r = newR - if sixUPlus2.Bit(i) == 1 { + switch sixUPlus2NAF[i-1] { + case 1: a, b, c, d, newR = lineFunctionAdd(r, aAffine, bAffine, r2) - mulLine(ret, retDen, a, b, c, d) - r = newR + case -1: + a, b, c, d, newR = lineFunctionAdd(r, minusA, bAffine, r2) + default: + continue } + + mulLine(ret, retDen, a, b, c, d) + r = newR } q1 := &twistPoint{} q1.x.Conjugate(&aAffine.x) diff --git a/sm9/constants.go b/sm9/constants.go index 41836f5..c49a3b9 100644 --- a/sm9/constants.go +++ b/sm9/constants.go @@ -6,6 +6,8 @@ var u = bigFromHex("600000000058f98a") // sixUPlus2 = 6*u+2 var sixUPlus2 = bigFromHex("02400000000215d93e") +var sixUPlus2NAF = []int8{0, -1, 0, 0, 0, 0, 1, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1} + // sixUPlus5 = 6*u+5 var sixUPlus5 = bigFromHex("02400000000215d941") diff --git a/sm9/sm9_key.go b/sm9/sm9_key.go index 2758cf0..2101ef1 100644 --- a/sm9/sm9_key.go +++ b/sm9/sm9_key.go @@ -80,9 +80,10 @@ func (master *SignMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*Sign if t1.Sign() == 0 { return nil, errors.New("sm9: need to re-generate sign master private key") } - t1.ModInverse(t1, Order) + t1 = fermatInverse(t1, Order) t2 := new(big.Int).Mul(t1, master.D) t2.Mod(t2, Order) + priv := new(SignPrivateKey) priv.SignMasterPublicKey = master.SignMasterPublicKey priv.PrivateKey = new(G1).ScalarBaseMult(t2) @@ -186,7 +187,7 @@ func (master *EncryptMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*E if t1.Sign() == 0 { return nil, errors.New("sm9: need to re-generate encrypt master private key") } - t1.ModInverse(t1, Order) + t1 = fermatInverse(t1, Order) t2 := new(big.Int).Mul(t1, master.D) t2.Mod(t2, Order) @@ -288,3 +289,14 @@ func (priv *EncryptPrivateKey) UnmarshalASN1(der []byte) error { priv.PrivateKey = g return nil } + +// fermatInverse calculates the inverse of k in GF(P) using Fermat's method +// (exponentiation modulo P - 2, per Euler's theorem). This has better +// constant-time properties than Euclid's method (implemented in +// math/big.Int.ModInverse and FIPS 186-4, Appendix C.1) although math/big +// itself isn't strictly constant-time so it's not perfect. +func fermatInverse(k, N *big.Int) *big.Int { + two := big.NewInt(2) + nMinus2 := new(big.Int).Sub(N, two) + return new(big.Int).Exp(k, nMinus2, N) +}