arnaucube
arnaucube/cryptofunPublic Self-hosted repository
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}