Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miller Loop on the twist #26

Merged
merged 16 commits into from
Jan 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions bls377/bls377.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ const ID = gurvy.BLS377
// bCurveCoeff b coeff of the curve
var bCurveCoeff fp.Element

// twist
var twist fptower.E2

// bTwistCurveCoeff b coeff of the twist (defined over Fp2) curve
var bTwistCurveCoeff fptower.E2

// twoInv 1/2 mod p (needed for DoubleStep in Miller loop)
var twoInv fp.Element

// generators of the r-torsion group, resp. in ker(pi-id), ker(Tr)
var g1Gen G1Jac
var g2Gen G2Jac
Expand Down Expand Up @@ -78,8 +84,10 @@ type E12 = fptower.E12
func init() {

bCurveCoeff.SetUint64(1)
bTwistCurveCoeff.A1.SetUint64(1)
bTwistCurveCoeff.Inverse(&bTwistCurveCoeff)
twist.A1.SetUint64(1)
bTwistCurveCoeff.Inverse(&twist)

twoInv.SetOne().Double(&twoInv).Inverse(&twoInv)

g1Gen.X.SetString("68333130937826953018162399284085925021577172705782285525244777453303237942212457240213897533859360921141590695983")
g1Gen.Y.SetString("243386584320553125968203959498080829207604143167922579970841210259134422887279629198736754149500839244552761526603")
Expand Down
26 changes: 23 additions & 3 deletions bls377/g1.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 23 additions & 3 deletions bls377/g2.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions bls377/internal/fptower/e12_pairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,54 @@ func (z *E12) MulByV2W(x *E12, y *E2) *E12 {
z.Set(&result)
return z
}

// MulBy034 multiplication by sparse element
func (z *E12) MulBy034(c0, c3, c4 *E2) *E12 {

var z0, z1, z2, z3, z4, z5, tmp1, tmp2 E2
var t [12]E2

z0 = z.C0.B0
z1 = z.C0.B1
z2 = z.C0.B2
z3 = z.C1.B0
z4 = z.C1.B1
z5 = z.C1.B2

tmp1.MulByNonResidue(c3)
tmp2.MulByNonResidue(c4)

t[0].Mul(&tmp1, &z5)
t[1].Mul(&tmp2, &z4)
t[2].Mul(c3, &z3)
t[3].Mul(&tmp2, &z5)
t[4].Mul(c3, &z4)
t[5].Mul(c4, &z3)
t[6].Mul(c3, &z0)
t[7].Mul(&tmp2, &z2)
t[8].Mul(c3, &z1)
t[9].Mul(c4, &z0)
t[10].Mul(c3, &z2)
t[11].Mul(c4, &z1)

z.C0.B0.Mul(c0, &z0).
Add(&z.C0.B0, &t[0]).
Add(&z.C0.B0, &t[1])
z.C0.B1.Mul(c0, &z1).
Add(&z.C0.B1, &t[2]).
Add(&z.C0.B1, &t[3])
z.C0.B2.Mul(c0, &z2).
Add(&z.C0.B2, &t[4]).
Add(&z.C0.B2, &t[5])
z.C1.B0.Mul(c0, &z3).
Add(&z.C1.B0, &t[6]).
Add(&z.C1.B0, &t[7])
z.C1.B1.Mul(c0, &z4).
Add(&z.C1.B1, &t[8]).
Add(&z.C1.B1, &t[9])
z.C1.B2.Mul(c0, &z5).
Add(&z.C1.B2, &t[10]).
Add(&z.C1.B2, &t[11])

return z
}
141 changes: 93 additions & 48 deletions bls377/pairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) {
ch = append(ch, make(chan struct{}, 10))
evaluations = append(evaluations, lineEvalPool.Get().(*[69]lineEvaluation))

go preCompute(evaluations[k-countInf], &Q[k], &P[k], ch[k-countInf])
go preCompute(evaluations[k-countInf], &Q[k], ch[k-countInf])
}

nP = nP - countInf
Expand All @@ -146,14 +146,14 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) {
result.Square(&result)
for k := 0; k < nP; k++ {
<-ch[k]
mulAssign(&result, &evaluations[k][j])
lineEval(&result, &evaluations[k][j], &P[k])
}
j++

if loopCounter[i] == 1 {
for k := 0; k < nP; k++ {
<-ch[k]
mulAssign(&result, &evaluations[k][j])
lineEval(&result, &evaluations[k][j], &P[k])
}
j++
}
Expand All @@ -167,68 +167,113 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) {
return result, nil
}

