github.com/chain5j/chain5j-pkg@v1.0.7/crypto/signature/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  
   471  func TestFp2Serialization(t *testing.T) {
   472  	field := newFp2()
   473  	for i := 0; i < fuz; i++ {
   474  		a, _ := new(fe2).rand(rand.Reader)
   475  		b, err := field.fromBytes(field.toBytes(a))
   476  		if err != nil {
   477  			t.Fatal(err)
   478  		}
   479  		if !a.equal(b) {
   480  			t.Fatal("bad serialization")
   481  		}
   482  	}
   483  }
   484  
   485  func TestFp2AdditionProperties(t *testing.T) {
   486  	field := newFp2()
   487  	for i := 0; i < fuz; i++ {
   488  		zero := field.zero()
   489  		a, _ := new(fe2).rand(rand.Reader)
   490  		b, _ := new(fe2).rand(rand.Reader)
   491  		c_1 := field.new()
   492  		c_2 := field.new()
   493  		field.add(c_1, a, zero)
   494  		if !c_1.equal(a) {
   495  			t.Fatal("a + 0 == a")
   496  		}
   497  		field.sub(c_1, a, zero)
   498  		if !c_1.equal(a) {
   499  			t.Fatal("a - 0 == a")
   500  		}
   501  		field.double(c_1, zero)
   502  		if !c_1.equal(zero) {
   503  			t.Fatal("2 * 0 == 0")
   504  		}
   505  		field.neg(c_1, zero)
   506  		if !c_1.equal(zero) {
   507  			t.Fatal("-0 == 0")
   508  		}
   509  		field.sub(c_1, zero, a)
   510  		field.neg(c_2, a)
   511  		if !c_1.equal(c_2) {
   512  			t.Fatal("0-a == -a")
   513  		}
   514  		field.double(c_1, a)
   515  		field.add(c_2, a, a)
   516  		if !c_1.equal(c_2) {
   517  			t.Fatal("2 * a == a + a")
   518  		}
   519  		field.add(c_1, a, b)
   520  		field.add(c_2, b, a)
   521  		if !c_1.equal(c_2) {
   522  			t.Fatal("a + b = b + a")
   523  		}
   524  		field.sub(c_1, a, b)
   525  		field.sub(c_2, b, a)
   526  		field.neg(c_2, c_2)
   527  		if !c_1.equal(c_2) {
   528  			t.Fatal("a - b = - ( b - a )")
   529  		}
   530  		c_x, _ := new(fe2).rand(rand.Reader)
   531  		field.add(c_1, a, b)
   532  		field.add(c_1, c_1, c_x)
   533  		field.add(c_2, a, c_x)
   534  		field.add(c_2, c_2, b)
   535  		if !c_1.equal(c_2) {
   536  			t.Fatal("(a + b) + c == (a + c ) + b")
   537  		}
   538  		field.sub(c_1, a, b)
   539  		field.sub(c_1, c_1, c_x)
   540  		field.sub(c_2, a, c_x)
   541  		field.sub(c_2, c_2, b)
   542  		if !c_1.equal(c_2) {
   543  			t.Fatal("(a - b) - c == (a - c ) -b")
   544  		}
   545  	}
   546  }
   547  
   548  func TestFp2AdditionPropertiesAssigned(t *testing.T) {
   549  	field := newFp2()
   550  	for i := 0; i < fuz; i++ {
   551  		zero := new(fe2).zero()
   552  		a, b := new(fe2), new(fe2)
   553  		_, _ = a.rand(rand.Reader)
   554  		b.set(a)
   555  		field.addAssign(a, zero)
   556  		if !a.equal(b) {
   557  			t.Fatal("a + 0 == a")
   558  		}
   559  		field.subAssign(a, zero)
   560  		if !a.equal(b) {
   561  			t.Fatal("a - 0 == a")
   562  		}
   563  		a.set(zero)
   564  		field.doubleAssign(a)
   565  		if !a.equal(zero) {
   566  			t.Fatal("2 * 0 == 0")
   567  		}
   568  		a.set(zero)
   569  		field.subAssign(a, b)
   570  		field.neg(b, b)
   571  		if !a.equal(b) {
   572  			t.Fatal("0-a == -a")
   573  		}
   574  		_, _ = a.rand(rand.Reader)
   575  		b.set(a)
   576  		field.doubleAssign(a)
   577  		field.addAssign(b, b)
   578  		if !a.equal(b) {
   579  			t.Fatal("2 * a == a + a")
   580  		}
   581  		_, _ = a.rand(rand.Reader)
   582  		_, _ = b.rand(rand.Reader)
   583  		c_1, c_2 := new(fe2).set(a), new(fe2).set(b)
   584  		field.addAssign(c_1, b)
   585  		field.addAssign(c_2, a)
   586  		if !c_1.equal(c_2) {
   587  			t.Fatal("a + b = b + a")
   588  		}
   589  		_, _ = a.rand(rand.Reader)
   590  		_, _ = b.rand(rand.Reader)
   591  		c_1.set(a)
   592  		c_2.set(b)
   593  		field.subAssign(c_1, b)
   594  		field.subAssign(c_2, a)
   595  		field.neg(c_2, c_2)
   596  		if !c_1.equal(c_2) {
   597  			t.Fatal("a - b = - ( b - a )")
   598  		}
   599  		_, _ = a.rand(rand.Reader)
   600  		_, _ = b.rand(rand.Reader)
   601  		c, _ := new(fe2).rand(rand.Reader)
   602  		a0 := new(fe2).set(a)
   603  		field.addAssign(a, b)
   604  		field.addAssign(a, c)
   605  		field.addAssign(b, c)
   606  		field.addAssign(b, a0)
   607  		if !a.equal(b) {
   608  			t.Fatal("(a + b) + c == (b + c) + a")
   609  		}
   610  		_, _ = a.rand(rand.Reader)
   611  		_, _ = b.rand(rand.Reader)
   612  		_, _ = c.rand(rand.Reader)
   613  		a0.set(a)
   614  		field.subAssign(a, b)
   615  		field.subAssign(a, c)
   616  		field.subAssign(a0, c)
   617  		field.subAssign(a0, b)
   618  		if !a.equal(a0) {
   619  			t.Fatal("(a - b) - c == (a - c) -b")
   620  		}
   621  	}
   622  }
   623  
   624  func TestFp2LazyOperations(t *testing.T) {
   625  	field := newFp2()
   626  	for i := 0; i < fuz; i++ {
   627  		a, _ := new(fe2).rand(rand.Reader)
   628  		b, _ := new(fe2).rand(rand.Reader)
   629  		c, _ := new(fe2).rand(rand.Reader)
   630  		c0 := new(fe2)
   631  		c1 := new(fe2)
   632  		field.ladd(c0, a, b)
   633  		field.add(c1, a, b)
   634  		field.mulAssign(c0, c)
   635  		field.mulAssign(c1, c)
   636  		if !c0.equal(c1) {
   637  			// l+ operator stands for lazy addition
   638  			t.Fatal("(a + b) * c == (a l+ b) * c")
   639  		}
   640  		_, _ = a.rand(rand.Reader)
   641  		b.set(a)
   642  		field.ldouble(a, a)
   643  		field.ladd(b, b, b)
   644  		if !a.equal(b) {
   645  			t.Fatal("2 l* a = a l+ a")
   646  		}
   647  	}
   648  }
   649  
   650  func TestFp2MultiplicationProperties(t *testing.T) {
   651  	field := newFp2()
   652  	for i := 0; i < fuz; i++ {
   653  		a, _ := new(fe2).rand(rand.Reader)
   654  		b, _ := new(fe2).rand(rand.Reader)
   655  		zero := field.zero()
   656  		one := field.one()
   657  		c_1, c_2 := field.new(), field.new()
   658  		field.mul(c_1, a, zero)
   659  		if !c_1.equal(zero) {
   660  			t.Fatal("a * 0 == 0")
   661  		}
   662  		field.mul(c_1, a, one)
   663  		if !c_1.equal(a) {
   664  			t.Fatal("a * 1 == a")
   665  		}
   666  		field.mul(c_1, a, b)
   667  		field.mul(c_2, b, a)
   668  		if !c_1.equal(c_2) {
   669  			t.Fatal("a * b == b * a")
   670  		}
   671  		c_x, _ := new(fe2).rand(rand.Reader)
   672  		field.mul(c_1, a, b)
   673  		field.mul(c_1, c_1, c_x)
   674  		field.mul(c_2, c_x, b)
   675  		field.mul(c_2, c_2, a)
   676  		if !c_1.equal(c_2) {
   677  			t.Fatal("(a * b) * c == (a * c) * b")
   678  		}
   679  		field.square(a, zero)
   680  		if !a.equal(zero) {
   681  			t.Fatal("0^2 == 0")
   682  		}
   683  		field.square(a, one)
   684  		if !a.equal(one) {
   685  			t.Fatal("1^2 == 1")
   686  		}
   687  		_, _ = a.rand(rand.Reader)
   688  		field.square(c_1, a)
   689  		field.mul(c_2, a, a)
   690  		if !c_2.equal(c_1) {
   691  			t.Fatal("a^2 == a*a")
   692  		}
   693  	}
   694  }
   695  
   696  func TestFp2MultiplicationPropertiesAssigned(t *testing.T) {
   697  	field := newFp2()
   698  	for i := 0; i < fuz; i++ {
   699  		a, _ := new(fe2).rand(rand.Reader)
   700  		zero, one := new(fe2).zero(), new(fe2).one()
   701  		field.mulAssign(a, zero)
   702  		if !a.equal(zero) {
   703  			t.Fatal("a * 0 == 0")
   704  		}
   705  		_, _ = a.rand(rand.Reader)
   706  		a0 := new(fe2).set(a)
   707  		field.mulAssign(a, one)
   708  		if !a.equal(a0) {
   709  			t.Fatal("a * 1 == a")
   710  		}
   711  		_, _ = a.rand(rand.Reader)
   712  		b, _ := new(fe2).rand(rand.Reader)
   713  		a0.set(a)
   714  		field.mulAssign(a, b)
   715  		field.mulAssign(b, a0)
   716  		if !a.equal(b) {
   717  			t.Fatal("a * b == b * a")
   718  		}
   719  		c, _ := new(fe2).rand(rand.Reader)
   720  		a0.set(a)
   721  		field.mulAssign(a, b)
   722  		field.mulAssign(a, c)
   723  		field.mulAssign(a0, c)
   724  		field.mulAssign(a0, b)
   725  		if !a.equal(a0) {
   726  			t.Fatal("(a * b) * c == (a * c) * b")
   727  		}
   728  		a0.set(a)
   729  		field.squareAssign(a)
   730  		field.mulAssign(a0, a0)
   731  		if !a.equal(a0) {
   732  			t.Fatal("a^2 == a*a")
   733  		}
   734  	}
   735  }
   736  
   737  func TestFp2Exponentiation(t *testing.T) {
   738  	field := newFp2()
   739  	for i := 0; i < fuz; i++ {
   740  		a, _ := new(fe2).rand(rand.Reader)
   741  		u := field.new()
   742  		field.exp(u, a, big.NewInt(0))
   743  		if !u.equal(field.one()) {
   744  			t.Fatal("a^0 == 1")
   745  		}
   746  		field.exp(u, a, big.NewInt(1))
   747  		if !u.equal(a) {
   748  			t.Fatal("a^1 == a")
   749  		}
   750  		v := field.new()
   751  		field.mul(u, a, a)
   752  		field.mul(u, u, u)
   753  		field.mul(u, u, u)
   754  		field.exp(v, a, big.NewInt(8))
   755  		if !u.equal(v) {
   756  			t.Fatal("((a^2)^2)^2 == a^8")
   757  		}
   758  	}
   759  }
   760  
   761  func TestFp2Inversion(t *testing.T) {
   762  	field := newFp2()
   763  	u := field.new()
   764  	zero := field.zero()
   765  	one := field.one()
   766  	field.inverse(u, zero)
   767  	if !u.equal(zero) {
   768  		t.Fatal("(0 ^ -1) == 0)")
   769  	}
   770  	field.inverse(u, one)
   771  	if !u.equal(one) {
   772  		t.Fatal("(1 ^ -1) == 1)")
   773  	}
   774  	for i := 0; i < fuz; i++ {
   775  		a, _ := new(fe2).rand(rand.Reader)
   776  		field.inverse(u, a)
   777  		field.mul(u, u, a)
   778  		if !u.equal(one) {
   779  			t.Fatal("(r * a) * r * (a ^ -1) == r)")
   780  		}
   781  	}
   782  }
   783  
   784  func TestFp2SquareRoot(t *testing.T) {
   785  	field := newFp2()
   786  	for z := 0; z < 1000; z++ {
   787  		zi := new(fe)
   788  		sub(zi, &modulus, &fe{uint64(z * z)})
   789  		// r = (-z*z, 0)
   790  		r := &fe2{*zi, fe{0}}
   791  		toMont(&r[0], &r[0])
   792  		toMont(&r[1], &r[1])
   793  		c := field.new()
   794  		// sqrt((-z*z, 0)) = (0, z)
   795  		if !field.sqrt(c, r) {
   796  			t.Fatal("z*z does have a square root")
   797  		}
   798  		e := &fe2{fe{uint64(0)}, fe{uint64(z)}}
   799  		toMont(&e[0], &e[0])
   800  		toMont(&e[1], &e[1])
   801  		field.square(e, e)
   802  		field.square(c, c)
   803  		if !e.equal(c) {
   804  			t.Fatal("square root failed")
   805  		}
   806  	}
   807  	if field.sqrt(field.new(), nonResidue2) {
   808  		t.Fatal("non residue cannot have a sqrt")
   809  	}
   810  	for i := 0; i < fuz; i++ {
   811  		a, _ := new(fe2).rand(rand.Reader)
   812  		aa, rr, r := field.new(), field.new(), field.new()
   813  		field.square(aa, a)
   814  		if !field.sqrt(r, aa) {
   815  			t.Fatal("bad sqrt 1")
   816  		}
   817  		field.square(rr, r)
   818  		if !rr.equal(aa) {
   819  			t.Fatal("bad sqrt 2")
   820  		}
   821  	}
   822  }
   823  
   824  func TestFp2NonResidue(t *testing.T) {
   825  	field := newFp2()
   826  	if !field.isQuadraticNonResidue(nonResidue2) {
   827  		t.Fatal("element is quadratic non residue, 1")
   828  	}
   829  	if field.isQuadraticNonResidue(new(fe2).one()) {
   830  		t.Fatal("one is not quadratic non residue")
   831  	}
   832  	if !field.isQuadraticNonResidue(new(fe2).zero()) {
   833  		t.Fatal("should accept zero as quadratic non residue")
   834  	}
   835  	for i := 0; i < fuz; i++ {
   836  		a, _ := new(fe2).rand(rand.Reader)
   837  		field.squareAssign(a)
   838  		if field.isQuadraticNonResidue(new(fe2).one()) {
   839  			t.Fatal("element is not quadratic non residue")
   840  		}
   841  	}
   842  	for i := 0; i < fuz; i++ {
   843  		a, _ := new(fe2).rand(rand.Reader)
   844  		if !field.sqrt(new(fe2), a) {
   845  			if !field.isQuadraticNonResidue(a) {
   846  				t.Fatal("element is quadratic non residue, 2", i)
   847  			}
   848  		} else {
   849  			i -= 1
   850  		}
   851  	}
   852  }
   853  
   854  func TestFp6Serialization(t *testing.T) {
   855  	field := newFp6(nil)
   856  	for i := 0; i < fuz; i++ {
   857  		a, _ := new(fe6).rand(rand.Reader)
   858  		b, err := field.fromBytes(field.toBytes(a))
   859  		if err != nil {
   860  			t.Fatal(err)
   861  		}
   862  		if !a.equal(b) {
   863  			t.Fatal("bad serialization")
   864  		}
   865  	}
   866  }
   867  
   868  func TestFp6AdditionProperties(t *testing.T) {
   869  	field := newFp6(nil)
   870  	for i := 0; i < fuz; i++ {
   871  		zero := field.zero()
   872  		a, _ := new(fe6).rand(rand.Reader)
   873  		b, _ := new(fe6).rand(rand.Reader)
   874  		c_1 := field.new()
   875  		c_2 := field.new()
   876  		field.add(c_1, a, zero)
   877  		if !c_1.equal(a) {
   878  			t.Fatal("a + 0 == a")
   879  		}
   880  		field.sub(c_1, a, zero)
   881  		if !c_1.equal(a) {
   882  			t.Fatal("a - 0 == a")
   883  		}
   884  		field.double(c_1, zero)
   885  		if !c_1.equal(zero) {
   886  			t.Fatal("2 * 0 == 0")
   887  		}
   888  		field.neg(c_1, zero)
   889  		if !c_1.equal(zero) {
   890  			t.Fatal("-0 == 0")
   891  		}
   892  		field.sub(c_1, zero, a)
   893  		field.neg(c_2, a)
   894  		if !c_1.equal(c_2) {
   895  			t.Fatal("0-a == -a")
   896  		}
   897  		field.double(c_1, a)
   898  		field.add(c_2, a, a)
   899  		if !c_1.equal(c_2) {
   900  			t.Fatal("2 * a == a + a")
   901  		}
   902  		field.add(c_1, a, b)
   903  		field.add(c_2, b, a)
   904  		if !c_1.equal(c_2) {
   905  			t.Fatal("a + b = b + a")
   906  		}
   907  		field.sub(c_1, a, b)
   908  		field.sub(c_2, b, a)
   909  		field.neg(c_2, c_2)
   910  		if !c_1.equal(c_2) {
   911  			t.Fatal("a - b = - ( b - a )")
   912  		}
   913  		c_x, _ := new(fe6).rand(rand.Reader)
   914  		field.add(c_1, a, b)
   915  		field.add(c_1, c_1, c_x)
   916  		field.add(c_2, a, c_x)
   917  		field.add(c_2, c_2, b)
   918  		if !c_1.equal(c_2) {
   919  			t.Fatal("(a + b) + c == (a + c ) + b")
   920  		}
   921  		field.sub(c_1, a, b)
   922  		field.sub(c_1, c_1, c_x)
   923  		field.sub(c_2, a, c_x)
   924  		field.sub(c_2, c_2, b)
   925  		if !c_1.equal(c_2) {
   926  			t.Fatal("(a - b) - c == (a - c ) -b")
   927  		}
   928  	}
   929  }
   930  
   931  func TestFp6AdditionPropertiesAssigned(t *testing.T) {
   932  	field := newFp6(nil)
   933  	for i := 0; i < fuz; i++ {
   934  		zero := new(fe6).zero()
   935  		a, b := new(fe6), new(fe6)
   936  		_, _ = a.rand(rand.Reader)
   937  		b.set(a)
   938  		field.addAssign(a, zero)
   939  		if !a.equal(b) {
   940  			t.Fatal("a + 0 == a")
   941  		}
   942  		field.subAssign(a, zero)
   943  		if !a.equal(b) {
   944  			t.Fatal("a - 0 == a")
   945  		}
   946  		a.set(zero)
   947  		field.doubleAssign(a)
   948  		if !a.equal(zero) {
   949  			t.Fatal("2 * 0 == 0")
   950  		}
   951  		a.set(zero)
   952  		field.subAssign(a, b)
   953  		field.neg(b, b)
   954  		if !a.equal(b) {
   955  			t.Fatal("0-a == -a")
   956  		}
   957  		_, _ = a.rand(rand.Reader)
   958  		b.set(a)
   959  		field.doubleAssign(a)
   960  		field.addAssign(b, b)
   961  		if !a.equal(b) {
   962  			t.Fatal("2 * a == a + a")
   963  		}
   964  		_, _ = a.rand(rand.Reader)
   965  		_, _ = b.rand(rand.Reader)
   966  		c_1, c_2 := new(fe6).set(a), new(fe6).set(b)
   967  		field.addAssign(c_1, b)
   968  		field.addAssign(c_2, a)
   969  		if !c_1.equal(c_2) {
   970  			t.Fatal("a + b = b + a")
   971  		}
   972  		_, _ = a.rand(rand.Reader)
   973  		_, _ = b.rand(rand.Reader)
   974  		c_1.set(a)
   975  		c_2.set(b)
   976  		field.subAssign(c_1, b)
   977  		field.subAssign(c_2, a)
   978  		field.neg(c_2, c_2)
   979  		if !c_1.equal(c_2) {
   980  			t.Fatal("a - b = - ( b - a )")
   981  		}
   982  		_, _ = a.rand(rand.Reader)
   983  		_, _ = b.rand(rand.Reader)
   984  		c, _ := new(fe6).rand(rand.Reader)
   985  		a0 := new(fe6).set(a)
   986  		field.addAssign(a, b)
   987  		field.addAssign(a, c)
   988  		field.addAssign(b, c)
   989  		field.addAssign(b, a0)
   990  		if !a.equal(b) {
   991  			t.Fatal("(a + b) + c == (b + c) + a")
   992  		}
   993  		_, _ = a.rand(rand.Reader)
   994  		_, _ = b.rand(rand.Reader)
   995  		_, _ = c.rand(rand.Reader)
   996  		a0.set(a)
   997  		field.subAssign(a, b)
   998  		field.subAssign(a, c)
   999  		field.subAssign(a0, c)
  1000  		field.subAssign(a0, b)
  1001  		if !a.equal(a0) {
  1002  			t.Fatal("(a - b) - c == (a - c) -b")
  1003  		}
  1004  	}
  1005  }
  1006  
  1007  func TestFp6SparseMultiplication(t *testing.T) {
  1008  	fp6 := newFp6(nil)
  1009  	var a, b, u *fe6
  1010  	for j := 0; j < fuz; j++ {
  1011  		a, _ = new(fe6).rand(rand.Reader)
  1012  		b, _ = new(fe6).rand(rand.Reader)
  1013  		u, _ = new(fe6).rand(rand.Reader)
  1014  		b[2].zero()
  1015  		fp6.mul(u, a, b)
  1016  		fp6.mulBy01(a, a, &b[0], &b[1])
  1017  		if !a.equal(u) {
  1018  			t.Fatal("bad mul by 01")
  1019  		}
  1020  	}
  1021  	for j := 0; j < fuz; j++ {
  1022  		a, _ = new(fe6).rand(rand.Reader)
  1023  		b, _ = new(fe6).rand(rand.Reader)
  1024  		u, _ = new(fe6).rand(rand.Reader)
  1025  		b[2].zero()
  1026  		b[0].zero()
  1027  		fp6.mul(u, a, b)
  1028  		fp6.mulBy1(a, a, &b[1])
  1029  		if !a.equal(u) {
  1030  			t.Fatal("bad mul by 1")
  1031  		}
  1032  	}
  1033  }
  1034  
  1035  func TestFp6MultiplicationProperties(t *testing.T) {
  1036  	field := newFp6(nil)
  1037  	for i := 0; i < fuz; i++ {
  1038  		a, _ := new(fe6).rand(rand.Reader)
  1039  		b, _ := new(fe6).rand(rand.Reader)
  1040  		zero := field.zero()
  1041  		one := field.one()
  1042  		c_1, c_2 := field.new(), field.new()
  1043  		field.mul(c_1, a, zero)
  1044  		if !c_1.equal(zero) {
  1045  			t.Fatal("a * 0 == 0")
  1046  		}
  1047  		field.mul(c_1, a, one)
  1048  		if !c_1.equal(a) {
  1049  			t.Fatal("a * 1 == a")
  1050  		}
  1051  		field.mul(c_1, a, b)
  1052  		field.mul(c_2, b, a)
  1053  		if !c_1.equal(c_2) {
  1054  			t.Fatal("a * b == b * a")
  1055  		}
  1056  		c_x, _ := new(fe6).rand(rand.Reader)
  1057  		field.mul(c_1, a, b)
  1058  		field.mul(c_1, c_1, c_x)
  1059  		field.mul(c_2, c_x, b)
  1060  		field.mul(c_2, c_2, a)
  1061  		if !c_1.equal(c_2) {
  1062  			t.Fatal("(a * b) * c == (a * c) * b")
  1063  		}
  1064  		field.square(a, zero)
  1065  		if !a.equal(zero) {
  1066  			t.Fatal("0^2 == 0")
  1067  		}
  1068  		field.square(a, one)
  1069  		if !a.equal(one) {
  1070  			t.Fatal("1^2 == 1")
  1071  		}
  1072  		_, _ = a.rand(rand.Reader)
  1073  		field.square(c_1, a)
  1074  		field.mul(c_2, a, a)
  1075  		if !c_2.equal(c_1) {
  1076  			t.Fatal("a^2 == a*a")
  1077  		}
  1078  	}
  1079  }
  1080  
  1081  func TestFp6MultiplicationPropertiesAssigned(t *testing.T) {
  1082  	field := newFp6(nil)
  1083  	for i := 0; i < fuz; i++ {
  1084  		a, _ := new(fe6).rand(rand.Reader)
  1085  		zero, one := new(fe6).zero(), new(fe6).one()
  1086  		field.mulAssign(a, zero)
  1087  		if !a.equal(zero) {
  1088  			t.Fatal("a * 0 == 0")
  1089  		}
  1090  		_, _ = a.rand(rand.Reader)
  1091  		a0 := new(fe6).set(a)
  1092  		field.mulAssign(a, one)
  1093  		if !a.equal(a0) {
  1094  			t.Fatal("a * 1 == a")
  1095  		}
  1096  		_, _ = a.rand(rand.Reader)
  1097  		b, _ := new(fe6).rand(rand.Reader)
  1098  		a0.set(a)
  1099  		field.mulAssign(a, b)
  1100  		field.mulAssign(b, a0)
  1101  		if !a.equal(b) {
  1102  			t.Fatal("a * b == b * a")
  1103  		}
  1104  		c, _ := new(fe6).rand(rand.Reader)
  1105  		a0.set(a)
  1106  		field.mulAssign(a, b)
  1107  		field.mulAssign(a, c)
  1108  		field.mulAssign(a0, c)
  1109  		field.mulAssign(a0, b)
  1110  		if !a.equal(a0) {
  1111  			t.Fatal("(a * b) * c == (a * c) * b")
  1112  		}
  1113  	}
  1114  }
  1115  
  1116  func TestFp6Exponentiation(t *testing.T) {
  1117  	field := newFp6(nil)
  1118  	for i := 0; i < fuz; i++ {
  1119  		a, _ := new(fe6).rand(rand.Reader)
  1120  		u := field.new()
  1121  		field.exp(u, a, big.NewInt(0))
  1122  		if !u.equal(field.one()) {
  1123  			t.Fatal("a^0 == 1")
  1124  		}
  1125  		field.exp(u, a, big.NewInt(1))
  1126  		if !u.equal(a) {
  1127  			t.Fatal("a^1 == a")
  1128  		}
  1129  		v := field.new()
  1130  		field.mul(u, a, a)
  1131  		field.mul(u, u, u)
  1132  		field.mul(u, u, u)
  1133  		field.exp(v, a, big.NewInt(8))
  1134  		if !u.equal(v) {
  1135  			t.Fatal("((a^2)^2)^2 == a^8")
  1136  		}
  1137  	}
  1138  }
  1139  
  1140  func TestFp6Inversion(t *testing.T) {
  1141  	field := newFp6(nil)
  1142  	for i := 0; i < fuz; i++ {
  1143  		u := field.new()
  1144  		zero := field.zero()
  1145  		one := field.one()
  1146  		field.inverse(u, zero)
  1147  		if !u.equal(zero) {
  1148  			t.Fatal("(0^-1) == 0)")
  1149  		}
  1150  		field.inverse(u, one)
  1151  		if !u.equal(one) {
  1152  			t.Fatal("(1^-1) == 1)")
  1153  		}
  1154  		a, _ := new(fe6).rand(rand.Reader)
  1155  		field.inverse(u, a)
  1156  		field.mul(u, u, a)
  1157  		if !u.equal(one) {
  1158  			t.Fatal("(r*a) * r*(a^-1) == r)")
  1159  		}
  1160  	}
  1161  }
  1162  
  1163  func TestFp12Serialization(t *testing.T) {
  1164  	field := newFp12(nil)
  1165  	for i := 0; i < fuz; i++ {
  1166  		a, _ := new(fe12).rand(rand.Reader)
  1167  		b, err := field.fromBytes(field.toBytes(a))
  1168  		if err != nil {
  1169  			t.Fatal(err)
  1170  		}
  1171  		if !a.equal(b) {
  1172  			t.Fatal("bad serialization")
  1173  		}
  1174  	}
  1175  }
  1176  
  1177  func TestFp12AdditionProperties(t *testing.T) {
  1178  	field := newFp12(nil)
  1179  	for i := 0; i < fuz; i++ {
  1180  		zero := field.zero()
  1181  		a, _ := new(fe12).rand(rand.Reader)
  1182  		b, _ := new(fe12).rand(rand.Reader)
  1183  		c_1 := field.new()
  1184  		c_2 := field.new()
  1185  		field.add(c_1, a, zero)
  1186  		if !c_1.equal(a) {
  1187  			t.Fatal("a + 0 == a")
  1188  		}
  1189  		field.sub(c_1, a, zero)
  1190  		if !c_1.equal(a) {
  1191  			t.Fatal("a - 0 == a")
  1192  		}
  1193  		field.double(c_1, zero)
  1194  		if !c_1.equal(zero) {
  1195  			t.Fatal("2 * 0 == 0")
  1196  		}
  1197  		field.neg(c_1, zero)
  1198  		if !c_1.equal(zero) {
  1199  			t.Fatal("-0 == 0")
  1200  		}
  1201  		field.sub(c_1, zero, a)
  1202  		field.neg(c_2, a)
  1203  		if !c_1.equal(c_2) {
  1204  			t.Fatal("0-a == -a")
  1205  		}
  1206  		field.double(c_1, a)
  1207  		field.add(c_2, a, a)
  1208  		if !c_1.equal(c_2) {
  1209  			t.Fatal("2 * a == a + a")
  1210  		}
  1211  		field.add(c_1, a, b)
  1212  		field.add(c_2, b, a)
  1213  		if !c_1.equal(c_2) {
  1214  			t.Fatal("a + b = b + a")
  1215  		}
  1216  		field.sub(c_1, a, b)
  1217  		field.sub(c_2, b, a)
  1218  		field.neg(c_2, c_2)
  1219  		if !c_1.equal(c_2) {
  1220  			t.Fatal("a - b = - ( b - a )")
  1221  		}
  1222  		c_x, _ := new(fe12).rand(rand.Reader)
  1223  		field.add(c_1, a, b)
  1224  		field.add(c_1, c_1, c_x)
  1225  		field.add(c_2, a, c_x)
  1226  		field.add(c_2, c_2, b)
  1227  		if !c_1.equal(c_2) {
  1228  			t.Fatal("(a + b) + c == (a + c ) + b")
  1229  		}
  1230  		field.sub(c_1, a, b)
  1231  		field.sub(c_1, c_1, c_x)
  1232  		field.sub(c_2, a, c_x)
  1233  		field.sub(c_2, c_2, b)
  1234  		if !c_1.equal(c_2) {
  1235  			t.Fatal("(a - b) - c == (a - c ) -b")
  1236  		}
  1237  	}
  1238  }
  1239  
  1240  func TestFp12MultiplicationProperties(t *testing.T) {
  1241  	field := newFp12(nil)
  1242  	for i := 0; i < fuz; i++ {
  1243  		a, _ := new(fe12).rand(rand.Reader)
  1244  		b, _ := new(fe12).rand(rand.Reader)
  1245  		zero := field.zero()
  1246  		one := field.one()
  1247  		c_1, c_2 := field.new(), field.new()
  1248  		field.mul(c_1, a, zero)
  1249  		if !c_1.equal(zero) {
  1250  			t.Fatal("a * 0 == 0")
  1251  		}
  1252  		field.mul(c_1, a, one)
  1253  		if !c_1.equal(a) {
  1254  			t.Fatal("a * 1 == a")
  1255  		}
  1256  		field.mul(c_1, a, b)
  1257  		field.mul(c_2, b, a)
  1258  		if !c_1.equal(c_2) {
  1259  			t.Fatal("a * b == b * a")
  1260  		}
  1261  		c_x, _ := new(fe12).rand(rand.Reader)
  1262  		field.mul(c_1, a, b)
  1263  		field.mul(c_1, c_1, c_x)
  1264  		field.mul(c_2, c_x, b)
  1265  		field.mul(c_2, c_2, a)
  1266  		if !c_1.equal(c_2) {
  1267  			t.Fatal("(a * b) * c == (a * c) * b")
  1268  		}
  1269  		field.square(a, zero)
  1270  		if !a.equal(zero) {
  1271  			t.Fatal("0^2 == 0")
  1272  		}
  1273  		field.square(a, one)
  1274  		if !a.equal(one) {
  1275  			t.Fatal("1^2 == 1")
  1276  		}
  1277  		_, _ = a.rand(rand.Reader)
  1278  		field.square(c_1, a)
  1279  		field.mul(c_2, a, a)
  1280  		if !c_2.equal(c_1) {
  1281  			t.Fatal("a^2 == a*a")
  1282  		}
  1283  	}
  1284  }
  1285  
  1286  func TestFp12MultiplicationPropertiesAssigned(t *testing.T) {
  1287  	field := newFp12(nil)
  1288  	for i := 0; i < fuz; i++ {
  1289  		a, _ := new(fe12).rand(rand.Reader)
  1290  		zero, one := new(fe12).zero(), new(fe12).one()
  1291  		field.mulAssign(a, zero)
  1292  		if !a.equal(zero) {
  1293  			t.Fatal("a * 0 == 0")
  1294  		}
  1295  		_, _ = a.rand(rand.Reader)
  1296  		a0 := new(fe12).set(a)
  1297  		field.mulAssign(a, one)
  1298  		if !a.equal(a0) {
  1299  			t.Fatal("a * 1 == a")
  1300  		}
  1301  		_, _ = a.rand(rand.Reader)
  1302  		b, _ := new(fe12).rand(rand.Reader)
  1303  		a0.set(a)
  1304  		field.mulAssign(a, b)
  1305  		field.mulAssign(b, a0)
  1306  		if !a.equal(b) {
  1307  			t.Fatal("a * b == b * a")
  1308  		}
  1309  		c, _ := new(fe12).rand(rand.Reader)
  1310  		a0.set(a)
  1311  		field.mulAssign(a, b)
  1312  		field.mulAssign(a, c)
  1313  		field.mulAssign(a0, c)
  1314  		field.mulAssign(a0, b)
  1315  		if !a.equal(a0) {
  1316  			t.Fatal("(a * b) * c == (a * c) * b")
  1317  		}
  1318  	}
  1319  }
  1320  
  1321  func TestFp12SparseMultiplication(t *testing.T) {
  1322  	fp12 := newFp12(nil)
  1323  	var a, b, u *fe12
  1324  	for j := 0; j < fuz; j++ {
  1325  		a, _ = new(fe12).rand(rand.Reader)
  1326  		b, _ = new(fe12).rand(rand.Reader)
  1327  		u, _ = new(fe12).rand(rand.Reader)
  1328  		b[0][2].zero()
  1329  		b[1][0].zero()
  1330  		b[1][2].zero()
  1331  		fp12.mul(u, a, b)
  1332  		fp12.mulBy014Assign(a, &b[0][0], &b[0][1], &b[1][1])
  1333  		if !a.equal(u) {
  1334  			t.Fatal("bad mul by 01")
  1335  		}
  1336  	}
  1337  }
  1338  
  1339  func TestFp12Exponentiation(t *testing.T) {
  1340  	field := newFp12(nil)
  1341  	for i := 0; i < fuz; i++ {
  1342  		a, _ := new(fe12).rand(rand.Reader)
  1343  		u := field.new()
  1344  		field.exp(u, a, big.NewInt(0))
  1345  		if !u.equal(field.one()) {
  1346  			t.Fatal("a^0 == 1")
  1347  		}
  1348  		field.exp(u, a, big.NewInt(1))
  1349  		if !u.equal(a) {
  1350  			t.Fatal("a^1 == a")
  1351  		}
  1352  		v := field.new()
  1353  		field.mul(u, a, a)
  1354  		field.mul(u, u, u)
  1355  		field.mul(u, u, u)
  1356  		field.exp(v, a, big.NewInt(8))
  1357  		if !u.equal(v) {
  1358  			t.Fatal("((a^2)^2)^2 == a^8")
  1359  		}
  1360  	}
  1361  }
  1362  
  1363  func TestFp12Inversion(t *testing.T) {
  1364  	field := newFp12(nil)
  1365  	for i := 0; i < fuz; i++ {
  1366  		u := field.new()
  1367  		zero := field.zero()
  1368  		one := field.one()
  1369  		field.inverse(u, zero)
  1370  		if !u.equal(zero) {
  1371  			t.Fatal("(0^-1) == 0)")
  1372  		}
  1373  		field.inverse(u, one)
  1374  		if !u.equal(one) {
  1375  			t.Fatal("(1^-1) == 1)")
  1376  		}
  1377  		a, _ := new(fe12).rand(rand.Reader)
  1378  		field.inverse(u, a)
  1379  		field.mul(u, u, a)
  1380  		if !u.equal(one) {
  1381  			t.Fatal("(r*a) * r*(a^-1) == r)")
  1382  		}
  1383  	}
  1384  }
  1385  
  1386  func BenchmarkMultiplication(t *testing.B) {
  1387  	a, _ := new(fe).rand(rand.Reader)
  1388  	b, _ := new(fe).rand(rand.Reader)
  1389  	c, _ := new(fe).rand(rand.Reader)
  1390  	t.ResetTimer()
  1391  	for i := 0; i < t.N; i++ {
  1392  		mul(c, a, b)
  1393  	}
  1394  }
  1395  
  1396  func BenchmarkInverse(t *testing.B) {
  1397  	a, _ := new(fe).rand(rand.Reader)
  1398  	b, _ := new(fe).rand(rand.Reader)
  1399  	t.ResetTimer()
  1400  	for i := 0; i < t.N; i++ {
  1401  		inverse(a, b)
  1402  	}
  1403  }
  1404  
  1405  func padBytes(in []byte, size int) []byte {
  1406  	out := make([]byte, size)
  1407  	if len(in) > size {
  1408  		panic("bad input for padding")
  1409  	}
  1410  	copy(out[size-len(in):], in)
  1411  	return out
  1412  }