1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package bn256
6
7import (
8	"bytes"
9	"crypto/rand"
10	"math/big"
11	"testing"
12)
13
14func TestGFp2Invert(t *testing.T) {
15	pool := new(bnPool)
16
17	a := newGFp2(pool)
18	a.x.SetString("23423492374", 10)
19	a.y.SetString("12934872398472394827398470", 10)
20
21	inv := newGFp2(pool)
22	inv.Invert(a, pool)
23
24	b := newGFp2(pool).Mul(inv, a, pool)
25	if b.x.Int64() != 0 || b.y.Int64() != 1 {
26		t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y)
27	}
28
29	a.Put(pool)
30	b.Put(pool)
31	inv.Put(pool)
32
33	if c := pool.Count(); c > 0 {
34		t.Errorf("Pool count non-zero: %d\n", c)
35	}
36}
37
38func isZero(n *big.Int) bool {
39	return new(big.Int).Mod(n, p).Int64() == 0
40}
41
42func isOne(n *big.Int) bool {
43	return new(big.Int).Mod(n, p).Int64() == 1
44}
45
46func TestGFp6Invert(t *testing.T) {
47	pool := new(bnPool)
48
49	a := newGFp6(pool)
50	a.x.x.SetString("239487238491", 10)
51	a.x.y.SetString("2356249827341", 10)
52	a.y.x.SetString("082659782", 10)
53	a.y.y.SetString("182703523765", 10)
54	a.z.x.SetString("978236549263", 10)
55	a.z.y.SetString("64893242", 10)
56
57	inv := newGFp6(pool)
58	inv.Invert(a, pool)
59
60	b := newGFp6(pool).Mul(inv, a, pool)
61	if !isZero(b.x.x) ||
62		!isZero(b.x.y) ||
63		!isZero(b.y.x) ||
64		!isZero(b.y.y) ||
65		!isZero(b.z.x) ||
66		!isOne(b.z.y) {
67		t.Fatalf("bad result for a^-1*a: %s", b)
68	}
69
70	a.Put(pool)
71	b.Put(pool)
72	inv.Put(pool)
73
74	if c := pool.Count(); c > 0 {
75		t.Errorf("Pool count non-zero: %d\n", c)
76	}
77}
78
79func TestGFp12Invert(t *testing.T) {
80	pool := new(bnPool)
81
82	a := newGFp12(pool)
83	a.x.x.x.SetString("239846234862342323958623", 10)
84	a.x.x.y.SetString("2359862352529835623", 10)
85	a.x.y.x.SetString("928836523", 10)
86	a.x.y.y.SetString("9856234", 10)
87	a.x.z.x.SetString("235635286", 10)
88	a.x.z.y.SetString("5628392833", 10)
89	a.y.x.x.SetString("252936598265329856238956532167968", 10)
90	a.y.x.y.SetString("23596239865236954178968", 10)
91	a.y.y.x.SetString("95421692834", 10)
92	a.y.y.y.SetString("236548", 10)
93	a.y.z.x.SetString("924523", 10)
94	a.y.z.y.SetString("12954623", 10)
95
96	inv := newGFp12(pool)
97	inv.Invert(a, pool)
98
99	b := newGFp12(pool).Mul(inv, a, pool)
100	if !isZero(b.x.x.x) ||
101		!isZero(b.x.x.y) ||
102		!isZero(b.x.y.x) ||
103		!isZero(b.x.y.y) ||
104		!isZero(b.x.z.x) ||
105		!isZero(b.x.z.y) ||
106		!isZero(b.y.x.x) ||
107		!isZero(b.y.x.y) ||
108		!isZero(b.y.y.x) ||
109		!isZero(b.y.y.y) ||
110		!isZero(b.y.z.x) ||
111		!isOne(b.y.z.y) {
112		t.Fatalf("bad result for a^-1*a: %s", b)
113	}
114
115	a.Put(pool)
116	b.Put(pool)
117	inv.Put(pool)
118
119	if c := pool.Count(); c > 0 {
120		t.Errorf("Pool count non-zero: %d\n", c)
121	}
122}
123
124func TestCurveImpl(t *testing.T) {
125	pool := new(bnPool)
126
127	g := &curvePoint{
128		pool.Get().SetInt64(1),
129		pool.Get().SetInt64(-2),
130		pool.Get().SetInt64(1),
131		pool.Get().SetInt64(0),
132	}
133
134	x := pool.Get().SetInt64(32498273234)
135	X := newCurvePoint(pool).Mul(g, x, pool)
136
137	y := pool.Get().SetInt64(98732423523)
138	Y := newCurvePoint(pool).Mul(g, y, pool)
139
140	s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool)
141	s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool)
142
143	if s1.x.Cmp(s2.x) != 0 ||
144		s2.x.Cmp(s1.x) != 0 {
145		t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y)
146	}
147
148	pool.Put(x)
149	X.Put(pool)
150	pool.Put(y)
151	Y.Put(pool)
152	s1.Put(pool)
153	s2.Put(pool)
154	g.Put(pool)
155
156	if c := pool.Count(); c > 0 {
157		t.Errorf("Pool count non-zero: %d\n", c)
158	}
159}
160
161func TestOrderG1(t *testing.T) {
162	g := new(G1).ScalarBaseMult(Order)
163	if !g.p.IsInfinity() {
164		t.Error("G1 has incorrect order")
165	}
166
167	one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
168	g.Add(g, one)
169	g.p.MakeAffine(nil)
170	if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 {
171		t.Errorf("1+0 != 1 in G1")
172	}
173}
174
175func TestOrderG2(t *testing.T) {
176	g := new(G2).ScalarBaseMult(Order)
177	if !g.p.IsInfinity() {
178		t.Error("G2 has incorrect order")
179	}
180
181	one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
182	g.Add(g, one)
183	g.p.MakeAffine(nil)
184	if g.p.x.x.Cmp(one.p.x.x) != 0 ||
185		g.p.x.y.Cmp(one.p.x.y) != 0 ||
186		g.p.y.x.Cmp(one.p.y.x) != 0 ||
187		g.p.y.y.Cmp(one.p.y.y) != 0 {
188		t.Errorf("1+0 != 1 in G2")
189	}
190}
191
192func TestOrderGT(t *testing.T) {
193	gt := Pair(&G1{curveGen}, &G2{twistGen})
194	g := new(GT).ScalarMult(gt, Order)
195	if !g.p.IsOne() {
196		t.Error("GT has incorrect order")
197	}
198}
199
200func TestBilinearity(t *testing.T) {
201	for i := 0; i < 2; i++ {
202		a, p1, _ := RandomG1(rand.Reader)
203		b, p2, _ := RandomG2(rand.Reader)
204		e1 := Pair(p1, p2)
205
206		e2 := Pair(&G1{curveGen}, &G2{twistGen})
207		e2.ScalarMult(e2, a)
208		e2.ScalarMult(e2, b)
209
210		minusE2 := new(GT).Neg(e2)
211		e1.Add(e1, minusE2)
212
213		if !e1.p.IsOne() {
214			t.Fatalf("bad pairing result: %s", e1)
215		}
216	}
217}
218
219func TestG1Marshal(t *testing.T) {
220	g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
221	form := g.Marshal()
222	_, ok := new(G1).Unmarshal(form)
223	if !ok {
224		t.Fatalf("failed to unmarshal")
225	}
226
227	g.ScalarBaseMult(Order)
228	form = g.Marshal()
229	g2, ok := new(G1).Unmarshal(form)
230	if !ok {
231		t.Fatalf("failed to unmarshal ∞")
232	}
233	if !g2.p.IsInfinity() {
234		t.Fatalf("∞ unmarshaled incorrectly")
235	}
236}
237
238func TestG2Marshal(t *testing.T) {
239	g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
240	form := g.Marshal()
241	_, ok := new(G2).Unmarshal(form)
242	if !ok {
243		t.Fatalf("failed to unmarshal")
244	}
245
246	g.ScalarBaseMult(Order)
247	form = g.Marshal()
248	g2, ok := new(G2).Unmarshal(form)
249	if !ok {
250		t.Fatalf("failed to unmarshal ∞")
251	}
252	if !g2.p.IsInfinity() {
253		t.Fatalf("∞ unmarshaled incorrectly")
254	}
255}
256
257func TestG1Identity(t *testing.T) {
258	g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0))
259	if !g.p.IsInfinity() {
260		t.Error("failure")
261	}
262}
263
264func TestG2Identity(t *testing.T) {
265	g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0))
266	if !g.p.IsInfinity() {
267		t.Error("failure")
268	}
269}
270
271func TestTripartiteDiffieHellman(t *testing.T) {
272	a, _ := rand.Int(rand.Reader, Order)
273	b, _ := rand.Int(rand.Reader, Order)
274	c, _ := rand.Int(rand.Reader, Order)
275
276	pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal())
277	qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal())
278	pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal())
279	qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal())
280	pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal())
281	qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal())
282
283	k1 := Pair(pb, qc)
284	k1.ScalarMult(k1, a)
285	k1Bytes := k1.Marshal()
286
287	k2 := Pair(pc, qa)
288	k2.ScalarMult(k2, b)
289	k2Bytes := k2.Marshal()
290
291	k3 := Pair(pa, qb)
292	k3.ScalarMult(k3, c)
293	k3Bytes := k3.Marshal()
294
295	if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) {
296		t.Errorf("keys didn't agree")
297	}
298}
299
300func BenchmarkPairing(b *testing.B) {
301	for i := 0; i < b.N; i++ {
302		Pair(&G1{curveGen}, &G2{twistGen})
303	}
304}
305