github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/crypto/internal/nistec/nistec_test.go (about)

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package nistec_test
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/elliptic"
    10  	"crypto/internal/nistec"
    11  	"internal/testenv"
    12  	"math/big"
    13  	"math/rand"
    14  	"testing"
    15  )
    16  
    17  func TestAllocations(t *testing.T) {
    18  	testenv.SkipIfOptimizationOff(t)
    19  
    20  	t.Run("P224", func(t *testing.T) {
    21  		if allocs := testing.AllocsPerRun(100, func() {
    22  			p := nistec.NewP224Point().SetGenerator()
    23  			scalar := make([]byte, 28)
    24  			rand.Read(scalar)
    25  			p.ScalarBaseMult(scalar)
    26  			p.ScalarMult(p, scalar)
    27  			out := p.Bytes()
    28  			if _, err := nistec.NewP224Point().SetBytes(out); err != nil {
    29  				t.Fatal(err)
    30  			}
    31  			out = p.BytesCompressed()
    32  			if _, err := p.SetBytes(out); err != nil {
    33  				t.Fatal(err)
    34  			}
    35  		}); allocs > 0 {
    36  			t.Errorf("expected zero allocations, got %0.1f", allocs)
    37  		}
    38  	})
    39  	t.Run("P256", func(t *testing.T) {
    40  		if allocs := testing.AllocsPerRun(100, func() {
    41  			p := nistec.NewP256Point().SetGenerator()
    42  			scalar := make([]byte, 32)
    43  			rand.Read(scalar)
    44  			p.ScalarBaseMult(scalar)
    45  			p.ScalarMult(p, scalar)
    46  			out := p.Bytes()
    47  			if _, err := nistec.NewP256Point().SetBytes(out); err != nil {
    48  				t.Fatal(err)
    49  			}
    50  			out = p.BytesCompressed()
    51  			if _, err := p.SetBytes(out); err != nil {
    52  				t.Fatal(err)
    53  			}
    54  		}); allocs > 0 {
    55  			t.Errorf("expected zero allocations, got %0.1f", allocs)
    56  		}
    57  	})
    58  	t.Run("P384", func(t *testing.T) {
    59  		if allocs := testing.AllocsPerRun(100, func() {
    60  			p := nistec.NewP384Point().SetGenerator()
    61  			scalar := make([]byte, 48)
    62  			rand.Read(scalar)
    63  			p.ScalarBaseMult(scalar)
    64  			p.ScalarMult(p, scalar)
    65  			out := p.Bytes()
    66  			if _, err := nistec.NewP384Point().SetBytes(out); err != nil {
    67  				t.Fatal(err)
    68  			}
    69  			out = p.BytesCompressed()
    70  			if _, err := p.SetBytes(out); err != nil {
    71  				t.Fatal(err)
    72  			}
    73  		}); allocs > 0 {
    74  			t.Errorf("expected zero allocations, got %0.1f", allocs)
    75  		}
    76  	})
    77  	t.Run("P521", func(t *testing.T) {
    78  		if allocs := testing.AllocsPerRun(100, func() {
    79  			p := nistec.NewP521Point().SetGenerator()
    80  			scalar := make([]byte, 66)
    81  			rand.Read(scalar)
    82  			p.ScalarBaseMult(scalar)
    83  			p.ScalarMult(p, scalar)
    84  			out := p.Bytes()
    85  			if _, err := nistec.NewP521Point().SetBytes(out); err != nil {
    86  				t.Fatal(err)
    87  			}
    88  			out = p.BytesCompressed()
    89  			if _, err := p.SetBytes(out); err != nil {
    90  				t.Fatal(err)
    91  			}
    92  		}); allocs > 0 {
    93  			t.Errorf("expected zero allocations, got %0.1f", allocs)
    94  		}
    95  	})
    96  }
    97  
    98  type nistPoint[T any] interface {
    99  	Bytes() []byte
   100  	SetGenerator() T
   101  	SetBytes([]byte) (T, error)
   102  	Add(T, T) T
   103  	Double(T) T
   104  	ScalarMult(T, []byte) (T, error)
   105  	ScalarBaseMult([]byte) (T, error)
   106  }
   107  
   108  func TestEquivalents(t *testing.T) {
   109  	t.Run("P224", func(t *testing.T) {
   110  		testEquivalents(t, nistec.NewP224Point, elliptic.P224())
   111  	})
   112  	t.Run("P256", func(t *testing.T) {
   113  		testEquivalents(t, nistec.NewP256Point, elliptic.P256())
   114  	})
   115  	t.Run("P384", func(t *testing.T) {
   116  		testEquivalents(t, nistec.NewP384Point, elliptic.P384())
   117  	})
   118  	t.Run("P521", func(t *testing.T) {
   119  		testEquivalents(t, nistec.NewP521Point, elliptic.P521())
   120  	})
   121  }
   122  
   123  func testEquivalents[P nistPoint[P]](t *testing.T, newPoint func() P, c elliptic.Curve) {
   124  	p := newPoint().SetGenerator()
   125  
   126  	elementSize := (c.Params().BitSize + 7) / 8
   127  	two := make([]byte, elementSize)
   128  	two[len(two)-1] = 2
   129  	nPlusTwo := make([]byte, elementSize)
   130  	new(big.Int).Add(c.Params().N, big.NewInt(2)).FillBytes(nPlusTwo)
   131  
   132  	p1 := newPoint().Double(p)
   133  	p2 := newPoint().Add(p, p)
   134  	p3, err := newPoint().ScalarMult(p, two)
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	p4, err := newPoint().ScalarBaseMult(two)
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  	p5, err := newPoint().ScalarMult(p, nPlusTwo)
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	p6, err := newPoint().ScalarBaseMult(nPlusTwo)
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	if !bytes.Equal(p1.Bytes(), p2.Bytes()) {
   152  		t.Error("P+P != 2*P")
   153  	}
   154  	if !bytes.Equal(p1.Bytes(), p3.Bytes()) {
   155  		t.Error("P+P != [2]P")
   156  	}
   157  	if !bytes.Equal(p1.Bytes(), p4.Bytes()) {
   158  		t.Error("G+G != [2]G")
   159  	}
   160  	if !bytes.Equal(p1.Bytes(), p5.Bytes()) {
   161  		t.Error("P+P != [N+2]P")
   162  	}
   163  	if !bytes.Equal(p1.Bytes(), p6.Bytes()) {
   164  		t.Error("G+G != [N+2]G")
   165  	}
   166  }
   167  
   168  func BenchmarkScalarMult(b *testing.B) {
   169  	b.Run("P224", func(b *testing.B) {
   170  		benchmarkScalarMult(b, nistec.NewP224Point().SetGenerator(), 28)
   171  	})
   172  	b.Run("P256", func(b *testing.B) {
   173  		benchmarkScalarMult(b, nistec.NewP256Point().SetGenerator(), 32)
   174  	})
   175  	b.Run("P384", func(b *testing.B) {
   176  		benchmarkScalarMult(b, nistec.NewP384Point().SetGenerator(), 48)
   177  	})
   178  	b.Run("P521", func(b *testing.B) {
   179  		benchmarkScalarMult(b, nistec.NewP521Point().SetGenerator(), 66)
   180  	})
   181  }
   182  
   183  func benchmarkScalarMult[P nistPoint[P]](b *testing.B, p P, scalarSize int) {
   184  	scalar := make([]byte, scalarSize)
   185  	rand.Read(scalar)
   186  	b.ReportAllocs()
   187  	b.ResetTimer()
   188  	for i := 0; i < b.N; i++ {
   189  		p.ScalarMult(p, scalar)
   190  	}
   191  }
   192  
   193  func BenchmarkScalarBaseMult(b *testing.B) {
   194  	b.Run("P224", func(b *testing.B) {
   195  		benchmarkScalarBaseMult(b, nistec.NewP224Point().SetGenerator(), 28)
   196  	})
   197  	b.Run("P256", func(b *testing.B) {
   198  		benchmarkScalarBaseMult(b, nistec.NewP256Point().SetGenerator(), 32)
   199  	})
   200  	b.Run("P384", func(b *testing.B) {
   201  		benchmarkScalarBaseMult(b, nistec.NewP384Point().SetGenerator(), 48)
   202  	})
   203  	b.Run("P521", func(b *testing.B) {
   204  		benchmarkScalarBaseMult(b, nistec.NewP521Point().SetGenerator(), 66)
   205  	})
   206  }
   207  
   208  func benchmarkScalarBaseMult[P nistPoint[P]](b *testing.B, p P, scalarSize int) {
   209  	scalar := make([]byte, scalarSize)
   210  	rand.Read(scalar)
   211  	b.ReportAllocs()
   212  	b.ResetTimer()
   213  	for i := 0; i < b.N; i++ {
   214  		p.ScalarBaseMult(scalar)
   215  	}
   216  }