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