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 }