github.com/cloudflare/circl@v1.5.0/dh/sidh/internal/p751/fp2_test.go (about)

     1  // Code generated by go generate; DO NOT EDIT.
     2  // This file was generated by robots.
     3  
     4  package p751
     5  
     6  import (
     7  	"math/rand"
     8  	"reflect"
     9  	"testing"
    10  	"testing/quick"
    11  
    12  	"github.com/cloudflare/circl/dh/sidh/internal/common"
    13  )
    14  
    15  type testParams struct {
    16  	Point   common.ProjectivePoint
    17  	Cparam  common.ProjectiveCurveParameters
    18  	ExtElem common.Fp2
    19  }
    20  
    21  // Returns true if lhs = rhs.  Takes variable time.
    22  func vartimeEqFp2(lhs, rhs *common.Fp2) bool {
    23  	a := *lhs
    24  	b := *rhs
    25  
    26  	modP751(&a.A)
    27  	modP751(&a.B)
    28  	modP751(&b.A)
    29  	modP751(&b.B)
    30  
    31  	eq := true
    32  	for i := 0; i < FpWords && eq; i++ {
    33  		eq = eq && (a.A[i] == b.A[i])
    34  		eq = eq && (a.B[i] == b.B[i])
    35  	}
    36  	return eq
    37  }
    38  
    39  func (testParams) generateFp2(rand *rand.Rand) common.Fp2 {
    40  	// Generation strategy: low limbs taken from [0,2^64); high limb
    41  	// taken from smaller range
    42  	//
    43  	// Size hint is ignored since all elements are fixed size.
    44  	//
    45  	// Field elements taken in range [0,2p).  Emulate this by capping
    46  	// the high limb by the top digit of 2*p-1:
    47  	//
    48  	// sage: (2*p-1).digits(2^64)[-1]
    49  	//
    50  	// This still allows generating values >= 2p, but hopefully that
    51  	// excess is OK (and if it's not, we'll find out, because it's for
    52  	// testing...)
    53  	highLimb := rand.Uint64() % P751x2[FpWords-1]
    54  	fpElementGen := func() (fp common.Fp) {
    55  		for i := 0; i < (FpWords - 1); i++ {
    56  			fp[i] = rand.Uint64()
    57  		}
    58  		fp[FpWords-1] = highLimb
    59  		return fp
    60  	}
    61  	return common.Fp2{A: fpElementGen(), B: fpElementGen()}
    62  }
    63  
    64  func (c testParams) Generate(rand *rand.Rand, size int) reflect.Value {
    65  	return reflect.ValueOf(
    66  		testParams{
    67  			common.ProjectivePoint{
    68  				X: c.generateFp2(rand),
    69  				Z: c.generateFp2(rand),
    70  			},
    71  			common.ProjectiveCurveParameters{
    72  				A: c.generateFp2(rand),
    73  				C: c.generateFp2(rand),
    74  			},
    75  			c.generateFp2(rand),
    76  		})
    77  }
    78  
    79  func TestOne(t *testing.T) {
    80  	var tmp common.Fp2
    81  
    82  	mul(&tmp, &params.OneFp2, &params.A.AffineP)
    83  	if !vartimeEqFp2(&tmp, &params.A.AffineP) {
    84  		t.Error("Not equal 1")
    85  	}
    86  }
    87  
    88  func TestFp2ToBytesRoundTrip(t *testing.T) {
    89  	roundTrips := func(x testParams) bool {
    90  		xBytes := make([]byte, 2*params.Bytelen)
    91  		var xPrime common.Fp2
    92  
    93  		common.Fp2ToBytes(xBytes[:], &x.ExtElem, params.Bytelen)
    94  		common.BytesToFp2(&xPrime, xBytes[:], params.Bytelen)
    95  		return vartimeEqFp2(&xPrime, &x.ExtElem)
    96  	}
    97  
    98  	if err := quick.Check(roundTrips, quickCheckConfig); err != nil {
    99  		t.Error(err)
   100  	}
   101  }
   102  
   103  func TestFp2MulDistributesOverAdd(t *testing.T) {
   104  	mulDistributesOverAdd := func(x, y, z testParams) bool {
   105  		// Compute t1 = (x+y)*z
   106  		t1 := new(common.Fp2)
   107  		add(t1, &x.ExtElem, &y.ExtElem)
   108  		mul(t1, t1, &z.ExtElem)
   109  
   110  		// Compute t2 = x*z + y*z
   111  		t2 := new(common.Fp2)
   112  		t3 := new(common.Fp2)
   113  		mul(t2, &x.ExtElem, &z.ExtElem)
   114  		mul(t3, &y.ExtElem, &z.ExtElem)
   115  		add(t2, t2, t3)
   116  
   117  		return vartimeEqFp2(t1, t2)
   118  	}
   119  
   120  	if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil {
   121  		t.Error(err)
   122  	}
   123  }
   124  
   125  func TestFp2MulIsAssociative(t *testing.T) {
   126  	isAssociative := func(x, y, z testParams) bool {
   127  		// Compute t1 = (x*y)*z
   128  		t1 := new(common.Fp2)
   129  		mul(t1, &x.ExtElem, &y.ExtElem)
   130  		mul(t1, t1, &z.ExtElem)
   131  
   132  		// Compute t2 = (y*z)*x
   133  		t2 := new(common.Fp2)
   134  		mul(t2, &y.ExtElem, &z.ExtElem)
   135  		mul(t2, t2, &x.ExtElem)
   136  
   137  		return vartimeEqFp2(t1, t2)
   138  	}
   139  
   140  	if err := quick.Check(isAssociative, quickCheckConfig); err != nil {
   141  		t.Error(err)
   142  	}
   143  }
   144  
   145  func TestFp2SquareMatchesMul(t *testing.T) {
   146  	sqrMatchesMul := func(x testParams) bool {
   147  		// Compute t1 = (x*x)
   148  		t1 := new(common.Fp2)
   149  		mul(t1, &x.ExtElem, &x.ExtElem)
   150  
   151  		// Compute t2 = x^2
   152  		t2 := new(common.Fp2)
   153  		sqr(t2, &x.ExtElem)
   154  
   155  		return vartimeEqFp2(t1, t2)
   156  	}
   157  
   158  	if err := quick.Check(sqrMatchesMul, quickCheckConfig); err != nil {
   159  		t.Error(err)
   160  	}
   161  }
   162  
   163  func TestFp2Inv(t *testing.T) {
   164  	inverseIsCorrect := func(x testParams) bool {
   165  		z := new(common.Fp2)
   166  		inv(z, &x.ExtElem)
   167  
   168  		// Now z = (1/x), so (z * x) * x == x
   169  		mul(z, z, &x.ExtElem)
   170  		mul(z, z, &x.ExtElem)
   171  
   172  		return vartimeEqFp2(z, &x.ExtElem)
   173  	}
   174  
   175  	// This is more expensive; run fewer tests
   176  	fasterCheckConfig := &quick.Config{MaxCount: (1 << 11)}
   177  	if err := quick.Check(inverseIsCorrect, fasterCheckConfig); err != nil {
   178  		t.Error(err)
   179  	}
   180  }
   181  
   182  func TestFp2Batch3Inv(t *testing.T) {
   183  	batchInverseIsCorrect := func(x1, x2, x3 testParams) bool {
   184  		var x1Inv, x2Inv, x3Inv common.Fp2
   185  		inv(&x1Inv, &x1.ExtElem)
   186  		inv(&x2Inv, &x2.ExtElem)
   187  		inv(&x3Inv, &x3.ExtElem)
   188  
   189  		var y1, y2, y3 common.Fp2
   190  		Fp2Batch3Inv(&x1.ExtElem, &x2.ExtElem, &x3.ExtElem, &y1, &y2, &y3)
   191  
   192  		return (vartimeEqFp2(&x1Inv, &y1) && vartimeEqFp2(&x2Inv, &y2) && vartimeEqFp2(&x3Inv, &y3))
   193  	}
   194  
   195  	// This is more expensive; run fewer tests
   196  	fasterCheckConfig := &quick.Config{MaxCount: (1 << 8)}
   197  	if err := quick.Check(batchInverseIsCorrect, fasterCheckConfig); err != nil {
   198  		t.Error(err)
   199  	}
   200  }
   201  
   202  func BenchmarkFp2Mul(b *testing.B) {
   203  	z := &common.Fp2{A: bench_x, B: bench_y}
   204  	w := new(common.Fp2)
   205  
   206  	for n := 0; n < b.N; n++ {
   207  		mul(w, z, z)
   208  	}
   209  }
   210  
   211  func BenchmarkFp2Inv(b *testing.B) {
   212  	z := &common.Fp2{A: bench_x, B: bench_y}
   213  	w := new(common.Fp2)
   214  
   215  	for n := 0; n < b.N; n++ {
   216  		inv(w, z)
   217  	}
   218  }
   219  
   220  func BenchmarkFp2Square(b *testing.B) {
   221  	z := &common.Fp2{A: bench_x, B: bench_y}
   222  	w := new(common.Fp2)
   223  
   224  	for n := 0; n < b.N; n++ {
   225  		sqr(w, z)
   226  	}
   227  }
   228  
   229  func BenchmarkFp2Add(b *testing.B) {
   230  	z := &common.Fp2{A: bench_x, B: bench_y}
   231  	w := new(common.Fp2)
   232  
   233  	for n := 0; n < b.N; n++ {
   234  		add(w, z, z)
   235  	}
   236  }
   237  
   238  func BenchmarkFp2Sub(b *testing.B) {
   239  	z := &common.Fp2{A: bench_x, B: bench_y}
   240  	w := new(common.Fp2)
   241  
   242  	for n := 0; n < b.N; n++ {
   243  		sub(w, z, z)
   244  	}
   245  }