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

     1  package fiat
     2  
     3  import (
     4  	"encoding/hex"
     5  	"math/big"
     6  	"testing"
     7  )
     8  
     9  // Reference https://github.com/mit-plv/fiat-crypto/blob/master/inversion/c/inversion_template.c
    10  func inverseByDivsteps2(g *[4]uint64) *[4]uint64 {
    11  	var precomp, v, vOut, rOut [4]uint64
    12  	var d, dOut uint64
    13  	var f, fOut, gOut, gs [5]uint64
    14  	var r sm2p256MontgomeryDomainFieldElement
    15  	r1 := (*[4]uint64)(&r)
    16  	sm2p256DivstepPrecomp(&precomp)
    17  	sm2p256Msat(&f)
    18  	sm2p256SetOne(&r)
    19  
    20  	copy(gs[:], g[:])
    21  
    22  	// 370 = (256 * 49 + 57) / 17 - 1
    23  	for i := 0; i < 370; i++ {
    24  		sm2p256Divstep(&dOut, &fOut, &gOut, &vOut, &rOut, d, &f, &gs, &v, r1)
    25  		sm2p256Divstep(&d, &f, &gs, &v, r1, dOut, &fOut, &gOut, &vOut, &rOut)
    26  	}
    27  
    28  	sm2p256Divstep(&dOut, &fOut, &gOut, &vOut, &rOut, d, &f, &gs, &v, r1)
    29  
    30  	var out sm2p256MontgomeryDomainFieldElement
    31  	sm2p256Opp(&out, (*sm2p256MontgomeryDomainFieldElement)(&vOut))
    32  	sm2p256Selectznz(&v, (sm2p256Uint1)(fOut[4]>>63), &vOut, (*[4]uint64)(&out))
    33  	sm2p256Mul(&out, (*sm2p256MontgomeryDomainFieldElement)(&v), (*sm2p256MontgomeryDomainFieldElement)(&precomp))
    34  
    35  	return (*[4]uint64)(&out)
    36  }
    37  
    38  func scalarInverseByDivsteps2(g *[4]uint64) *[4]uint64 {
    39  	var precomp, v, vOut, rOut [4]uint64
    40  	var d, dOut uint64
    41  	var f, fOut, gOut, gs [5]uint64
    42  	var r sm2p256scalarMontgomeryDomainFieldElement
    43  	r1 := (*[4]uint64)(&r)
    44  	sm2p256scalarDivstepPrecomp(&precomp)
    45  	sm2p256scalarMsat(&f)
    46  	sm2p256scalarSetOne(&r)
    47  
    48  	copy(gs[:], g[:])
    49  
    50  	// 370 = (256 * 49 + 57) / 17 - 1
    51  	for i := 0; i < 370; i++ {
    52  		sm2p256scalarDivstep(&dOut, &fOut, &gOut, &vOut, &rOut, d, &f, &gs, &v, r1)
    53  		sm2p256scalarDivstep(&d, &f, &gs, &v, r1, dOut, &fOut, &gOut, &vOut, &rOut)
    54  	}
    55  
    56  	sm2p256scalarDivstep(&dOut, &fOut, &gOut, &vOut, &rOut, d, &f, &gs, &v, r1)
    57  
    58  	var out sm2p256scalarMontgomeryDomainFieldElement
    59  	sm2p256scalarOpp(&out, (*sm2p256scalarMontgomeryDomainFieldElement)(&vOut))
    60  	sm2p256scalarSelectznz(&v, (sm2p256scalarUint1)(fOut[4]>>63), &vOut, (*[4]uint64)(&out))
    61  	sm2p256scalarMul(&out, (*sm2p256scalarMontgomeryDomainFieldElement)(&v), (*sm2p256scalarMontgomeryDomainFieldElement)(&precomp))
    62  
    63  	return (*[4]uint64)(&out)
    64  }
    65  
    66  func TestPrecomp(t *testing.T) {
    67  	pBytes, _ := hex.DecodeString("fffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff")
    68  	p := new(big.Int).SetBytes(pBytes)
    69  	m := new(big.Int).Add(p, big.NewInt(1))
    70  	m.Rsh(m, 1)
    71  	z := new(big.Int).Exp(m, big.NewInt(741), p)
    72  
    73  	v := new(SM2P256Element)
    74  	v.SetBytes(z.Bytes())
    75  
    76  	var precomp [4]uint64
    77  	sm2p256DivstepPrecomp(&precomp)
    78  
    79  	for i := 0; i < 4; i++ {
    80  		if v.x[i] != precomp[i] {
    81  			t.Errorf("got %x, want %x", v.x[i], precomp[i])
    82  		}
    83  	}
    84  }
    85  
    86  var testValues = []string{
    87  	"0000000000000000000000000000000000000000000000000000000000000001",
    88  	"0000000000000000000000000000000000000000000000000000000000000002",
    89  	"0000000000000000000000000000000000000000000000000000000000000003",
    90  	"1000000000000000000000000000000000000000000000000000000000000000",
    91  	"1000000000000000000000000000000000000000000000000000000000000001",
    92  	"1000000000000000000000000000000000000000000000000000000000000002",
    93  	"1000000000000000000000000000000000000000000000000000000000000003",
    94  	"8356e642a40ebd18d29ba3532fbd9f3bbee8f027c3f6f39a5ba2f870369f9988",
    95  	"981f5efe55d1c5cdf6c0ef2b070847a14f7fdf4272a8df09c442f3058af94ba1",
    96  	"d6833540d019e0438a5dd73b414f26ab43d8064b99671206944e284dbd969093",
    97  	"6c5a0a0b2eed3cbec3e4f1252bfe0e28c504a1c6bf1999eebb0af9ef0f8e6c85",
    98  }
    99  
   100  func TestInverseByDivsteps2(t *testing.T) {
   101  	for _, v := range testValues {
   102  		vBytes, _ := hex.DecodeString(v)
   103  
   104  		in, err := new(SM2P256Element).SetBytes(vBytes)
   105  		if err != nil {
   106  			t.Errorf("SetBytes failed: %v", err)
   107  		}
   108  		in2 := *(*[4]uint64)(&in.x)
   109  		out1 := new(SM2P256Element).Invert(in)
   110  		out1r := (*[4]uint64)(&out1.x)
   111  		out2 := inverseByDivsteps2(&in2)
   112  		tmp := (*sm2p256NonMontgomeryDomainFieldElement)(out2)
   113  		out3 := new(sm2p256MontgomeryDomainFieldElement)
   114  		sm2p256ToMontgomery(out3, tmp)
   115  		if *out3 != *out1r {
   116  			t.Errorf("got %v, want %v", out3, &out1.x)
   117  		}
   118  	}
   119  }
   120  
   121  func TestScalarInverseByDivsteps2(t *testing.T) {
   122  	for _, v := range testValues {
   123  		vBytes, _ := hex.DecodeString(v)
   124  
   125  		in, err := new(SM2P256OrderElement).SetBytes(vBytes)
   126  		if err != nil {
   127  			t.Errorf("SetBytes failed: %v", err)
   128  		}
   129  		in2 := *(*[4]uint64)(&in.x)
   130  		out1 := new(SM2P256OrderElement).Invert(in)
   131  		out1r := (*[4]uint64)(&out1.x)
   132  		out2 := scalarInverseByDivsteps2(&in2)
   133  		tmp := (*sm2p256scalarNonMontgomeryDomainFieldElement)(out2)
   134  		out3 := new(sm2p256scalarMontgomeryDomainFieldElement)
   135  		sm2p256scalarToMontgomery(out3, tmp)
   136  		if *out3 != *out1r {
   137  			t.Errorf("got %v, want %v", out3, &out1.x)
   138  		}
   139  	}
   140  }
   141  
   142  func BenchmarkSm2p256scalarDivstep(b *testing.B) {
   143  	var precomp, v, vOut, rOut [4]uint64
   144  	var d, dOut uint64
   145  	var f, fOut, gOut, gs [5]uint64
   146  	var r sm2p256scalarMontgomeryDomainFieldElement
   147  	r1 := (*[4]uint64)(&r)
   148  	sm2p256scalarDivstepPrecomp(&precomp)
   149  	sm2p256scalarMsat(&f)
   150  	sm2p256scalarSetOne(&r)
   151  
   152  	vBytes, _ := hex.DecodeString(testValues[0])
   153  
   154  	in, _ := new(SM2P256Element).SetBytes(vBytes)
   155  	g := *(*[4]uint64)(&in.x)
   156  	copy(gs[:], g[:])
   157  
   158  	b.ReportAllocs()
   159  	b.ResetTimer()
   160  
   161  	for i := 0; i < b.N; i++ {
   162  		sm2p256scalarDivstep(&dOut, &fOut, &gOut, &vOut, &rOut, d, &f, &gs, &v, r1)
   163  		sm2p256scalarDivstep(&d, &f, &gs, &v, r1, dOut, &fOut, &gOut, &vOut, &rOut)
   164  	}
   165  }
   166  
   167  func BenchmarkInverseByDivsteps2(b *testing.B) {
   168  	vBytes, _ := hex.DecodeString(testValues[0])
   169  
   170  	in, _ := new(SM2P256Element).SetBytes(vBytes)
   171  	in2 := *(*[4]uint64)(&in.x)
   172  	b.ReportAllocs()
   173  	b.ResetTimer()
   174  	for i := 0; i < b.N; i++ {
   175  		inverseByDivsteps2(&in2)
   176  	}
   177  }
   178  
   179  func BenchmarkInvert(b *testing.B) {
   180  	vBytes, _ := hex.DecodeString(testValues[0])
   181  
   182  	in, _ := new(SM2P256Element).SetBytes(vBytes)
   183  	out := new(SM2P256Element)
   184  	b.ReportAllocs()
   185  	b.ResetTimer()
   186  	for i := 0; i < b.N; i++ {
   187  		out.Invert(in)
   188  	}
   189  }
   190  
   191  func BenchmarkScalarInverseByDivsteps2(b *testing.B) {
   192  	vBytes, _ := hex.DecodeString(testValues[0])
   193  
   194  	in, _ := new(SM2P256OrderElement).SetBytes(vBytes)
   195  	in2 := *(*[4]uint64)(&in.x)
   196  	b.ReportAllocs()
   197  	b.ResetTimer()
   198  	for i := 0; i < b.N; i++ {
   199  		scalarInverseByDivsteps2(&in2)
   200  	}
   201  }
   202  
   203  func BenchmarkOrderInvert(b *testing.B) {
   204  	vBytes, _ := hex.DecodeString(testValues[0])
   205  
   206  	in, _ := new(SM2P256OrderElement).SetBytes(vBytes)
   207  	out := new(SM2P256OrderElement)
   208  	b.ReportAllocs()
   209  	b.ResetTimer()
   210  	for i := 0; i < b.N; i++ {
   211  		out.Invert(in)
   212  	}
   213  }