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