github.com/0xsequence/ethkit@v1.25.0/go-ethereum/crypto/bls12381/fp_test.go (about)

     1  package bls12381
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"math/big"
     7  	"testing"
     8  )
     9  
    10  func TestFpSerialization(t *testing.T) {
    11  	t.Run("zero", func(t *testing.T) {
    12  		in := make([]byte, 48)
    13  		fe, err := fromBytes(in)
    14  		if err != nil {
    15  			t.Fatal(err)
    16  		}
    17  		if !fe.isZero() {
    18  			t.Fatal("bad serialization")
    19  		}
    20  		if !bytes.Equal(in, toBytes(fe)) {
    21  			t.Fatal("bad serialization")
    22  		}
    23  	})
    24  	t.Run("bytes", func(t *testing.T) {
    25  		for i := 0; i < fuz; i++ {
    26  			a, _ := new(fe).rand(rand.Reader)
    27  			b, err := fromBytes(toBytes(a))
    28  			if err != nil {
    29  				t.Fatal(err)
    30  			}
    31  			if !a.equal(b) {
    32  				t.Fatal("bad serialization")
    33  			}
    34  		}
    35  	})
    36  	t.Run("string", func(t *testing.T) {
    37  		for i := 0; i < fuz; i++ {
    38  			a, _ := new(fe).rand(rand.Reader)
    39  			b, err := fromString(toString(a))
    40  			if err != nil {
    41  				t.Fatal(err)
    42  			}
    43  			if !a.equal(b) {
    44  				t.Fatal("bad encoding or decoding")
    45  			}
    46  		}
    47  	})
    48  	t.Run("big", func(t *testing.T) {
    49  		for i := 0; i < fuz; i++ {
    50  			a, _ := new(fe).rand(rand.Reader)
    51  			b, err := fromBig(toBig(a))
    52  			if err != nil {
    53  				t.Fatal(err)
    54  			}
    55  			if !a.equal(b) {
    56  				t.Fatal("bad encoding or decoding")
    57  			}
    58  		}
    59  	})
    60  }
    61  
    62  func TestFpAdditionCrossAgainstBigInt(t *testing.T) {
    63  	for i := 0; i < fuz; i++ {
    64  		a, _ := new(fe).rand(rand.Reader)
    65  		b, _ := new(fe).rand(rand.Reader)
    66  		c := new(fe)
    67  		big_a := toBig(a)
    68  		big_b := toBig(b)
    69  		big_c := new(big.Int)
    70  		add(c, a, b)
    71  		out_1 := toBytes(c)
    72  		out_2 := padBytes(big_c.Add(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48)
    73  		if !bytes.Equal(out_1, out_2) {
    74  			t.Fatal("cross test against big.Int is not satisfied A")
    75  		}
    76  		double(c, a)
    77  		out_1 = toBytes(c)
    78  		out_2 = padBytes(big_c.Add(big_a, big_a).Mod(big_c, modulus.big()).Bytes(), 48)
    79  		if !bytes.Equal(out_1, out_2) {
    80  			t.Fatal("cross test against big.Int is not satisfied B")
    81  		}
    82  		sub(c, a, b)
    83  		out_1 = toBytes(c)
    84  		out_2 = padBytes(big_c.Sub(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48)
    85  		if !bytes.Equal(out_1, out_2) {
    86  			t.Fatal("cross test against big.Int is not satisfied C")
    87  		}
    88  		neg(c, a)
    89  		out_1 = toBytes(c)
    90  		out_2 = padBytes(big_c.Neg(big_a).Mod(big_c, modulus.big()).Bytes(), 48)
    91  		if !bytes.Equal(out_1, out_2) {
    92  			t.Fatal("cross test against big.Int is not satisfied D")
    93  		}
    94  	}
    95  }
    96  
    97  func TestFpAdditionCrossAgainstBigIntAssigned(t *testing.T) {
    98  	for i := 0; i < fuz; i++ {
    99  		a, _ := new(fe).rand(rand.Reader)
   100  		b, _ := new(fe).rand(rand.Reader)
   101  		big_a, big_b := toBig(a), toBig(b)
   102  		addAssign(a, b)
   103  		out_1 := toBytes(a)
   104  		out_2 := padBytes(big_a.Add(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), 48)
   105  		if !bytes.Equal(out_1, out_2) {
   106  			t.Fatal("cross test against big.Int is not satisfied A")
   107  		}
   108  		a, _ = new(fe).rand(rand.Reader)
   109  		big_a = toBig(a)
   110  		doubleAssign(a)
   111  		out_1 = toBytes(a)
   112  		out_2 = padBytes(big_a.Add(big_a, big_a).Mod(big_a, modulus.big()).Bytes(), 48)
   113  		if !bytes.Equal(out_1, out_2) {
   114  			t.Fatal("cross test against big.Int is not satisfied B")
   115  		}
   116  		a, _ = new(fe).rand(rand.Reader)
   117  		b, _ = new(fe).rand(rand.Reader)
   118  		big_a, big_b = toBig(a), toBig(b)
   119  		subAssign(a, b)
   120  		out_1 = toBytes(a)
   121  		out_2 = padBytes(big_a.Sub(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), 48)
   122  		if !bytes.Equal(out_1, out_2) {
   123  			t.Fatal("cross test against big.Int is not satisfied A")
   124  		}
   125  	}
   126  }
   127  
   128  func TestFpAdditionProperties(t *testing.T) {
   129  	for i := 0; i < fuz; i++ {
   130  		zero := new(fe).zero()
   131  		a, _ := new(fe).rand(rand.Reader)
   132  		b, _ := new(fe).rand(rand.Reader)
   133  		c_1, c_2 := new(fe), new(fe)
   134  		add(c_1, a, zero)
   135  		if !c_1.equal(a) {
   136  			t.Fatal("a + 0 == a")
   137  		}
   138  		sub(c_1, a, zero)
   139  		if !c_1.equal(a) {
   140  			t.Fatal("a - 0 == a")
   141  		}
   142  		double(c_1, zero)
   143  		if !c_1.equal(zero) {
   144  			t.Fatal("2 * 0 == 0")
   145  		}
   146  		neg(c_1, zero)
   147  		if !c_1.equal(zero) {
   148  			t.Fatal("-0 == 0")
   149  		}
   150  		sub(c_1, zero, a)
   151  		neg(c_2, a)
   152  		if !c_1.equal(c_2) {
   153  			t.Fatal("0-a == -a")
   154  		}
   155  		double(c_1, a)
   156  		add(c_2, a, a)
   157  		if !c_1.equal(c_2) {
   158  			t.Fatal("2 * a == a + a")
   159  		}
   160  		add(c_1, a, b)
   161  		add(c_2, b, a)
   162  		if !c_1.equal(c_2) {
   163  			t.Fatal("a + b = b + a")
   164  		}
   165  		sub(c_1, a, b)
   166  		sub(c_2, b, a)
   167  		neg(c_2, c_2)
   168  		if !c_1.equal(c_2) {
   169  			t.Fatal("a - b = - ( b - a )")
   170  		}
   171  		c_x, _ := new(fe).rand(rand.Reader)
   172  		add(c_1, a, b)
   173  		add(c_1, c_1, c_x)
   174  		add(c_2, a, c_x)
   175  		add(c_2, c_2, b)
   176  		if !c_1.equal(c_2) {
   177  			t.Fatal("(a + b) + c == (a + c ) + b")
   178  		}
   179  		sub(c_1, a, b)
   180  		sub(c_1, c_1, c_x)
   181  		sub(c_2, a, c_x)
   182  		sub(c_2, c_2, b)
   183  		if !c_1.equal(c_2) {
   184  			t.Fatal("(a - b) - c == (a - c ) -b")
   185  		}
   186  	}
   187  }
   188  
   189  func TestFpAdditionPropertiesAssigned(t *testing.T) {
   190  	for i := 0; i < fuz; i++ {
   191  		zero := new(fe).zero()
   192  		a, b := new(fe), new(fe)
   193  		_, _ = a.rand(rand.Reader)
   194  		b.set(a)
   195  		addAssign(a, zero)
   196  		if !a.equal(b) {
   197  			t.Fatal("a + 0 == a")
   198  		}
   199  		subAssign(a, zero)
   200  		if !a.equal(b) {
   201  			t.Fatal("a - 0 == a")
   202  		}
   203  		a.set(zero)
   204  		doubleAssign(a)
   205  		if !a.equal(zero) {
   206  			t.Fatal("2 * 0 == 0")
   207  		}
   208  		a.set(zero)
   209  		subAssign(a, b)
   210  		neg(b, b)
   211  		if !a.equal(b) {
   212  			t.Fatal("0-a == -a")
   213  		}
   214  		_, _ = a.rand(rand.Reader)
   215  		b.set(a)
   216  		doubleAssign(a)
   217  		addAssign(b, b)
   218  		if !a.equal(b) {
   219  			t.Fatal("2 * a == a + a")
   220  		}
   221  		_, _ = a.rand(rand.Reader)
   222  		_, _ = b.rand(rand.Reader)
   223  		c_1, c_2 := new(fe).set(a), new(fe).set(b)
   224  		addAssign(c_1, b)
   225  		addAssign(c_2, a)
   226  		if !c_1.equal(c_2) {
   227  			t.Fatal("a + b = b + a")
   228  		}
   229  		_, _ = a.rand(rand.Reader)
   230  		_, _ = b.rand(rand.Reader)
   231  		c_1.set(a)
   232  		c_2.set(b)
   233  		subAssign(c_1, b)
   234  		subAssign(c_2, a)
   235  		neg(c_2, c_2)
   236  		if !c_1.equal(c_2) {
   237  			t.Fatal("a - b = - ( b - a )")
   238  		}
   239  		_, _ = a.rand(rand.Reader)
   240  		_, _ = b.rand(rand.Reader)
   241  		c, _ := new(fe).rand(rand.Reader)
   242  		a0 := new(fe).set(a)
   243  		addAssign(a, b)
   244  		addAssign(a, c)
   245  		addAssign(b, c)
   246  		addAssign(b, a0)
   247  		if !a.equal(b) {
   248  			t.Fatal("(a + b) + c == (b + c) + a")
   249  		}
   250  		_, _ = a.rand(rand.Reader)
   251  		_, _ = b.rand(rand.Reader)
   252  		_, _ = c.rand(rand.Reader)
   253  		a0.set(a)
   254  		subAssign(a, b)
   255  		subAssign(a, c)
   256  		subAssign(a0, c)
   257  		subAssign(a0, b)
   258  		if !a.equal(a0) {
   259  			t.Fatal("(a - b) - c == (a - c) -b")
   260  		}
   261  	}
   262  }
   263  
   264  func TestFpLazyOperations(t *testing.T) {
   265  	for i := 0; i < fuz; i++ {
   266  		a, _ := new(fe).rand(rand.Reader)
   267  		b, _ := new(fe).rand(rand.Reader)
   268  		c, _ := new(fe).rand(rand.Reader)
   269  		c0 := new(fe)
   270  		c1 := new(fe)
   271  		ladd(c0, a, b)
   272  		add(c1, a, b)
   273  		mul(c0, c0, c)
   274  		mul(c1, c1, c)
   275  		if !c0.equal(c1) {
   276  			// l+ operator stands for lazy addition
   277  			t.Fatal("(a + b) * c == (a l+ b) * c")
   278  		}
   279  		_, _ = a.rand(rand.Reader)
   280  		b.set(a)
   281  		ldouble(a, a)
   282  		ladd(b, b, b)
   283  		if !a.equal(b) {
   284  			t.Fatal("2 l* a = a l+ a")
   285  		}
   286  		_, _ = a.rand(rand.Reader)
   287  		_, _ = b.rand(rand.Reader)
   288  		_, _ = c.rand(rand.Reader)
   289  		a0 := new(fe).set(a)
   290  		lsubAssign(a, b)
   291  		laddAssign(a, &modulus)
   292  		mul(a, a, c)
   293  		subAssign(a0, b)
   294  		mul(a0, a0, c)
   295  		if !a.equal(a0) {
   296  			t.Fatal("((a l- b) + p) * c = (a-b) * c")
   297  		}
   298  	}
   299  }
   300  
   301  func TestFpMultiplicationCrossAgainstBigInt(t *testing.T) {
   302  	for i := 0; i < fuz; i++ {
   303  		a, _ := new(fe).rand(rand.Reader)
   304  		b, _ := new(fe).rand(rand.Reader)
   305  		c := new(fe)
   306  		big_a := toBig(a)
   307  		big_b := toBig(b)
   308  		big_c := new(big.Int)
   309  		mul(c, a, b)
   310  		out_1 := toBytes(c)
   311  		out_2 := padBytes(big_c.Mul(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48)
   312  		if !bytes.Equal(out_1, out_2) {
   313  			t.Fatal("cross test against big.Int is not satisfied")
   314  		}
   315  	}
   316  }
   317  
   318  func TestFpMultiplicationProperties(t *testing.T) {
   319  	for i := 0; i < fuz; i++ {
   320  		a, _ := new(fe).rand(rand.Reader)
   321  		b, _ := new(fe).rand(rand.Reader)
   322  		zero, one := new(fe).zero(), new(fe).one()
   323  		c_1, c_2 := new(fe), new(fe)
   324  		mul(c_1, a, zero)
   325  		if !c_1.equal(zero) {
   326  			t.Fatal("a * 0 == 0")
   327  		}
   328  		mul(c_1, a, one)
   329  		if !c_1.equal(a) {
   330  			t.Fatal("a * 1 == a")
   331  		}
   332  		mul(c_1, a, b)
   333  		mul(c_2, b, a)
   334  		if !c_1.equal(c_2) {
   335  			t.Fatal("a * b == b * a")
   336  		}
   337  		c_x, _ := new(fe).rand(rand.Reader)
   338  		mul(c_1, a, b)
   339  		mul(c_1, c_1, c_x)
   340  		mul(c_2, c_x, b)
   341  		mul(c_2, c_2, a)
   342  		if !c_1.equal(c_2) {
   343  			t.Fatal("(a * b) * c == (a * c) * b")
   344  		}
   345  		square(a, zero)
   346  		if !a.equal(zero) {
   347  			t.Fatal("0^2 == 0")
   348  		}
   349  		square(a, one)
   350  		if !a.equal(one) {
   351  			t.Fatal("1^2 == 1")
   352  		}
   353  		_, _ = a.rand(rand.Reader)
   354  		square(c_1, a)
   355  		mul(c_2, a, a)
   356  		if !c_1.equal(c_1) {
   357  			t.Fatal("a^2 == a*a")
   358  		}
   359  	}
   360  }
   361  
   362  func TestFpExponentiation(t *testing.T) {
   363  	for i := 0; i < fuz; i++ {
   364  		a, _ := new(fe).rand(rand.Reader)
   365  		u := new(fe)
   366  		exp(u, a, big.NewInt(0))
   367  		if !u.isOne() {
   368  			t.Fatal("a^0 == 1")
   369  		}
   370  		exp(u, a, big.NewInt(1))
   371  		if !u.equal(a) {
   372  			t.Fatal("a^1 == a")
   373  		}
   374  		v := new(fe)
   375  		mul(u, a, a)
   376  		mul(u, u, u)
   377  		mul(u, u, u)
   378  		exp(v, a, big.NewInt(8))
   379  		if !u.equal(v) {
   380  			t.Fatal("((a^2)^2)^2 == a^8")
   381  		}
   382  		p := modulus.big()
   383  		exp(u, a, p)
   384  		if !u.equal(a) {
   385  			t.Fatal("a^p == a")
   386  		}
   387  		exp(u, a, p.Sub(p, big.NewInt(1)))
   388  		if !u.isOne() {
   389  			t.Fatal("a^(p-1) == 1")
   390  		}
   391  	}
   392  }
   393  
   394  func TestFpInversion(t *testing.T) {
   395  	for i := 0; i < fuz; i++ {
   396  		u := new(fe)
   397  		zero, one := new(fe).zero(), new(fe).one()
   398  		inverse(u, zero)
   399  		if !u.equal(zero) {
   400  			t.Fatal("(0^-1) == 0)")
   401  		}
   402  		inverse(u, one)
   403  		if !u.equal(one) {
   404  			t.Fatal("(1^-1) == 1)")
   405  		}
   406  		a, _ := new(fe).rand(rand.Reader)
   407  		inverse(u, a)
   408  		mul(u, u, a)
   409  		if !u.equal(one) {
   410  			t.Fatal("(r*a) * r*(a^-1) == r)")
   411  		}
   412  		v := new(fe)
   413  		p := modulus.big()
   414  		exp(u, a, p.Sub(p, big.NewInt(2)))
   415  		inverse(v, a)
   416  		if !v.equal(u) {
   417  			t.Fatal("a^(p-2) == a^-1")
   418  		}
   419  	}
   420  }
   421  
   422  func TestFpSquareRoot(t *testing.T) {
   423  	r := new(fe)
   424  	if sqrt(r, nonResidue1) {
   425  		t.Fatal("non residue cannot have a sqrt")
   426  	}
   427  	for i := 0; i < fuz; i++ {
   428  		a, _ := new(fe).rand(rand.Reader)
   429  		aa, rr, r := &fe{}, &fe{}, &fe{}
   430  		square(aa, a)
   431  		if !sqrt(r, aa) {
   432  			t.Fatal("bad sqrt 1")
   433  		}
   434  		square(rr, r)
   435  		if !rr.equal(aa) {
   436  			t.Fatal("bad sqrt 2")
   437  		}
   438  	}
   439  }
   440  
   441  func TestFpNonResidue(t *testing.T) {
   442  	if !isQuadraticNonResidue(nonResidue1) {
   443  		t.Fatal("element is quadratic non residue, 1")
   444  	}
   445  	if isQuadraticNonResidue(new(fe).one()) {
   446  		t.Fatal("one is not quadratic non residue")
   447  	}
   448  	if !isQuadraticNonResidue(new(fe).zero()) {
   449  		t.Fatal("should accept zero as quadratic non residue")
   450  	}
   451  	for i := 0; i < fuz; i++ {
   452  		a, _ := new(fe).rand(rand.Reader)
   453  		square(a, a)
   454  		if isQuadraticNonResidue(new(fe).one()) {
   455  			t.Fatal("element is not quadratic non residue")
   456  		}
   457  	}
   458  	for i := 0; i < fuz; i++ {
   459  		a, _ := new(fe).rand(rand.Reader)
   460  		if !sqrt(new(fe), a) {
   461  			if !isQuadraticNonResidue(a) {
   462  				t.Fatal("element is quadratic non residue, 2", i)
   463  			}
   464  		} else {
   465  			i -= 1
   466  		}
   467  	}
   468  }
   469  
   470  func TestFp2Serialization(t *testing.T) {
   471  	field := newFp2()
   472  	for i := 0; i < fuz; i++ {
   473  		a, _ := new(fe2).rand(rand.Reader)
   474  		b, err := field.fromBytes(field.toBytes(a))
   475  		if err != nil {
   476  			t.Fatal(err)
   477  		}
   478  		if !a.equal(b) {
   479  			t.Fatal("bad serialization")
   480  		}
   481  	}
   482  }
   483  
   484  func TestFp2AdditionProperties(t *testing.T) {
   485  	field := newFp2()
   486  	for i := 0; i < fuz; i++ {
   487  		zero := field.zero()
   488  		a, _ := new(fe2).rand(rand.Reader)
   489  		b, _ := new(fe2).rand(rand.Reader)
   490  		c_1 := field.new()
   491  		c_2 := field.new()
   492  		field.add(c_1, a, zero)
   493  		if !c_1.equal(a) {
   494  			t.Fatal("a + 0 == a")
   495  		}
   496  		field.sub(c_1, a, zero)
   497  		if !c_1.equal(a) {
   498  			t.Fatal("a - 0 == a")
   499  		}
   500  		field.double(c_1, zero)
   501  		if !c_1.equal(zero) {
   502  			t.Fatal("2 * 0 == 0")
   503  		}
   504  		field.neg(c_1, zero)
   505  		if !c_1.equal(zero) {
   506  			t.Fatal("-0 == 0")
   507  		}
   508  		field.sub(c_1, zero, a)
   509  		field.neg(c_2, a)
   510  		if !c_1.equal(c_2) {
   511  			t.Fatal("0-a == -a")
   512  		}
   513  		field.double(c_1, a)
   514  		field.add(c_2, a, a)
   515  		if !c_1.equal(c_2) {
   516  			t.Fatal("2 * a == a + a")
   517  		}
   518  		field.add(c_1, a, b)
   519  		field.add(c_2, b, a)
   520  		if !c_1.equal(c_2) {
   521  			t.Fatal("a + b = b + a")
   522  		}
   523  		field.sub(c_1, a, b)
   524  		field.sub(c_2, b, a)
   525  		field.neg(c_2, c_2)
   526  		if !c_1.equal(c_2) {
   527  			t.Fatal("a - b = - ( b - a )")
   528  		}
   529  		c_x, _ := new(fe2).rand(rand.Reader)
   530  		field.add(c_1, a, b)
   531  		field.add(c_1, c_1, c_x)
   532  		field.add(c_2, a, c_x)
   533  		field.add(c_2, c_2, b)
   534  		if !c_1.equal(c_2) {
   535  			t.Fatal("(a + b) + c == (a + c ) + b")
   536  		}
   537  		field.sub(c_1, a, b)
   538  		field.sub(c_1, c_1, c_x)
   539  		field.sub(c_2, a, c_x)
   540  		field.sub(c_2, c_2, b)
   541  		if !c_1.equal(c_2) {
   542  			t.Fatal("(a - b) - c == (a - c ) -b")
   543  		}
   544  	}
   545  }
   546  
   547  func TestFp2AdditionPropertiesAssigned(t *testing.T) {
   548  	field := newFp2()
   549  	for i := 0; i < fuz; i++ {
   550  		zero := new(fe2).zero()
   551  		a, b := new(fe2), new(fe2)
   552  		_, _ = a.rand(rand.Reader)
   553  		b.set(a)
   554  		field.addAssign(a, zero)
   555  		if !a.equal(b) {
   556  			t.Fatal("a + 0 == a")
   557  		}
   558  		field.subAssign(a, zero)
   559  		if !a.equal(b) {
   560  			t.Fatal("a - 0 == a")
   561  		}
   562  		a.set(zero)
   563  		field.doubleAssign(a)
   564  		if !a.equal(zero) {
   565  			t.Fatal("2 * 0 == 0")
   566  		}
   567  		a.set(zero)
   568  		field.subAssign(a, b)
   569  		field.neg(b, b)
   570  		if !a.equal(b) {
   571  			t.Fatal("0-a == -a")
   572  		}
   573  		_, _ = a.rand(rand.Reader)
   574  		b.set(a)
   575  		field.doubleAssign(a)
   576  		field.addAssign(b, b)
   577  		if !a.equal(b) {
   578  			t.Fatal("2 * a == a + a")
   579  		}
   580  		_, _ = a.rand(rand.Reader)
   581  		_, _ = b.rand(rand.Reader)
   582  		c_1, c_2 := new(fe2).set(a), new(fe2).set(b)
   583  		field.addAssign(c_1, b)
   584  		field.addAssign(c_2, a)
   585  		if !c_1.equal(c_2) {
   586  			t.Fatal("a + b = b + a")
   587  		}
   588  		_, _ = a.rand(rand.Reader)
   589  		_, _ = b.rand(rand.Reader)
   590  		c_1.set(a)
   591  		c_2.set(b)
   592  		field.subAssign(c_1, b)
   593  		field.subAssign(c_2, a)
   594  		field.neg(c_2, c_2)
   595  		if !c_1.equal(c_2) {
   596  			t.Fatal("a - b = - ( b - a )")
   597  		}
   598  		_, _ = a.rand(rand.Reader)
   599  		_, _ = b.rand(rand.Reader)
   600  		c, _ := new(fe2).rand(rand.Reader)
   601  		a0 := new(fe2).set(a)
   602  		field.addAssign(a, b)
   603  		field.addAssign(a, c)
   604  		field.addAssign(b, c)
   605  		field.addAssign(b, a0)
   606  		if !a.equal(b) {
   607  			t.Fatal("(a + b) + c == (b + c) + a")
   608  		}
   609  		_, _ = a.rand(rand.Reader)
   610  		_, _ = b.rand(rand.Reader)
   611  		_, _ = c.rand(rand.Reader)
   612  		a0.set(a)
   613  		field.subAssign(a, b)
   614  		field.subAssign(a, c)
   615  		field.subAssign(a0, c)
   616  		field.subAssign(a0, b)
   617  		if !a.equal(a0) {
   618  			t.Fatal("(a - b) - c == (a - c) -b")
   619  		}
   620  	}
   621  }
   622  
   623  func TestFp2LazyOperations(t *testing.T) {
   624  	field := newFp2()
   625  	for i := 0; i < fuz; i++ {
   626  		a, _ := new(fe2).rand(rand.Reader)
   627  		b, _ := new(fe2).rand(rand.Reader)
   628  		c, _ := new(fe2).rand(rand.Reader)
   629  		c0 := new(fe2)
   630  		c1 := new(fe2)
   631  		field.ladd(c0, a, b)
   632  		field.add(c1, a, b)
   633  		field.mulAssign(c0, c)
   634  		field.mulAssign(c1, c)
   635  		if !c0.equal(c1) {
   636  			// l+ operator stands for lazy addition
   637  			t.Fatal("(a + b) * c == (a l+ b) * c")
   638  		}
   639  		_, _ = a.rand(rand.Reader)
   640  		b.set(a)
   641  		field.ldouble(a, a)
   642  		field.ladd(b, b, b)
   643  		if !a.equal(b) {
   644  			t.Fatal("2 l* a = a l+ a")
   645  		}
   646  	}
   647  }
   648  
   649  func TestFp2MultiplicationProperties(t *testing.T) {
   650  	field := newFp2()
   651  	for i := 0; i < fuz; i++ {
   652  		a, _ := new(fe2).rand(rand.Reader)
   653  		b, _ := new(fe2).rand(rand.Reader)
   654  		zero := field.zero()
   655  		one := field.one()
   656  		c_1, c_2 := field.new(), field.new()
   657  		field.mul(c_1, a, zero)
   658  		if !c_1.equal(zero) {
   659  			t.Fatal("a * 0 == 0")
   660  		}
   661  		field.mul(c_1, a, one)
   662  		if !c_1.equal(a) {
   663  			t.Fatal("a * 1 == a")
   664  		}
   665  		field.mul(c_1, a, b)
   666  		field.mul(c_2, b, a)
   667  		if !c_1.equal(c_2) {
   668  			t.Fatal("a * b == b * a")
   669  		}
   670  		c_x, _ := new(fe2).rand(rand.Reader)
   671  		field.mul(c_1, a, b)
   672  		field.mul(c_1, c_1, c_x)
   673  		field.mul(c_2, c_x, b)
   674  		field.mul(c_2, c_2, a)
   675  		if !c_1.equal(c_2) {
   676  			t.Fatal("(a * b) * c == (a * c) * b")
   677  		}
   678  		field.square(a, zero)
   679  		if !a.equal(zero) {
   680  			t.Fatal("0^2 == 0")
   681  		}
   682  		field.square(a, one)
   683  		if !a.equal(one) {
   684  			t.Fatal("1^2 == 1")
   685  		}
   686  		_, _ = a.rand(rand.Reader)
   687  		field.square(c_1, a)
   688  		field.mul(c_2, a, a)
   689  		if !c_2.equal(c_1) {
   690  			t.Fatal("a^2 == a*a")
   691  		}
   692  	}
   693  }
   694  
   695  func TestFp2MultiplicationPropertiesAssigned(t *testing.T) {
   696  	field := newFp2()
   697  	for i := 0; i < fuz; i++ {
   698  		a, _ := new(fe2).rand(rand.Reader)
   699  		zero, one := new(fe2).zero(), new(fe2).one()
   700  		field.mulAssign(a, zero)
   701  		if !a.equal(zero) {
   702  			t.Fatal("a * 0 == 0")
   703  		}
   704  		_, _ = a.rand(rand.Reader)
   705  		a0 := new(fe2).set(a)
   706  		field.mulAssign(a, one)
   707  		if !a.equal(a0) {
   708  			t.Fatal("a * 1 == a")
   709  		}
   710  		_, _ = a.rand(rand.Reader)
   711  		b, _ := new(fe2).rand(rand.Reader)
   712  		a0.set(a)
   713  		field.mulAssign(a, b)
   714  		field.mulAssign(b, a0)
   715  		if !a.equal(b) {
   716  			t.Fatal("a * b == b * a")
   717  		}
   718  		c, _ := new(fe2).rand(rand.Reader)
   719  		a0.set(a)
   720  		field.mulAssign(a, b)
   721  		field.mulAssign(a, c)
   722  		field.mulAssign(a0, c)
   723  		field.mulAssign(a0, b)
   724  		if !a.equal(a0) {
   725  			t.Fatal("(a * b) * c == (a * c) * b")
   726  		}
   727  		a0.set(a)
   728  		field.squareAssign(a)
   729  		field.mulAssign(a0, a0)
   730  		if !a.equal(a0) {
   731  			t.Fatal("a^2 == a*a")
   732  		}
   733  	}
   734  }
   735  
   736  func TestFp2Exponentiation(t *testing.T) {
   737  	field := newFp2()
   738  	for i := 0; i < fuz; i++ {
   739  		a, _ := new(fe2).rand(rand.Reader)
   740  		u := field.new()
   741  		field.exp(u, a, big.NewInt(0))
   742  		if !u.equal(field.one()) {
   743  			t.Fatal("a^0 == 1")
   744  		}
   745  		field.exp(u, a, big.NewInt(1))
   746  		if !u.equal(a) {
   747  			t.Fatal("a^1 == a")
   748  		}
   749  		v := field.new()
   750  		field.mul(u, a, a)
   751  		field.mul(u, u, u)
   752  		field.mul(u, u, u)
   753  		field.exp(v, a, big.NewInt(8))
   754  		if !u.equal(v) {
   755  			t.Fatal("((a^2)^2)^2 == a^8")
   756  		}
   757  	}
   758  }
   759  
   760  func TestFp2Inversion(t *testing.T) {
   761  	field := newFp2()
   762  	u := field.new()
   763  	zero := field.zero()
   764  	one := field.one()
   765  	field.inverse(u, zero)
   766  	if !u.equal(zero) {
   767  		t.Fatal("(0 ^ -1) == 0)")
   768  	}
   769  	field.inverse(u, one)
   770  	if !u.equal(one) {
   771  		t.Fatal("(1 ^ -1) == 1)")
   772  	}
   773  	for i := 0; i < fuz; i++ {
   774  		a, _ := new(fe2).rand(rand.Reader)
   775  		field.inverse(u, a)
   776  		field.mul(u, u, a)
   777  		if !u.equal(one) {
   778  			t.Fatal("(r * a) * r * (a ^ -1) == r)")
   779  		}
   780  	}
   781  }
   782  
   783  func TestFp2SquareRoot(t *testing.T) {
   784  	field := newFp2()
   785  	for z := 0; z < 1000; z++ {
   786  		zi := new(fe)
   787  		sub(zi, &modulus, &fe{uint64(z * z)})
   788  		// r = (-z*z, 0)
   789  		r := &fe2{*zi, fe{0}}
   790  		toMont(&r[0], &r[0])
   791  		toMont(&r[1], &r[1])
   792  		c := field.new()
   793  		// sqrt((-z*z, 0)) = (0, z)
   794  		if !field.sqrt(c, r) {
   795  			t.Fatal("z*z does have a square root")
   796  		}
   797  		e := &fe2{fe{uint64(0)}, fe{uint64(z)}}
   798  		toMont(&e[0], &e[0])
   799  		toMont(&e[1], &e[1])
   800  		field.square(e, e)
   801  		field.square(c, c)
   802  		if !e.equal(c) {
   803  			t.Fatal("square root failed")
   804  		}
   805  	}
   806  	if field.sqrt(field.new(), nonResidue2) {
   807  		t.Fatal("non residue cannot have a sqrt")
   808  	}
   809  	for i := 0; i < fuz; i++ {
   810  		a, _ := new(fe2).rand(rand.Reader)
   811  		aa, rr, r := field.new(), field.new(), field.new()
   812  		field.square(aa, a)
   813  		if !field.sqrt(r, aa) {
   814  			t.Fatal("bad sqrt 1")
   815  		}
   816  		field.square(rr, r)
   817  		if !rr.equal(aa) {
   818  			t.Fatal("bad sqrt 2")
   819  		}
   820  	}
   821  }
   822  
   823  func TestFp2NonResidue(t *testing.T) {
   824  	field := newFp2()
   825  	if !field.isQuadraticNonResidue(nonResidue2) {
   826  		t.Fatal("element is quadratic non residue, 1")
   827  	}
   828  	if field.isQuadraticNonResidue(new(fe2).one()) {
   829  		t.Fatal("one is not quadratic non residue")
   830  	}
   831  	if !field.isQuadraticNonResidue(new(fe2).zero()) {
   832  		t.Fatal("should accept zero as quadratic non residue")
   833  	}
   834  	for i := 0; i < fuz; i++ {
   835  		a, _ := new(fe2).rand(rand.Reader)
   836  		field.squareAssign(a)
   837  		if field.isQuadraticNonResidue(new(fe2).one()) {
   838  			t.Fatal("element is not quadratic non residue")
   839  		}
   840  	}
   841  	for i := 0; i < fuz; i++ {
   842  		a, _ := new(fe2).rand(rand.Reader)
   843  		if !field.sqrt(new(fe2), a) {
   844  			if !field.isQuadraticNonResidue(a) {
   845  				t.Fatal("element is quadratic non residue, 2", i)
   846  			}
   847  		} else {
   848  			i -= 1
   849  		}
   850  	}
   851  }
   852  
   853  func TestFp6Serialization(t *testing.T) {
   854  	field := newFp6(nil)
   855  	for i := 0; i < fuz; i++ {
   856  		a, _ := new(fe6).rand(rand.Reader)
   857  		b, err := field.fromBytes(field.toBytes(a))
   858  		if err != nil {
   859  			t.Fatal(err)
   860  		}
   861  		if !a.equal(b) {
   862  			t.Fatal("bad serialization")
   863  		}
   864  	}
   865  }
   866  
   867  func TestFp6AdditionProperties(t *testing.T) {
   868  	field := newFp6(nil)
   869  	for i := 0; i < fuz; i++ {
   870  		zero := field.zero()
   871  		a, _ := new(fe6).rand(rand.Reader)
   872  		b, _ := new(fe6).rand(rand.Reader)
   873  		c_1 := field.new()
   874  		c_2 := field.new()
   875  		field.add(c_1, a, zero)
   876  		if !c_1.equal(a) {
   877  			t.Fatal("a + 0 == a")
   878  		}
   879  		field.sub(c_1, a, zero)
   880  		if !c_1.equal(a) {
   881  			t.Fatal("a - 0 == a")
   882  		}
   883  		field.double(c_1, zero)
   884  		if !c_1.equal(zero) {
   885  			t.Fatal("2 * 0 == 0")
   886  		}
   887  		field.neg(c_1, zero)
   888  		if !c_1.equal(zero) {
   889  			t.Fatal("-0 == 0")
   890  		}
   891  		field.sub(c_1, zero, a)
   892  		field.neg(c_2, a)
   893  		if !c_1.equal(c_2) {
   894  			t.Fatal("0-a == -a")
   895  		}
   896  		field.double(c_1, a)
   897  		field.add(c_2, a, a)
   898  		if !c_1.equal(c_2) {
   899  			t.Fatal("2 * a == a + a")
   900  		}
   901  		field.add(c_1, a, b)
   902  		field.add(c_2, b, a)
   903  		if !c_1.equal(c_2) {
   904  			t.Fatal("a + b = b + a")
   905  		}
   906  		field.sub(c_1, a, b)
   907  		field.sub(c_2, b, a)
   908  		field.neg(c_2, c_2)
   909  		if !c_1.equal(c_2) {
   910  			t.Fatal("a - b = - ( b - a )")
   911  		}
   912  		c_x, _ := new(fe6).rand(rand.Reader)
   913  		field.add(c_1, a, b)
   914  		field.add(c_1, c_1, c_x)
   915  		field.add(c_2, a, c_x)
   916  		field.add(c_2, c_2, b)
   917  		if !c_1.equal(c_2) {
   918  			t.Fatal("(a + b) + c == (a + c ) + b")
   919  		}
   920  		field.sub(c_1, a, b)
   921  		field.sub(c_1, c_1, c_x)
   922  		field.sub(c_2, a, c_x)
   923  		field.sub(c_2, c_2, b)
   924  		if !c_1.equal(c_2) {
   925  			t.Fatal("(a - b) - c == (a - c ) -b")
   926  		}
   927  	}
   928  }
   929  
   930  func TestFp6AdditionPropertiesAssigned(t *testing.T) {
   931  	field := newFp6(nil)
   932  	for i := 0; i < fuz; i++ {
   933  		zero := new(fe6).zero()
   934  		a, b := new(fe6), new(fe6)
   935  		_, _ = a.rand(rand.Reader)
   936  		b.set(a)
   937  		field.addAssign(a, zero)
   938  		if !a.equal(b) {
   939  			t.Fatal("a + 0 == a")
   940  		}
   941  		field.subAssign(a, zero)
   942  		if !a.equal(b) {
   943  			t.Fatal("a - 0 == a")
   944  		}
   945  		a.set(zero)
   946  		field.doubleAssign(a)
   947  		if !a.equal(zero) {
   948  			t.Fatal("2 * 0 == 0")
   949  		}
   950  		a.set(zero)
   951  		field.subAssign(a, b)
   952  		field.neg(b, b)
   953  		if !a.equal(b) {
   954  			t.Fatal("0-a == -a")
   955  		}
   956  		_, _ = a.rand(rand.Reader)
   957  		b.set(a)
   958  		field.doubleAssign(a)
   959  		field.addAssign(b, b)
   960  		if !a.equal(b) {
   961  			t.Fatal("2 * a == a + a")
   962  		}
   963  		_, _ = a.rand(rand.Reader)
   964  		_, _ = b.rand(rand.Reader)
   965  		c_1, c_2 := new(fe6).set(a), new(fe6).set(b)
   966  		field.addAssign(c_1, b)
   967  		field.addAssign(c_2, a)
   968  		if !c_1.equal(c_2) {
   969  			t.Fatal("a + b = b + a")
   970  		}
   971  		_, _ = a.rand(rand.Reader)
   972  		_, _ = b.rand(rand.Reader)
   973  		c_1.set(a)
   974  		c_2.set(b)
   975  		field.subAssign(c_1, b)
   976  		field.subAssign(c_2, a)
   977  		field.neg(c_2, c_2)
   978  		if !c_1.equal(c_2) {
   979  			t.Fatal("a - b = - ( b - a )")
   980  		}
   981  		_, _ = a.rand(rand.Reader)
   982  		_, _ = b.rand(rand.Reader)
   983  		c, _ := new(fe6).rand(rand.Reader)
   984  		a0 := new(fe6).set(a)
   985  		field.addAssign(a, b)
   986  		field.addAssign(a, c)
   987  		field.addAssign(b, c)
   988  		field.addAssign(b, a0)
   989  		if !a.equal(b) {
   990  			t.Fatal("(a + b) + c == (b + c) + a")
   991  		}
   992  		_, _ = a.rand(rand.Reader)
   993  		_, _ = b.rand(rand.Reader)
   994  		_, _ = c.rand(rand.Reader)
   995  		a0.set(a)
   996  		field.subAssign(a, b)
   997  		field.subAssign(a, c)
   998  		field.subAssign(a0, c)
   999  		field.subAssign(a0, b)
  1000  		if !a.equal(a0) {
  1001  			t.Fatal("(a - b) - c == (a - c) -b")
  1002  		}
  1003  	}
  1004  }
  1005  
  1006  func TestFp6SparseMultiplication(t *testing.T) {
  1007  	fp6 := newFp6(nil)
  1008  	var a, b, u *fe6
  1009  	for j := 0; j < fuz; j++ {
  1010  		a, _ = new(fe6).rand(rand.Reader)
  1011  		b, _ = new(fe6).rand(rand.Reader)
  1012  		u, _ = new(fe6).rand(rand.Reader)
  1013  		b[2].zero()
  1014  		fp6.mul(u, a, b)
  1015  		fp6.mulBy01(a, a, &b[0], &b[1])
  1016  		if !a.equal(u) {
  1017  			t.Fatal("bad mul by 01")
  1018  		}
  1019  	}
  1020  	for j := 0; j < fuz; j++ {
  1021  		a, _ = new(fe6).rand(rand.Reader)
  1022  		b, _ = new(fe6).rand(rand.Reader)
  1023  		u, _ = new(fe6).rand(rand.Reader)
  1024  		b[2].zero()
  1025  		b[0].zero()
  1026  		fp6.mul(u, a, b)
  1027  		fp6.mulBy1(a, a, &b[1])
  1028  		if !a.equal(u) {
  1029  			t.Fatal("bad mul by 1")
  1030  		}
  1031  	}
  1032  }
  1033  
  1034  func TestFp6MultiplicationProperties(t *testing.T) {
  1035  	field := newFp6(nil)
  1036  	for i := 0; i < fuz; i++ {
  1037  		a, _ := new(fe6).rand(rand.Reader)
  1038  		b, _ := new(fe6).rand(rand.Reader)
  1039  		zero := field.zero()
  1040  		one := field.one()
  1041  		c_1, c_2 := field.new(), field.new()
  1042  		field.mul(c_1, a, zero)
  1043  		if !c_1.equal(zero) {
  1044  			t.Fatal("a * 0 == 0")
  1045  		}
  1046  		field.mul(c_1, a, one)
  1047  		if !c_1.equal(a) {
  1048  			t.Fatal("a * 1 == a")
  1049  		}
  1050  		field.mul(c_1, a, b)
  1051  		field.mul(c_2, b, a)
  1052  		if !c_1.equal(c_2) {
  1053  			t.Fatal("a * b == b * a")
  1054  		}
  1055  		c_x, _ := new(fe6).rand(rand.Reader)
  1056  		field.mul(c_1, a, b)
  1057  		field.mul(c_1, c_1, c_x)
  1058  		field.mul(c_2, c_x, b)
  1059  		field.mul(c_2, c_2, a)
  1060  		if !c_1.equal(c_2) {
  1061  			t.Fatal("(a * b) * c == (a * c) * b")
  1062  		}
  1063  		field.square(a, zero)
  1064  		if !a.equal(zero) {
  1065  			t.Fatal("0^2 == 0")
  1066  		}
  1067  		field.square(a, one)
  1068  		if !a.equal(one) {
  1069  			t.Fatal("1^2 == 1")
  1070  		}
  1071  		_, _ = a.rand(rand.Reader)
  1072  		field.square(c_1, a)
  1073  		field.mul(c_2, a, a)
  1074  		if !c_2.equal(c_1) {
  1075  			t.Fatal("a^2 == a*a")
  1076  		}
  1077  	}
  1078  }
  1079  
  1080  func TestFp6MultiplicationPropertiesAssigned(t *testing.T) {
  1081  	field := newFp6(nil)
  1082  	for i := 0; i < fuz; i++ {
  1083  		a, _ := new(fe6).rand(rand.Reader)
  1084  		zero, one := new(fe6).zero(), new(fe6).one()
  1085  		field.mulAssign(a, zero)
  1086  		if !a.equal(zero) {
  1087  			t.Fatal("a * 0 == 0")
  1088  		}
  1089  		_, _ = a.rand(rand.Reader)
  1090  		a0 := new(fe6).set(a)
  1091  		field.mulAssign(a, one)
  1092  		if !a.equal(a0) {
  1093  			t.Fatal("a * 1 == a")
  1094  		}
  1095  		_, _ = a.rand(rand.Reader)
  1096  		b, _ := new(fe6).rand(rand.Reader)
  1097  		a0.set(a)
  1098  		field.mulAssign(a, b)
  1099  		field.mulAssign(b, a0)
  1100  		if !a.equal(b) {
  1101  			t.Fatal("a * b == b * a")
  1102  		}
  1103  		c, _ := new(fe6).rand(rand.Reader)
  1104  		a0.set(a)
  1105  		field.mulAssign(a, b)
  1106  		field.mulAssign(a, c)
  1107  		field.mulAssign(a0, c)
  1108  		field.mulAssign(a0, b)
  1109  		if !a.equal(a0) {
  1110  			t.Fatal("(a * b) * c == (a * c) * b")
  1111  		}
  1112  	}
  1113  }
  1114  
  1115  func TestFp6Exponentiation(t *testing.T) {
  1116  	field := newFp6(nil)
  1117  	for i := 0; i < fuz; i++ {
  1118  		a, _ := new(fe6).rand(rand.Reader)
  1119  		u := field.new()
  1120  		field.exp(u, a, big.NewInt(0))
  1121  		if !u.equal(field.one()) {
  1122  			t.Fatal("a^0 == 1")
  1123  		}
  1124  		field.exp(u, a, big.NewInt(1))
  1125  		if !u.equal(a) {
  1126  			t.Fatal("a^1 == a")
  1127  		}
  1128  		v := field.new()
  1129  		field.mul(u, a, a)
  1130  		field.mul(u, u, u)
  1131  		field.mul(u, u, u)
  1132  		field.exp(v, a, big.NewInt(8))
  1133  		if !u.equal(v) {
  1134  			t.Fatal("((a^2)^2)^2 == a^8")
  1135  		}
  1136  	}
  1137  }
  1138  
  1139  func TestFp6Inversion(t *testing.T) {
  1140  	field := newFp6(nil)
  1141  	for i := 0; i < fuz; i++ {
  1142  		u := field.new()
  1143  		zero := field.zero()
  1144  		one := field.one()
  1145  		field.inverse(u, zero)
  1146  		if !u.equal(zero) {
  1147  			t.Fatal("(0^-1) == 0)")
  1148  		}
  1149  		field.inverse(u, one)
  1150  		if !u.equal(one) {
  1151  			t.Fatal("(1^-1) == 1)")
  1152  		}
  1153  		a, _ := new(fe6).rand(rand.Reader)
  1154  		field.inverse(u, a)
  1155  		field.mul(u, u, a)
  1156  		if !u.equal(one) {
  1157  			t.Fatal("(r*a) * r*(a^-1) == r)")
  1158  		}
  1159  	}
  1160  }
  1161  
  1162  func TestFp12Serialization(t *testing.T) {
  1163  	field := newFp12(nil)
  1164  	for i := 0; i < fuz; i++ {
  1165  		a, _ := new(fe12).rand(rand.Reader)
  1166  		b, err := field.fromBytes(field.toBytes(a))
  1167  		if err != nil {
  1168  			t.Fatal(err)
  1169  		}
  1170  		if !a.equal(b) {
  1171  			t.Fatal("bad serialization")
  1172  		}
  1173  	}
  1174  }
  1175  
  1176  func TestFp12AdditionProperties(t *testing.T) {
  1177  	field := newFp12(nil)
  1178  	for i := 0; i < fuz; i++ {
  1179  		zero := field.zero()
  1180  		a, _ := new(fe12).rand(rand.Reader)
  1181  		b, _ := new(fe12).rand(rand.Reader)
  1182  		c_1 := field.new()
  1183  		c_2 := field.new()
  1184  		field.add(c_1, a, zero)
  1185  		if !c_1.equal(a) {
  1186  			t.Fatal("a + 0 == a")
  1187  		}
  1188  		field.sub(c_1, a, zero)
  1189  		if !c_1.equal(a) {
  1190  			t.Fatal("a - 0 == a")
  1191  		}
  1192  		field.double(c_1, zero)
  1193  		if !c_1.equal(zero) {
  1194  			t.Fatal("2 * 0 == 0")
  1195  		}
  1196  		field.neg(c_1, zero)
  1197  		if !c_1.equal(zero) {
  1198  			t.Fatal("-0 == 0")
  1199  		}
  1200  		field.sub(c_1, zero, a)
  1201  		field.neg(c_2, a)
  1202  		if !c_1.equal(c_2) {
  1203  			t.Fatal("0-a == -a")
  1204  		}
  1205  		field.double(c_1, a)
  1206  		field.add(c_2, a, a)
  1207  		if !c_1.equal(c_2) {
  1208  			t.Fatal("2 * a == a + a")
  1209  		}
  1210  		field.add(c_1, a, b)
  1211  		field.add(c_2, b, a)
  1212  		if !c_1.equal(c_2) {
  1213  			t.Fatal("a + b = b + a")
  1214  		}
  1215  		field.sub(c_1, a, b)
  1216  		field.sub(c_2, b, a)
  1217  		field.neg(c_2, c_2)
  1218  		if !c_1.equal(c_2) {
  1219  			t.Fatal("a - b = - ( b - a )")
  1220  		}
  1221  		c_x, _ := new(fe12).rand(rand.Reader)
  1222  		field.add(c_1, a, b)
  1223  		field.add(c_1, c_1, c_x)
  1224  		field.add(c_2, a, c_x)
  1225  		field.add(c_2, c_2, b)
  1226  		if !c_1.equal(c_2) {
  1227  			t.Fatal("(a + b) + c == (a + c ) + b")
  1228  		}
  1229  		field.sub(c_1, a, b)
  1230  		field.sub(c_1, c_1, c_x)
  1231  		field.sub(c_2, a, c_x)
  1232  		field.sub(c_2, c_2, b)
  1233  		if !c_1.equal(c_2) {
  1234  			t.Fatal("(a - b) - c == (a - c ) -b")
  1235  		}
  1236  	}
  1237  }
  1238  
  1239  func TestFp12MultiplicationProperties(t *testing.T) {
  1240  	field := newFp12(nil)
  1241  	for i := 0; i < fuz; i++ {
  1242  		a, _ := new(fe12).rand(rand.Reader)
  1243  		b, _ := new(fe12).rand(rand.Reader)
  1244  		zero := field.zero()
  1245  		one := field.one()
  1246  		c_1, c_2 := field.new(), field.new()
  1247  		field.mul(c_1, a, zero)
  1248  		if !c_1.equal(zero) {
  1249  			t.Fatal("a * 0 == 0")
  1250  		}
  1251  		field.mul(c_1, a, one)
  1252  		if !c_1.equal(a) {
  1253  			t.Fatal("a * 1 == a")
  1254  		}
  1255  		field.mul(c_1, a, b)
  1256  		field.mul(c_2, b, a)
  1257  		if !c_1.equal(c_2) {
  1258  			t.Fatal("a * b == b * a")
  1259  		}
  1260  		c_x, _ := new(fe12).rand(rand.Reader)
  1261  		field.mul(c_1, a, b)
  1262  		field.mul(c_1, c_1, c_x)
  1263  		field.mul(c_2, c_x, b)
  1264  		field.mul(c_2, c_2, a)
  1265  		if !c_1.equal(c_2) {
  1266  			t.Fatal("(a * b) * c == (a * c) * b")
  1267  		}
  1268  		field.square(a, zero)
  1269  		if !a.equal(zero) {
  1270  			t.Fatal("0^2 == 0")
  1271  		}
  1272  		field.square(a, one)
  1273  		if !a.equal(one) {
  1274  			t.Fatal("1^2 == 1")
  1275  		}
  1276  		_, _ = a.rand(rand.Reader)
  1277  		field.square(c_1, a)
  1278  		field.mul(c_2, a, a)
  1279  		if !c_2.equal(c_1) {
  1280  			t.Fatal("a^2 == a*a")
  1281  		}
  1282  	}
  1283  }
  1284  
  1285  func TestFp12MultiplicationPropertiesAssigned(t *testing.T) {
  1286  	field := newFp12(nil)
  1287  	for i := 0; i < fuz; i++ {
  1288  		a, _ := new(fe12).rand(rand.Reader)
  1289  		zero, one := new(fe12).zero(), new(fe12).one()
  1290  		field.mulAssign(a, zero)
  1291  		if !a.equal(zero) {
  1292  			t.Fatal("a * 0 == 0")
  1293  		}
  1294  		_, _ = a.rand(rand.Reader)
  1295  		a0 := new(fe12).set(a)
  1296  		field.mulAssign(a, one)
  1297  		if !a.equal(a0) {
  1298  			t.Fatal("a * 1 == a")
  1299  		}
  1300  		_, _ = a.rand(rand.Reader)
  1301  		b, _ := new(fe12).rand(rand.Reader)
  1302  		a0.set(a)
  1303  		field.mulAssign(a, b)
  1304  		field.mulAssign(b, a0)
  1305  		if !a.equal(b) {
  1306  			t.Fatal("a * b == b * a")
  1307  		}
  1308  		c, _ := new(fe12).rand(rand.Reader)
  1309  		a0.set(a)
  1310  		field.mulAssign(a, b)
  1311  		field.mulAssign(a, c)
  1312  		field.mulAssign(a0, c)
  1313  		field.mulAssign(a0, b)
  1314  		if !a.equal(a0) {
  1315  			t.Fatal("(a * b) * c == (a * c) * b")
  1316  		}
  1317  	}
  1318  }
  1319  
  1320  func TestFp12SparseMultiplication(t *testing.T) {
  1321  	fp12 := newFp12(nil)
  1322  	var a, b, u *fe12
  1323  	for j := 0; j < fuz; j++ {
  1324  		a, _ = new(fe12).rand(rand.Reader)
  1325  		b, _ = new(fe12).rand(rand.Reader)
  1326  		u, _ = new(fe12).rand(rand.Reader)
  1327  		b[0][2].zero()
  1328  		b[1][0].zero()
  1329  		b[1][2].zero()
  1330  		fp12.mul(u, a, b)
  1331  		fp12.mulBy014Assign(a, &b[0][0], &b[0][1], &b[1][1])
  1332  		if !a.equal(u) {
  1333  			t.Fatal("bad mul by 01")
  1334  		}
  1335  	}
  1336  }
  1337  
  1338  func TestFp12Exponentiation(t *testing.T) {
  1339  	field := newFp12(nil)
  1340  	for i := 0; i < fuz; i++ {
  1341  		a, _ := new(fe12).rand(rand.Reader)
  1342  		u := field.new()
  1343  		field.exp(u, a, big.NewInt(0))
  1344  		if !u.equal(field.one()) {
  1345  			t.Fatal("a^0 == 1")
  1346  		}
  1347  		field.exp(u, a, big.NewInt(1))
  1348  		if !u.equal(a) {
  1349  			t.Fatal("a^1 == a")
  1350  		}
  1351  		v := field.new()
  1352  		field.mul(u, a, a)
  1353  		field.mul(u, u, u)
  1354  		field.mul(u, u, u)
  1355  		field.exp(v, a, big.NewInt(8))
  1356  		if !u.equal(v) {
  1357  			t.Fatal("((a^2)^2)^2 == a^8")
  1358  		}
  1359  	}
  1360  }
  1361  
  1362  func TestFp12Inversion(t *testing.T) {
  1363  	field := newFp12(nil)
  1364  	for i := 0; i < fuz; i++ {
  1365  		u := field.new()
  1366  		zero := field.zero()
  1367  		one := field.one()
  1368  		field.inverse(u, zero)
  1369  		if !u.equal(zero) {
  1370  			t.Fatal("(0^-1) == 0)")
  1371  		}
  1372  		field.inverse(u, one)
  1373  		if !u.equal(one) {
  1374  			t.Fatal("(1^-1) == 1)")
  1375  		}
  1376  		a, _ := new(fe12).rand(rand.Reader)
  1377  		field.inverse(u, a)
  1378  		field.mul(u, u, a)
  1379  		if !u.equal(one) {
  1380  			t.Fatal("(r*a) * r*(a^-1) == r)")
  1381  		}
  1382  	}
  1383  }
  1384  
  1385  func BenchmarkMultiplication(t *testing.B) {
  1386  	a, _ := new(fe).rand(rand.Reader)
  1387  	b, _ := new(fe).rand(rand.Reader)
  1388  	c, _ := new(fe).rand(rand.Reader)
  1389  	t.ResetTimer()
  1390  	for i := 0; i < t.N; i++ {
  1391  		mul(c, a, b)
  1392  	}
  1393  }
  1394  
  1395  func BenchmarkInverse(t *testing.B) {
  1396  	a, _ := new(fe).rand(rand.Reader)
  1397  	b, _ := new(fe).rand(rand.Reader)
  1398  	t.ResetTimer()
  1399  	for i := 0; i < t.N; i++ {
  1400  		inverse(a, b)
  1401  	}
  1402  }
  1403  
  1404  func padBytes(in []byte, size int) []byte {
  1405  	out := make([]byte, size)
  1406  	if len(in) > size {
  1407  		panic("bad input for padding")
  1408  	}
  1409  	copy(out[size-len(in):], in)
  1410  	return out
  1411  }