github.com/cloudflare/circl@v1.5.0/ecc/fourq/point_test.go (about)

     1  package fourq
     2  
     3  import (
     4  	"crypto/rand"
     5  	"math/big"
     6  	"testing"
     7  
     8  	"github.com/cloudflare/circl/internal/conv"
     9  	"github.com/cloudflare/circl/internal/test"
    10  )
    11  
    12  func (P *pointR1) random() {
    13  	var k [Size]byte
    14  	_, _ = rand.Read(k[:])
    15  	P.ScalarBaseMult(&k)
    16  }
    17  
    18  func TestPointAddition(t *testing.T) {
    19  	const testTimes = 1 << 10
    20  	var P, Q pointR1
    21  	_16P := &pointR1{}
    22  	S := &pointR2{}
    23  	for i := 0; i < testTimes; i++ {
    24  		P.random()
    25  		_16P.copy(&P)
    26  		S.FromR1(&P)
    27  		// 16P = 2^4P
    28  		for j := 0; j < 4; j++ {
    29  			_16P.double()
    30  		}
    31  		// 16P = P+P...+P
    32  		Q.SetIdentity()
    33  		for j := 0; j < 16; j++ {
    34  			Q.add(S)
    35  		}
    36  		got := _16P.isEqual(&Q)
    37  		want := true
    38  		if got != want {
    39  			test.ReportError(t, got, want, P)
    40  		}
    41  	}
    42  }
    43  
    44  func TestOddMultiples(t *testing.T) {
    45  	const testTimes = 1 << 10
    46  	var P, Q, R pointR1
    47  	var Tab [8]pointR2
    48  	for i := 0; i < testTimes; i++ {
    49  		P.random()
    50  		// T = [1P, 3P, 5P, 7P, 9P, 11P, 13P, 15P]
    51  		P.oddMultiples(&Tab)
    52  		// Q = sum of all T[i] == 64P
    53  		Q.SetIdentity()
    54  		for j := range Tab {
    55  			Q.add(&Tab[j])
    56  		}
    57  		// R = (2^6)P == 64P
    58  		for j := 0; j < 6; j++ {
    59  			R.double()
    60  		}
    61  		got := Q.isEqual(&R)
    62  		want := true
    63  		if got != want {
    64  			test.ReportError(t, got, want, P)
    65  		}
    66  	}
    67  }
    68  
    69  func TestScalarMult(t *testing.T) {
    70  	const testTimes = 1 << 10
    71  	var P, Q, G pointR1
    72  	var k [Size]byte
    73  
    74  	t.Run("0P=0", func(t *testing.T) {
    75  		for i := 0; i < testTimes; i++ {
    76  			P.random()
    77  			Q.ScalarMult(&k, &P)
    78  			got := Q.IsIdentity()
    79  			want := true
    80  			if got != want {
    81  				test.ReportError(t, got, want, P)
    82  			}
    83  		}
    84  	})
    85  	t.Run("order*P=0", func(t *testing.T) {
    86  		conv.BigInt2BytesLe(k[:], conv.Uint64Le2BigInt(orderGenerator[:]))
    87  		for i := 0; i < testTimes; i++ {
    88  			P.random()
    89  			Q.ScalarMult(&k, &P)
    90  			got := Q.IsIdentity()
    91  			want := true
    92  			if got != want {
    93  				test.ReportError(t, got, want, P)
    94  			}
    95  		}
    96  	})
    97  	t.Run("cofactor*P=clear(P)", func(t *testing.T) {
    98  		conv.BigInt2BytesLe(k[:], big.NewInt(392))
    99  		for i := 0; i < testTimes; i++ {
   100  			P.random()
   101  			Q.ScalarMult(&k, &P)
   102  			P.ClearCofactor()
   103  			got := Q.isEqual(&P)
   104  			want := true
   105  			if got != want {
   106  				test.ReportError(t, got, want, P)
   107  			}
   108  		}
   109  	})
   110  	t.Run("mult", func(t *testing.T) {
   111  		G.X = genX
   112  		G.Y = genY
   113  		for i := 0; i < testTimes; i++ {
   114  			_, _ = rand.Read(k[:])
   115  			P.ScalarMult(&k, &G)
   116  			Q.ScalarBaseMult(&k)
   117  			got := Q.isEqual(&P)
   118  			want := true
   119  			if got != want {
   120  				test.ReportError(t, got, want, k)
   121  			}
   122  		}
   123  	})
   124  }
   125  
   126  func TestScalar(t *testing.T) {
   127  	const testTimes = 1 << 12
   128  	var xx [5]uint64
   129  	two256 := big.NewInt(1)
   130  	two256.Lsh(two256, 256)
   131  	two64 := big.NewInt(1)
   132  	two64.Lsh(two64, 64)
   133  	bigOrder := conv.Uint64Le2BigInt(orderGenerator[:])
   134  
   135  	t.Run("subYdiv16", func(t *testing.T) {
   136  		want := new(big.Int)
   137  		for i := 0; i < testTimes; i++ {
   138  			bigX, _ := rand.Int(rand.Reader, two256)
   139  			conv.BigInt2Uint64Le(xx[:], bigX)
   140  			x := xx
   141  			bigY, _ := rand.Int(rand.Reader, two64)
   142  			y := bigY.Int64()
   143  			bigY.SetInt64(y)
   144  
   145  			subYDiv16(&x, y)
   146  			got := conv.Uint64Le2BigInt(x[:])
   147  
   148  			want.Sub(bigX, bigY).Rsh(want, 4)
   149  
   150  			if got.Cmp(want) != 0 {
   151  				test.ReportError(t, got, want, bigX, y)
   152  			}
   153  		}
   154  	})
   155  
   156  	t.Run("div2subY", func(t *testing.T) {
   157  		want := new(big.Int)
   158  		for i := 0; i < testTimes; i++ {
   159  			bigX, _ := rand.Int(rand.Reader, two256)
   160  			conv.BigInt2Uint64Le(xx[:], bigX)
   161  			x := xx
   162  			bigY, _ := rand.Int(rand.Reader, two64)
   163  			y := bigY.Int64()
   164  			bigY.SetInt64(y)
   165  
   166  			div2subY(&x, y)
   167  			got := conv.Uint64Le2BigInt(x[:])
   168  
   169  			want.Rsh(bigX, 1).Sub(want, bigY)
   170  
   171  			if got.Cmp(want) != 0 {
   172  				test.ReportError(t, got, want, bigX, y)
   173  			}
   174  		}
   175  	})
   176  
   177  	t.Run("condAddOrderN", func(t *testing.T) {
   178  		for i := 0; i < testTimes; i++ {
   179  			bigX, _ := rand.Int(rand.Reader, two256)
   180  			conv.BigInt2Uint64Le(xx[:], bigX)
   181  			x := xx
   182  
   183  			condAddOrderN(&x)
   184  			got := conv.Uint64Le2BigInt(x[:])
   185  
   186  			want := bigX
   187  			if want.Bit(0) == 0 {
   188  				want.Add(want, bigOrder)
   189  			}
   190  
   191  			if got.Cmp(want) != 0 {
   192  				test.ReportError(t, got, want, x)
   193  			}
   194  		}
   195  	})
   196  
   197  	t.Run("recode", func(t *testing.T) {
   198  		var k [32]byte
   199  		var d [65]int8
   200  		got := new(big.Int)
   201  		for i := 0; i < testTimes; i++ {
   202  			_, _ = rand.Read(k[:])
   203  
   204  			recodeScalar(&d, &k)
   205  			got.SetInt64(0)
   206  			for j := len(d) - 1; j >= 0; j-- {
   207  				got.Lsh(got, 4).Add(got, big.NewInt(int64(d[j])))
   208  			}
   209  
   210  			want := conv.BytesLe2BigInt(k[:])
   211  			if want.Bit(0) == 0 {
   212  				want.Add(want, bigOrder)
   213  			}
   214  
   215  			if got.Cmp(want) != 0 {
   216  				test.ReportError(t, got, want, k)
   217  			}
   218  		}
   219  	})
   220  }
   221  
   222  func BenchmarkPoint(b *testing.B) {
   223  	var P, R pointR1
   224  	var Q pointR2
   225  	var k [Size]byte
   226  
   227  	_, _ = rand.Read(k[:])
   228  
   229  	P.random()
   230  	R.random()
   231  	Q.FromR1(&R)
   232  	R.random()
   233  
   234  	b.Run("affine", func(b *testing.B) {
   235  		for i := 0; i < b.N; i++ {
   236  			P.ToAffine()
   237  		}
   238  	})
   239  	b.Run("double", func(b *testing.B) {
   240  		for i := 0; i < b.N; i++ {
   241  			P.double()
   242  		}
   243  	})
   244  	b.Run("add", func(b *testing.B) {
   245  		for i := 0; i < b.N; i++ {
   246  			P.add(&Q)
   247  		}
   248  	})
   249  	b.Run("scmulBase", func(b *testing.B) {
   250  		for i := 0; i < b.N; i++ {
   251  			P.ScalarBaseMult(&k)
   252  		}
   253  	})
   254  	b.Run("scmul", func(b *testing.B) {
   255  		for i := 0; i < b.N; i++ {
   256  			P.ScalarMult(&k, &R)
   257  		}
   258  	})
   259  }