go-snark/fields/fq2.go
fields/fq2.goRaw
1package fields
2
3import (
4 "math/big"
5)
6
7// Fq2 is Field 2
8type Fq2 struct {
9 F Fq
10 NonResidue *big.Int
11}
12
13// NewFq2 generates a new Fq2
14func NewFq2(f Fq, nonResidue *big.Int) Fq2 {
15 fq2 := Fq2{
16 f,
17 nonResidue,
18 }
19 return fq2
20}
21
22// Zero returns a Zero value on the Fq2
23func (fq2 Fq2) Zero() [2]*big.Int {
24 return [2]*big.Int{fq2.F.Zero(), fq2.F.Zero()}
25}
26
27// One returns a One value on the Fq2
28func (fq2 Fq2) One() [2]*big.Int {
29 return [2]*big.Int{fq2.F.One(), fq2.F.Zero()}
30}
31
32func (fq2 Fq2) mulByNonResidue(a *big.Int) *big.Int {
33 return fq2.F.Mul(fq2.NonResidue, a)
34}
35
36// Add performs an addition on the Fq2
37func (fq2 Fq2) Add(a, b [2]*big.Int) [2]*big.Int {
38 return [2]*big.Int{
39 fq2.F.Add(a[0], b[0]),
40 fq2.F.Add(a[1], b[1]),
41 }
42}
43
44// Double performs a doubling on the Fq2
45func (fq2 Fq2) Double(a [2]*big.Int) [2]*big.Int {
46 return fq2.Add(a, a)
47}
48
49// Sub performs a subtraction on the Fq2
50func (fq2 Fq2) Sub(a, b [2]*big.Int) [2]*big.Int {
51 return [2]*big.Int{
52 fq2.F.Sub(a[0], b[0]),
53 fq2.F.Sub(a[1], b[1]),
54 }
55}
56
57// Neg performs a negation on the Fq2
58func (fq2 Fq2) Neg(a [2]*big.Int) [2]*big.Int {
59 return fq2.Sub(fq2.Zero(), a)
60}
61
62// Mul performs a multiplication on the Fq2
63func (fq2 Fq2) Mul(a, b [2]*big.Int) [2]*big.Int {
64 // Multiplication and Squaring on Pairing-Friendly.pdf; Section 3 (Karatsuba)
65 // https://pdfs.semanticscholar.org/3e01/de88d7428076b2547b60072088507d881bf1.pdf
66 v0 := fq2.F.Mul(a[0], b[0])
67 v1 := fq2.F.Mul(a[1], b[1])
68 return [2]*big.Int{
69 fq2.F.Add(v0, fq2.mulByNonResidue(v1)),
70 fq2.F.Sub(
71 fq2.F.Mul(
72 fq2.F.Add(a[0], a[1]),
73 fq2.F.Add(b[0], b[1])),
74 fq2.F.Add(v0, v1)),
75 }
76}
77
78func (fq2 Fq2) MulScalar(p [2]*big.Int, e *big.Int) [2]*big.Int {
79 // for more possible implementations see g2.go file, at the function g2.MulScalar()
80
81 q := fq2.Zero()
82 d := fq2.F.Copy(e)
83 r := p
84
85 foundone := false
86 for i := d.BitLen(); i >= 0; i-- {
87 if foundone {
88 q = fq2.Double(q)
89 }
90 if d.Bit(i) == 1 {
91 foundone = true
92 q = fq2.Add(q, r)
93 }
94 }
95 return q
96}
97
98// Inverse returns the inverse on the Fq2
99func (fq2 Fq2) Inverse(a [2]*big.Int) [2]*big.Int {
100 // High-Speed Software Implementation of the Optimal Ate Pairing over Barreto–Naehrig Curves .pdf
101 // https://eprint.iacr.org/2010/354.pdf , algorithm 8
102 t0 := fq2.F.Square(a[0])
103 t1 := fq2.F.Square(a[1])
104 t2 := fq2.F.Sub(t0, fq2.mulByNonResidue(t1))
105 t3 := fq2.F.Inverse(t2)
106 return [2]*big.Int{
107 fq2.F.Mul(a[0], t3),
108 fq2.F.Neg(fq2.F.Mul(a[1], t3)),
109 }
110}
111
112// Div performs a division on the Fq2
113func (fq2 Fq2) Div(a, b [2]*big.Int) [2]*big.Int {
114 return fq2.Mul(a, fq2.Inverse(b))
115}
116
117// Square performs a square operation on the Fq2
118func (fq2 Fq2) Square(a [2]*big.Int) [2]*big.Int {
119 // https://pdfs.semanticscholar.org/3e01/de88d7428076b2547b60072088507d881bf1.pdf , complex squaring
120 ab := fq2.F.Mul(a[0], a[1])
121 return [2]*big.Int{
122 fq2.F.Sub(
123 fq2.F.Mul(
124 fq2.F.Add(a[0], a[1]),
125 fq2.F.Add(
126 a[0],
127 fq2.mulByNonResidue(a[1]))),
128 fq2.F.Add(
129 ab,
130 fq2.mulByNonResidue(ab))),
131 fq2.F.Add(ab, ab),
132 }
133}
134
135func (fq2 Fq2) IsZero(a [2]*big.Int) bool {
136 return fq2.F.IsZero(a[0]) && fq2.F.IsZero(a[1])
137}
138
139func (fq2 Fq2) Affine(a [2]*big.Int) [2]*big.Int {
140 return [2]*big.Int{
141 fq2.F.Affine(a[0]),
142 fq2.F.Affine(a[1]),
143 }
144}
145func (fq2 Fq2) Equal(a, b [2]*big.Int) bool {
146 return fq2.F.Equal(a[0], b[0]) && fq2.F.Equal(a[1], b[1])
147}
148
149func (fq2 Fq2) Copy(a [2]*big.Int) [2]*big.Int {
150 return [2]*big.Int{
151 fq2.F.Copy(a[0]),
152 fq2.F.Copy(a[1]),
153 }
154}