// lineEval computes the evaluation of the line through Q, R (on the twist) at P
// Q, R are in jacobian coordinates
func lineEval(Q, R *G2Jac, P *G1Affine, result *lineEvaluation) {
func lineEval(z *GT, l *lineEvaluation, P *G1Affine) *GT {

// converts _Q and _R to projective coords
var _Q, _R g2Proj
_Q.FromJacobian(Q)
_R.FromJacobian(R)
l.r0.MulByElement(&l.r0, &P.Y)
l.r1.MulByElement(&l.r1, &P.X)

result.r1.Mul(&_Q.y, &_R.z)
result.r0.Mul(&_Q.z, &_R.x)
result.r2.Mul(&_Q.x, &_R.y)

_Q.z.Mul(&_Q.z, &_R.y)
_Q.x.Mul(&_Q.x, &_R.z)
_Q.y.Mul(&_Q.y, &_R.x)

result.r1.Sub(&result.r1, &_Q.z)
result.r0.Sub(&result.r0, &_Q.x)
result.r2.Sub(&result.r2, &_Q.y)

result.r1.MulByElement(&result.r1, &P.X)
result.r0.MulByElement(&result.r0, &P.Y)
}

func mulAssign(z *GT, l *lineEvaluation) *GT {

var a, b, c GT
a.MulByVW(z, &l.r1)
b.MulByV(z, &l.r0)
c.MulByV2W(z, &l.r2)
z.Add(&a, &b).Add(z, &c)
z.MulBy034(&l.r0, &l.r1, &l.r2)

return z
}

// precomputes the line evaluations used during the Miller loop.
func preCompute(evaluations *[69]lineEvaluation, Q *G2Affine, P *G1Affine, ch chan struct{}) {
func preCompute(evaluations *[69]lineEvaluation, Q *G2Affine, ch chan struct{}) {

var Q1, Q2, Qbuf G2Jac
Q1.FromAffine(Q)
Q2.FromAffine(Q)
Qbuf.FromAffine(Q)
var Qproj g2Proj
Qproj.FromAffine(Q)

j := 0

for i := len(loopCounter) - 2; i >= 0; i-- {

Q1.Set(&Q2)
Q2.Double(&Q1).Neg(&Q2)
lineEval(&Q1, &Q2, P, &evaluations[j]) // f(P), div(f) = 2(Q1)+(-2Q2)-3(O)
Qproj.DoubleStep(&evaluations[j])
ch <- struct{}{}
Q2.Neg(&Q2)
j++

if loopCounter[i] == 1 {
lineEval(&Q2, &Qbuf, P, &evaluations[j]) // f(P), div(f) = (Q2)+(Q)+(-Q2-Q)-3(O)
ch <- struct{}{}
Q2.AddMixed(Q)
if loopCounter[i] != 0 {
j++
Qproj.AddMixedStep(&evaluations[j], Q)
ch <- struct{}{}
}
j++
}

close(ch)
}

// DoubleStep doubles a point in Homogenous projective coordinates, and evaluates the line in Miller loop
// https://eprint.iacr.org/2013/722.pdf (Section 4.3)
func (p *g2Proj) DoubleStep(evaluations *lineEvaluation) {

// get some Element from our pool
var t0, t1, A, B, C, D, E, EE, F, G, H, I, J, K fptower.E2
t0.Mul(&p.x, &p.y)
A.MulByElement(&t0, &twoInv)
B.Square(&p.y)
C.Square(&p.z)
D.Double(&C).
Add(&D, &C)
E.Mul(&D, &bTwistCurveCoeff)
F.Double(&E).
Add(&F, &E)
G.Add(&B, &F)
G.MulByElement(&G, &twoInv)
H.Add(&p.y, &p.z).
Square(&H)
t1.Add(&B, &C)
H.Sub(&H, &t1)
I.Sub(&E, &B)
J.Square(&p.x)
EE.Square(&E)
K.Double(&EE).
Add(&K, &EE)

// X, Y, Z
p.x.Sub(&B, &F).
Mul(&p.x, &A)
p.y.Square(&G).
Sub(&p.y, &K)
p.z.Mul(&B, &H)

// Line evaluation
evaluations.r0.Neg(&H)
evaluations.r1.Double(&J).
Add(&evaluations.r1, &J)
evaluations.r2.Set(&I)
}

// AddMixedStep point addition in Mixed Homogenous projective and Affine coordinates
// https://eprint.iacr.org/2013/722.pdf (Section 4.3)
func (p *g2Proj) AddMixedStep(evaluations *lineEvaluation, a *G2Affine) {

// get some Element from our pool
var Y2Z1, X2Z1, O, L, C, D, E, F, G, H, t0, t1, t2, J fptower.E2
Y2Z1.Mul(&a.Y, &p.z)
O.Sub(&p.y, &Y2Z1)
X2Z1.Mul(&a.X, &p.z)
L.Sub(&p.x, &X2Z1)
C.Square(&O)
D.Square(&L)
E.Mul(&L, &D)
F.Mul(&p.z, &C)
G.Mul(&p.x, &D)
t0.Double(&G)
H.Add(&E, &F).
Sub(&H, &t0)
t1.Mul(&p.y, &E)

// X, Y, Z
p.x.Mul(&L, &H)
p.y.Sub(&G, &H).
Mul(&p.y, &O).
Sub(&p.y, &t1)
p.z.Mul(&E, &p.z)

t2.Mul(&L, &a.Y)
J.Mul(&a.X, &O).
Sub(&J, &t2)

// Line evaluation
evaluations.r0.Set(&L)
evaluations.r1.Neg(&O)
evaluations.r2.Set(&J)
}
Loading