github.com/emmansun/gmsm@v0.29.1/internal/sm2ec/sm2p256_asm_test.go (about)

     1  //go:build (amd64 || arm64 || s390x || ppc64le) && !purego
     2  
     3  package sm2ec
     4  
     5  import (
     6  	"bytes"
     7  	"crypto/rand"
     8  	"encoding/hex"
     9  	"io"
    10  	"math/big"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  // fromBig converts a *big.Int into a format used by this code.
    16  func fromBig(out *p256Element, big *big.Int) {
    17  	for i := range out {
    18  		out[i] = 0
    19  	}
    20  
    21  	for i, v := range big.Bits() {
    22  		out[i] = uint64(v)
    23  	}
    24  }
    25  
    26  func toBigInt(in *p256Element) *big.Int {
    27  	var valBytes [32]byte
    28  	p256LittleToBig(&valBytes, in)
    29  	return new(big.Int).SetBytes(valBytes[:])
    30  }
    31  
    32  func p256MulTest(t *testing.T, x, y, p, r *big.Int) {
    33  	x1 := new(big.Int).Mul(x, r)
    34  	x1 = x1.Mod(x1, p)
    35  	y1 := new(big.Int).Mul(y, r)
    36  	y1 = y1.Mod(y1, p)
    37  	ax := new(p256Element)
    38  	ay := new(p256Element)
    39  	res := new(p256Element)
    40  	res2 := new(p256Element)
    41  	fromBig(ax, x1)
    42  	fromBig(ay, y1)
    43  	p256Mul(res2, ax, ay)
    44  	p256FromMont(res, res2)
    45  	resInt := toBigInt(res)
    46  
    47  	expected := new(big.Int).Mul(x, y)
    48  	expected = expected.Mod(expected, p)
    49  	if resInt.Cmp(expected) != 0 {
    50  		t.FailNow()
    51  	}
    52  }
    53  
    54  func TestP256MulPMinus1(t *testing.T) {
    55  	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
    56  	r, _ := new(big.Int).SetString("10000000000000000000000000000000000000000000000000000000000000000", 16)
    57  	pMinus1 := new(big.Int).Sub(p, big.NewInt(1))
    58  	p256MulTest(t, pMinus1, pMinus1, p, r)
    59  }
    60  
    61  func TestFuzzyP256Mul(t *testing.T) {
    62  	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
    63  	r, _ := new(big.Int).SetString("10000000000000000000000000000000000000000000000000000000000000000", 16)
    64  	var scalar1 [32]byte
    65  	var scalar2 [32]byte
    66  	var timeout *time.Timer
    67  
    68  	if testing.Short() {
    69  		timeout = time.NewTimer(10 * time.Millisecond)
    70  	} else {
    71  		timeout = time.NewTimer(2 * time.Second)
    72  	}
    73  	for {
    74  		select {
    75  		case <-timeout.C:
    76  			return
    77  		default:
    78  		}
    79  		io.ReadFull(rand.Reader, scalar1[:])
    80  		io.ReadFull(rand.Reader, scalar2[:])
    81  		x := new(big.Int).SetBytes(scalar1[:])
    82  		y := new(big.Int).SetBytes(scalar2[:])
    83  		p256MulTest(t, x, y, p, r)
    84  	}
    85  }
    86  
    87  func BenchmarkP256Mul(b *testing.B) {
    88  	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
    89  	r, _ := new(big.Int).SetString("10000000000000000000000000000000000000000000000000000000000000000", 16)
    90  	var scalar1 [32]byte
    91  	io.ReadFull(rand.Reader, scalar1[:])
    92  	x := new(big.Int).SetBytes(scalar1[:])
    93  	x1 := new(big.Int).Mul(x, r)
    94  	x1 = x1.Mod(x1, p)
    95  	ax := new(p256Element)
    96  	res := new(p256Element)
    97  	fromBig(ax, x1)
    98  	b.ResetTimer()
    99  	for i := 0; i < b.N; i++ {
   100  		p256Mul(res, ax, ax)
   101  	}
   102  }
   103  
   104  func p256SqrTest(t *testing.T, x, p, r *big.Int) {
   105  	x1 := new(big.Int).Mul(x, r)
   106  	x1 = x1.Mod(x1, p)
   107  	ax := new(p256Element)
   108  	res := new(p256Element)
   109  	res2 := new(p256Element)
   110  	fromBig(ax, x1)
   111  	p256Sqr(res2, ax, 1)
   112  	p256FromMont(res, res2)
   113  	resInt := toBigInt(res)
   114  
   115  	expected := new(big.Int).Mul(x, x)
   116  	expected = expected.Mod(expected, p)
   117  	if resInt.Cmp(expected) != 0 {
   118  		t.FailNow()
   119  	}
   120  }
   121  
   122  func TestP256SqrPMinus1(t *testing.T) {
   123  	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
   124  	r, _ := new(big.Int).SetString("10000000000000000000000000000000000000000000000000000000000000000", 16)
   125  	pMinus1 := new(big.Int).Sub(p, big.NewInt(1))
   126  	p256SqrTest(t, pMinus1, p, r)
   127  }
   128  
   129  func TestFuzzyP256Sqr(t *testing.T) {
   130  	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
   131  	r, _ := new(big.Int).SetString("10000000000000000000000000000000000000000000000000000000000000000", 16)
   132  	var scalar1 [32]byte
   133  	var timeout *time.Timer
   134  
   135  	if testing.Short() {
   136  		timeout = time.NewTimer(10 * time.Millisecond)
   137  	} else {
   138  		timeout = time.NewTimer(2 * time.Second)
   139  	}
   140  	for {
   141  		select {
   142  		case <-timeout.C:
   143  			return
   144  		default:
   145  		}
   146  		io.ReadFull(rand.Reader, scalar1[:])
   147  		x := new(big.Int).SetBytes(scalar1[:])
   148  		p256SqrTest(t, x, p, r)
   149  	}
   150  }
   151  
   152  func BenchmarkP256Sqr(b *testing.B) {
   153  	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
   154  	r, _ := new(big.Int).SetString("10000000000000000000000000000000000000000000000000000000000000000", 16)
   155  	var scalar1 [32]byte
   156  	io.ReadFull(rand.Reader, scalar1[:])
   157  	x := new(big.Int).SetBytes(scalar1[:])
   158  	x1 := new(big.Int).Mul(x, r)
   159  	x1 = x1.Mod(x1, p)
   160  	ax := new(p256Element)
   161  	res := new(p256Element)
   162  	fromBig(ax, x1)
   163  	b.ResetTimer()
   164  	for i := 0; i < b.N; i++ {
   165  		p256Sqr(res, ax, 20)
   166  	}
   167  }
   168  
   169  func Test_p256Inverse(t *testing.T) {
   170  	r, _ := new(big.Int).SetString("10000000000000000000000000000000000000000000000000000000000000000", 16)
   171  	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
   172  	x, _ := new(big.Int).SetString("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16)
   173  	gx := &p256Element{0x61328990f418029e, 0x3e7981eddca6c050, 0xd6a1ed99ac24c3c3, 0x91167a5ee1c13b05}
   174  	res := new(p256Element)
   175  	p256Inverse(res, gx)
   176  	resInt := toBigInt(res)
   177  	xInv := new(big.Int).ModInverse(x, p)
   178  	xInv = new(big.Int).Mul(xInv, r)
   179  	xInv = new(big.Int).Mod(xInv, p)
   180  	if resInt.Cmp(xInv) != 0 {
   181  		t.Errorf("expected %v, got %v", hex.EncodeToString(xInv.Bytes()), hex.EncodeToString(resInt.Bytes()))
   182  	}
   183  }
   184  
   185  func BenchmarkP256SelectAffine(b *testing.B) {
   186  	var t0 p256AffinePoint
   187  	for i := 0; i < b.N; i++ {
   188  		p256SelectAffine(&t0, &p256Precomputed[20], 20)
   189  	}
   190  }
   191  
   192  func TestPointDouble(t *testing.T) {
   193  	var double1, double2 SM2P256Point
   194  	p := NewSM2P256Point().SetGenerator()
   195  	p256PointDoubleAsm(&double1, p)
   196  	p256PointDoubleAsm(&double1, &double1)
   197  	p256PointDoubleAsm(&double1, &double1)
   198  	p256PointDoubleAsm(&double1, &double1)
   199  	p256PointDoubleAsm(&double1, &double1)
   200  	p256PointDoubleAsm(&double1, &double1)
   201  
   202  	p256PointDouble6TimesAsm(&double2, p)
   203  	if !bytes.Equal(double1.Bytes(), double2.Bytes()) {
   204  		t.Error("PointDouble6Times is incorrect")
   205  	}
   206  
   207  	if hex.EncodeToString(double1.Bytes()) != "0497662389f36ce643a47dcf644f700651e988794843797b0c4a69c806e78615c2cd4d9449aea5cac5328b8d67d4ae956f5eb06c4515ff01bd17eef58bf866b33f" {
   208  		t.Errorf("PointDouble6Times is incorrect %x", double1.Bytes())
   209  	}
   210  }
   211  
   212  func TestPointAdd(t *testing.T) {
   213  	p := NewSM2P256Point().SetGenerator()
   214  	var p1, p2, sum1, sum2 SM2P256Point
   215  	p256PointDoubleAsm(&p1, p)
   216  	p256PointAddAsm(&sum1, p, &p1)
   217  
   218  	p256PointDouble6TimesAsm(&p2, p)
   219  	p256PointAddAsm(&sum2, p, &p2)
   220  
   221  	if hex.EncodeToString(sum1.Bytes()) != "04a97f7cd4b3c993b4be2daa8cdb41e24ca13f6bd945302244e26918f1d0509ebf530b5dd88c688ef5ccc5cec08a72150f7c400ee5cd045292aaacdd037458f6e6" {
   222  		t.Errorf("G + [2]G is incorrect %x", sum1.Bytes())
   223  	}
   224  	if hex.EncodeToString(sum2.Bytes()) != "04403b18162679c05515a8ecd063d726ba7b1eb83b8306ace5cd382e53ed23ae1feb42ebf496a7bd698d61a1c805ef7074df882dfcffcc84bcd0a5d4ebea56f425" {
   225  		t.Errorf("G + [64]G is incorrect %x", sum2.Bytes())
   226  	}
   227  }