OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / bn256 / optate.go
1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package bn256
6
7 func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
8         // See the mixed addition algorithm from "Faster Computation of the
9         // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
10
11         B := newGFp2(pool).Mul(p.x, r.t, pool)
12
13         D := newGFp2(pool).Add(p.y, r.z)
14         D.Square(D, pool)
15         D.Sub(D, r2)
16         D.Sub(D, r.t)
17         D.Mul(D, r.t, pool)
18
19         H := newGFp2(pool).Sub(B, r.x)
20         I := newGFp2(pool).Square(H, pool)
21
22         E := newGFp2(pool).Add(I, I)
23         E.Add(E, E)
24
25         J := newGFp2(pool).Mul(H, E, pool)
26
27         L1 := newGFp2(pool).Sub(D, r.y)
28         L1.Sub(L1, r.y)
29
30         V := newGFp2(pool).Mul(r.x, E, pool)
31
32         rOut = newTwistPoint(pool)
33         rOut.x.Square(L1, pool)
34         rOut.x.Sub(rOut.x, J)
35         rOut.x.Sub(rOut.x, V)
36         rOut.x.Sub(rOut.x, V)
37
38         rOut.z.Add(r.z, H)
39         rOut.z.Square(rOut.z, pool)
40         rOut.z.Sub(rOut.z, r.t)
41         rOut.z.Sub(rOut.z, I)
42
43         t := newGFp2(pool).Sub(V, rOut.x)
44         t.Mul(t, L1, pool)
45         t2 := newGFp2(pool).Mul(r.y, J, pool)
46         t2.Add(t2, t2)
47         rOut.y.Sub(t, t2)
48
49         rOut.t.Square(rOut.z, pool)
50
51         t.Add(p.y, rOut.z)
52         t.Square(t, pool)
53         t.Sub(t, r2)
54         t.Sub(t, rOut.t)
55
56         t2.Mul(L1, p.x, pool)
57         t2.Add(t2, t2)
58         a = newGFp2(pool)
59         a.Sub(t2, t)
60
61         c = newGFp2(pool)
62         c.MulScalar(rOut.z, q.y)
63         c.Add(c, c)
64
65         b = newGFp2(pool)
66         b.SetZero()
67         b.Sub(b, L1)
68         b.MulScalar(b, q.x)
69         b.Add(b, b)
70
71         B.Put(pool)
72         D.Put(pool)
73         H.Put(pool)
74         I.Put(pool)
75         E.Put(pool)
76         J.Put(pool)
77         L1.Put(pool)
78         V.Put(pool)
79         t.Put(pool)
80         t2.Put(pool)
81
82         return
83 }
84
85 func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
86         // See the doubling algorithm for a=0 from "Faster Computation of the
87         // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
88
89         A := newGFp2(pool).Square(r.x, pool)
90         B := newGFp2(pool).Square(r.y, pool)
91         C := newGFp2(pool).Square(B, pool)
92
93         D := newGFp2(pool).Add(r.x, B)
94         D.Square(D, pool)
95         D.Sub(D, A)
96         D.Sub(D, C)
97         D.Add(D, D)
98
99         E := newGFp2(pool).Add(A, A)
100         E.Add(E, A)
101
102         G := newGFp2(pool).Square(E, pool)
103
104         rOut = newTwistPoint(pool)
105         rOut.x.Sub(G, D)
106         rOut.x.Sub(rOut.x, D)
107
108         rOut.z.Add(r.y, r.z)
109         rOut.z.Square(rOut.z, pool)
110         rOut.z.Sub(rOut.z, B)
111         rOut.z.Sub(rOut.z, r.t)
112
113         rOut.y.Sub(D, rOut.x)
114         rOut.y.Mul(rOut.y, E, pool)
115         t := newGFp2(pool).Add(C, C)
116         t.Add(t, t)
117         t.Add(t, t)
118         rOut.y.Sub(rOut.y, t)
119
120         rOut.t.Square(rOut.z, pool)
121
122         t.Mul(E, r.t, pool)
123         t.Add(t, t)
124         b = newGFp2(pool)
125         b.SetZero()
126         b.Sub(b, t)
127         b.MulScalar(b, q.x)
128
129         a = newGFp2(pool)
130         a.Add(r.x, E)
131         a.Square(a, pool)
132         a.Sub(a, A)
133         a.Sub(a, G)
134         t.Add(B, B)
135         t.Add(t, t)
136         a.Sub(a, t)
137
138         c = newGFp2(pool)
139         c.Mul(rOut.z, r.t, pool)
140         c.Add(c, c)
141         c.MulScalar(c, q.y)
142
143         A.Put(pool)
144         B.Put(pool)
145         C.Put(pool)
146         D.Put(pool)
147         E.Put(pool)
148         G.Put(pool)
149         t.Put(pool)
150
151         return
152 }
153
154 func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
155         a2 := newGFp6(pool)
156         a2.x.SetZero()
157         a2.y.Set(a)
158         a2.z.Set(b)
159         a2.Mul(a2, ret.x, pool)
160         t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
161
162         t := newGFp2(pool)
163         t.Add(b, c)
164         t2 := newGFp6(pool)
165         t2.x.SetZero()
166         t2.y.Set(a)
167         t2.z.Set(t)
168         ret.x.Add(ret.x, ret.y)
169
170         ret.y.Set(t3)
171
172         ret.x.Mul(ret.x, t2, pool)
173         ret.x.Sub(ret.x, a2)
174         ret.x.Sub(ret.x, ret.y)
175         a2.MulTau(a2, pool)
176         ret.y.Add(ret.y, a2)
177
178         a2.Put(pool)
179         t3.Put(pool)
180         t2.Put(pool)
181         t.Put(pool)
182 }
183
184 // sixuPlus2NAF is 6u+2 in non-adjacent form.
185 var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1}
186
187 // miller implements the Miller loop for calculating the Optimal Ate pairing.
188 // See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
189 func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
190         ret := newGFp12(pool)
191         ret.SetOne()
192
193         aAffine := newTwistPoint(pool)
194         aAffine.Set(q)
195         aAffine.MakeAffine(pool)
196
197         bAffine := newCurvePoint(pool)
198         bAffine.Set(p)
199         bAffine.MakeAffine(pool)
200
201         minusA := newTwistPoint(pool)
202         minusA.Negative(aAffine, pool)
203
204         r := newTwistPoint(pool)
205         r.Set(aAffine)
206
207         r2 := newGFp2(pool)
208         r2.Square(aAffine.y, pool)
209
210         for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
211                 a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
212                 if i != len(sixuPlus2NAF)-1 {
213                         ret.Square(ret, pool)
214                 }
215
216                 mulLine(ret, a, b, c, pool)
217                 a.Put(pool)
218                 b.Put(pool)
219                 c.Put(pool)
220                 r.Put(pool)
221                 r = newR
222
223                 switch sixuPlus2NAF[i-1] {
224                 case 1:
225                         a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
226                 case -1:
227                         a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
228                 default:
229                         continue
230                 }
231
232                 mulLine(ret, a, b, c, pool)
233                 a.Put(pool)
234                 b.Put(pool)
235                 c.Put(pool)
236                 r.Put(pool)
237                 r = newR
238         }
239
240         // In order to calculate Q1 we have to convert q from the sextic twist
241         // to the full GF(p^12) group, apply the Frobenius there, and convert
242         // back.
243         //
244         // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
245         // x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
246         // where x̄ is the conjugate of x. If we are going to apply the inverse
247         // isomorphism we need a value with a single coefficient of ω² so we
248         // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
249         // p, 2p-2 is a multiple of six. Therefore we can rewrite as
250         // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
251         // ω².
252         //
253         // A similar argument can be made for the y value.
254
255         q1 := newTwistPoint(pool)
256         q1.x.Conjugate(aAffine.x)
257         q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
258         q1.y.Conjugate(aAffine.y)
259         q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
260         q1.z.SetOne()
261         q1.t.SetOne()
262
263         // For Q2 we are applying the p² Frobenius. The two conjugations cancel
264         // out and we are left only with the factors from the isomorphism. In
265         // the case of x, we end up with a pure number which is why
266         // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
267         // ignore this to end up with -Q2.
268
269         minusQ2 := newTwistPoint(pool)
270         minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
271         minusQ2.y.Set(aAffine.y)
272         minusQ2.z.SetOne()
273         minusQ2.t.SetOne()
274
275         r2.Square(q1.y, pool)
276         a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
277         mulLine(ret, a, b, c, pool)
278         a.Put(pool)
279         b.Put(pool)
280         c.Put(pool)
281         r.Put(pool)
282         r = newR
283
284         r2.Square(minusQ2.y, pool)
285         a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
286         mulLine(ret, a, b, c, pool)
287         a.Put(pool)
288         b.Put(pool)
289         c.Put(pool)
290         r.Put(pool)
291         r = newR
292
293         aAffine.Put(pool)
294         bAffine.Put(pool)
295         minusA.Put(pool)
296         r.Put(pool)
297         r2.Put(pool)
298
299         return ret
300 }
301
302 // finalExponentiation computes the (p¹²-1)/Order-th power of an element of
303 // GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
304 // http://cryptojedi.org/papers/dclxvi-20100714.pdf)
305 func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
306         t1 := newGFp12(pool)
307
308         // This is the p^6-Frobenius
309         t1.x.Negative(in.x)
310         t1.y.Set(in.y)
311
312         inv := newGFp12(pool)
313         inv.Invert(in, pool)
314         t1.Mul(t1, inv, pool)
315
316         t2 := newGFp12(pool).FrobeniusP2(t1, pool)
317         t1.Mul(t1, t2, pool)
318
319         fp := newGFp12(pool).Frobenius(t1, pool)
320         fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
321         fp3 := newGFp12(pool).Frobenius(fp2, pool)
322
323         fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
324         fu.Exp(t1, u, pool)
325         fu2.Exp(fu, u, pool)
326         fu3.Exp(fu2, u, pool)
327
328         y3 := newGFp12(pool).Frobenius(fu, pool)
329         fu2p := newGFp12(pool).Frobenius(fu2, pool)
330         fu3p := newGFp12(pool).Frobenius(fu3, pool)
331         y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
332
333         y0 := newGFp12(pool)
334         y0.Mul(fp, fp2, pool)
335         y0.Mul(y0, fp3, pool)
336
337         y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
338         y1.Conjugate(t1)
339         y5.Conjugate(fu2)
340         y3.Conjugate(y3)
341         y4.Mul(fu, fu2p, pool)
342         y4.Conjugate(y4)
343
344         y6 := newGFp12(pool)
345         y6.Mul(fu3, fu3p, pool)
346         y6.Conjugate(y6)
347
348         t0 := newGFp12(pool)
349         t0.Square(y6, pool)
350         t0.Mul(t0, y4, pool)
351         t0.Mul(t0, y5, pool)
352         t1.Mul(y3, y5, pool)
353         t1.Mul(t1, t0, pool)
354         t0.Mul(t0, y2, pool)
355         t1.Square(t1, pool)
356         t1.Mul(t1, t0, pool)
357         t1.Square(t1, pool)
358         t0.Mul(t1, y1, pool)
359         t1.Mul(t1, y0, pool)
360         t0.Square(t0, pool)
361         t0.Mul(t0, t1, pool)
362
363         inv.Put(pool)
364         t1.Put(pool)
365         t2.Put(pool)
366         fp.Put(pool)
367         fp2.Put(pool)
368         fp3.Put(pool)
369         fu.Put(pool)
370         fu2.Put(pool)
371         fu3.Put(pool)
372         fu2p.Put(pool)
373         fu3p.Put(pool)
374         y0.Put(pool)
375         y1.Put(pool)
376         y2.Put(pool)
377         y3.Put(pool)
378         y4.Put(pool)
379         y5.Put(pool)
380         y6.Put(pool)
381
382         return t0
383 }
384
385 func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
386         e := miller(a, b, pool)
387         ret := finalExponentiation(e, pool)
388         e.Put(pool)
389
390         if a.IsInfinity() || b.IsInfinity() {
391                 ret.SetOne()
392         }
393
394         return ret
395 }