cryptofun/bn128/g2.go
bn128/g2.goRaw
1package bn128
2
3import (
4 "bytes"
5 "math/big"
6)
7
8type G2 struct {
9 F Fq2
10 G [3][2]*big.Int
11}
12
13func NewG2(f Fq2, g [2][2]*big.Int) G2 {
14 var g2 G2
15 g2.F = f
16 g2.G = [3][2]*big.Int{
17 g[0],
18 g[1],
19 g2.F.One(),
20 }
21 return g2
22}
23
24func (g2 G2) Zero() [3][2]*big.Int {
25 return [3][2]*big.Int{g2.F.Zero(), g2.F.One(), g2.F.Zero()}
26}
27func (g2 G2) IsZero(p [3][2]*big.Int) bool {
28 return g2.F.IsZero(p[2])
29}
30
31func (g2 G2) Add(p1, p2 [3][2]*big.Int) [3][2]*big.Int {
32
33 // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
34 // https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp#L208
35 // http://hyperelliptic.org/EFD/g2p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
36
37 if g2.IsZero(p1) {
38 return p2
39 }
40 if g2.IsZero(p2) {
41 return p1
42 }
43
44 x1 := p1[0]
45 y1 := p1[1]
46 z1 := p1[2]
47 x2 := p2[0]
48 y2 := p2[1]
49 z2 := p2[2]
50
51 z1z1 := g2.F.Square(z1)
52 z2z2 := g2.F.Square(z2)
53
54 u1 := g2.F.Mul(x1, z2z2)
55 u2 := g2.F.Mul(x2, z1z1)
56
57 t0 := g2.F.Mul(z2, z2z2)
58 s1 := g2.F.Mul(y1, t0)
59
60 t1 := g2.F.Mul(z1, z1z1)
61 s2 := g2.F.Mul(y2, t1)
62
63 h := g2.F.Sub(u2, u1)
64 t2 := g2.F.Add(h, h)
65 i := g2.F.Square(t2)
66 j := g2.F.Mul(h, i)
67 t3 := g2.F.Sub(s2, s1)
68 r := g2.F.Add(t3, t3)
69 v := g2.F.Mul(u1, i)
70 t4 := g2.F.Square(r)
71 t5 := g2.F.Add(v, v)
72 t6 := g2.F.Sub(t4, j)
73 x3 := g2.F.Sub(t6, t5)
74 t7 := g2.F.Sub(v, x3)
75 t8 := g2.F.Mul(s1, j)
76 t9 := g2.F.Add(t8, t8)
77 t10 := g2.F.Mul(r, t7)
78
79 y3 := g2.F.Sub(t10, t9)
80
81 t11 := g2.F.Add(z1, z2)
82 t12 := g2.F.Square(t11)
83 t13 := g2.F.Sub(t12, z1z1)
84 t14 := g2.F.Sub(t13, z2z2)
85 z3 := g2.F.Mul(t14, h)
86
87 return [3][2]*big.Int{x3, y3, z3}
88}
89
90func (g2 G2) Neg(p [3][2]*big.Int) [3][2]*big.Int {
91 return [3][2]*big.Int{
92 p[0],
93 g2.F.Neg(p[1]),
94 p[2],
95 }
96}
97
98func (g2 G2) Sub(a, b [3][2]*big.Int) [3][2]*big.Int {
99 return g2.Add(a, g2.Neg(b))
100}
101
102func (g2 G2) Double(p [3][2]*big.Int) [3][2]*big.Int {
103
104 // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
105 // http://hyperelliptic.org/EFD/g2p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
106 // https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp#L325
107
108 if g2.IsZero(p) {
109 return p
110 }
111
112 a := g2.F.Square(p[0])
113 b := g2.F.Square(p[1])
114 c := g2.F.Square(b)
115
116 t0 := g2.F.Add(p[0], b)
117 t1 := g2.F.Square(t0)
118 t2 := g2.F.Sub(t1, a)
119 t3 := g2.F.Sub(t2, c)
120
121 d := g2.F.Double(t3)
122 e := g2.F.Add(g2.F.Add(a, a), a) // e = 3*a
123 f := g2.F.Square(e)
124
125 t4 := g2.F.Double(d)
126 x3 := g2.F.Sub(f, t4)
127
128 t5 := g2.F.Sub(d, x3)
129 twoC := g2.F.Add(c, c)
130 fourC := g2.F.Add(twoC, twoC)
131 t6 := g2.F.Add(fourC, fourC)
132 t7 := g2.F.Mul(e, t5)
133 y3 := g2.F.Sub(t7, t6)
134
135 t8 := g2.F.Mul(p[1], p[2])
136 z3 := g2.F.Double(t8)
137
138 return [3][2]*big.Int{x3, y3, z3}
139}
140
141func (g2 G2) MulScalar(base [3][2]*big.Int, e *big.Int) [3][2]*big.Int {
142 // res := g2.Zero()
143 res := [3][2]*big.Int{g2.F.Zero(), g2.F.Zero(), g2.F.Zero()}
144 rem := e
145 exp := base
146
147 for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
148 // if rem % 2 == 1
149 if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
150 res = g2.Add(res, exp)
151 }
152 exp = g2.Double(exp)
153 rem = rem.Rsh(rem, 1) // rem = rem >> 1
154 }
155 return res
156}
157
158func (g2 G2) Affine(p [3][2]*big.Int) [3][2]*big.Int {
159 if g2.IsZero(p) {
160 return g2.Zero()
161 }
162
163 zinv := g2.F.Inverse(p[2])
164 zinv2 := g2.F.Square(zinv)
165 x := g2.F.Mul(p[0], zinv2)
166
167 zinv3 := g2.F.Mul(zinv2, zinv)
168 y := g2.F.Mul(p[1], zinv3)
169
170 return [3][2]*big.Int{
171 x,
172 y,
173 [2]*big.Int{
174 big.NewInt(int64(0)),
175 big.NewInt(int64(0)),
176 },
177 }
178}