Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

323 Zeilen
8.1 KiB

  1. package p751
  2. import (
  3. "math/big"
  4. "testing"
  5. "testing/quick"
  6. . "github.com/cloudflare/p751sidh/internal/isogeny"
  7. )
  8. func TestPrimeFieldElementToBigInt(t *testing.T) {
  9. // Chosen so that p < xR < 2p
  10. x := primeFieldElement{A: FpElement{
  11. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 140737488355328,
  12. }}
  13. // Computed using Sage:
  14. // sage: p = 2^372 * 3^239 - 1
  15. // sage: R = 2^768
  16. // sage: from_radix_64 = lambda xs: sum((xi * (2**64)**i for i,xi in enumerate(xs)))
  17. // sage: xR = from_radix_64([1]*11 + [2^47])
  18. // sage: assert(p < xR)
  19. // sage: assert(xR < 2*p)
  20. // sage: (xR / R) % p
  21. xBig, _ := new(big.Int).SetString("4469946751055876387821312289373600189787971305258234719850789711074696941114031433609871105823930699680637820852699269802003300352597419024286385747737509380032982821081644521634652750355306547718505685107272222083450567982240", 10)
  22. if xBig.Cmp(toBigInt(&x.A)) != 0 {
  23. t.Error("Expected", xBig, "found", toBigInt(&x.A))
  24. }
  25. }
  26. //------------------------------------------------------------------------------
  27. // Extended Field
  28. //------------------------------------------------------------------------------
  29. func TestOneFp2ToBytes(t *testing.T) {
  30. var x = P751_OneFp2
  31. var xBytes [188]byte
  32. kCurveOps.Fp2ToBytes(xBytes[:], &x)
  33. if xBytes[0] != 1 {
  34. t.Error("Expected 1, got", xBytes[0])
  35. }
  36. for i := 1; i < 188; i++ {
  37. if xBytes[i] != 0 {
  38. t.Error("Expected 0, got", xBytes[0])
  39. }
  40. }
  41. }
  42. func TestFp2ElementToBytesRoundTrip(t *testing.T) {
  43. roundTrips := func(x GeneratedTestParams) bool {
  44. var xBytes [188]byte
  45. var xPrime Fp2Element
  46. kCurveOps.Fp2ToBytes(xBytes[:], &x.ExtElem)
  47. kCurveOps.Fp2FromBytes(&xPrime, xBytes[:])
  48. return VartimeEqFp2(&xPrime, &x.ExtElem)
  49. }
  50. if err := quick.Check(roundTrips, quickCheckConfig); err != nil {
  51. t.Error(err)
  52. }
  53. }
  54. func TestFp2ElementMulDistributesOverAdd(t *testing.T) {
  55. mulDistributesOverAdd := func(x, y, z GeneratedTestParams) bool {
  56. // Compute t1 = (x+y)*z
  57. t1 := new(Fp2Element)
  58. kFieldOps.Add(t1, &x.ExtElem, &y.ExtElem)
  59. kFieldOps.Mul(t1, t1, &z.ExtElem)
  60. // Compute t2 = x*z + y*z
  61. t2 := new(Fp2Element)
  62. t3 := new(Fp2Element)
  63. kFieldOps.Mul(t2, &x.ExtElem, &z.ExtElem)
  64. kFieldOps.Mul(t3, &y.ExtElem, &z.ExtElem)
  65. kFieldOps.Add(t2, t2, t3)
  66. return VartimeEqFp2(t1, t2)
  67. }
  68. if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil {
  69. t.Error(err)
  70. }
  71. }
  72. func TestFp2ElementMulIsAssociative(t *testing.T) {
  73. isAssociative := func(x, y, z GeneratedTestParams) bool {
  74. // Compute t1 = (x*y)*z
  75. t1 := new(Fp2Element)
  76. kFieldOps.Mul(t1, &x.ExtElem, &y.ExtElem)
  77. kFieldOps.Mul(t1, t1, &z.ExtElem)
  78. // Compute t2 = (y*z)*x
  79. t2 := new(Fp2Element)
  80. kFieldOps.Mul(t2, &y.ExtElem, &z.ExtElem)
  81. kFieldOps.Mul(t2, t2, &x.ExtElem)
  82. return VartimeEqFp2(t1, t2)
  83. }
  84. if err := quick.Check(isAssociative, quickCheckConfig); err != nil {
  85. t.Error(err)
  86. }
  87. }
  88. func TestFp2ElementSquareMatchesMul(t *testing.T) {
  89. sqrMatchesMul := func(x GeneratedTestParams) bool {
  90. // Compute t1 = (x*x)
  91. t1 := new(Fp2Element)
  92. kFieldOps.Mul(t1, &x.ExtElem, &x.ExtElem)
  93. // Compute t2 = x^2
  94. t2 := new(Fp2Element)
  95. kFieldOps.Square(t2, &x.ExtElem)
  96. return VartimeEqFp2(t1, t2)
  97. }
  98. if err := quick.Check(sqrMatchesMul, quickCheckConfig); err != nil {
  99. t.Error(err)
  100. }
  101. }
  102. func TestFp2ElementInv(t *testing.T) {
  103. inverseIsCorrect := func(x GeneratedTestParams) bool {
  104. z := new(Fp2Element)
  105. kFieldOps.Inv(z, &x.ExtElem)
  106. // Now z = (1/x), so (z * x) * x == x
  107. kFieldOps.Mul(z, z, &x.ExtElem)
  108. kFieldOps.Mul(z, z, &x.ExtElem)
  109. return VartimeEqFp2(z, &x.ExtElem)
  110. }
  111. // This is more expensive; run fewer tests
  112. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  113. if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil {
  114. t.Error(err)
  115. }
  116. }
  117. func TestFp2ElementBatch3Inv(t *testing.T) {
  118. batchInverseIsCorrect := func(x1, x2, x3 GeneratedTestParams) bool {
  119. var x1Inv, x2Inv, x3Inv Fp2Element
  120. kFieldOps.Inv(&x1Inv, &x1.ExtElem)
  121. kFieldOps.Inv(&x2Inv, &x2.ExtElem)
  122. kFieldOps.Inv(&x3Inv, &x3.ExtElem)
  123. var y1, y2, y3 Fp2Element
  124. kCurveOps.Fp2Batch3Inv(&x1.ExtElem, &x2.ExtElem, &x3.ExtElem, &y1, &y2, &y3)
  125. return (VartimeEqFp2(&x1Inv,&y1) && VartimeEqFp2(&x2Inv,&y2) && VartimeEqFp2(&x3Inv,&y3))
  126. }
  127. // This is more expensive; run fewer tests
  128. var quickCheckConfig = &quick.Config{MaxCount: (1 << (5 + quickCheckScaleFactor))}
  129. if err := quick.Check(batchInverseIsCorrect, quickCheckConfig); err != nil {
  130. t.Error(err)
  131. }
  132. }
  133. //------------------------------------------------------------------------------
  134. // Prime Field
  135. //------------------------------------------------------------------------------
  136. func TestPrimeFieldElementMulVersusBigInt(t *testing.T) {
  137. mulMatchesBigInt := func(x, y primeFieldElement) bool {
  138. z := new(primeFieldElement)
  139. z.Mul(&x, &y)
  140. check := new(big.Int)
  141. check.Mul(toBigInt(&x.A), toBigInt(&y.A))
  142. check.Mod(check, cln16prime)
  143. return check.Cmp(toBigInt(&z.A)) == 0
  144. }
  145. if err := quick.Check(mulMatchesBigInt, quickCheckConfig); err != nil {
  146. t.Error(err)
  147. }
  148. }
  149. func TestPrimeFieldElementP34VersusBigInt(t *testing.T) {
  150. var p34, _ = new(big.Int).SetString("2588679435442326313244442059466701330356847411387267792529047419763669735170619711625720724140266678406138302904710050596300977994130638598261040117192787954244176710019728333589599932738193731745058771712747875468166412894207", 10)
  151. p34MatchesBigInt := func(x primeFieldElement) bool {
  152. z := new(primeFieldElement)
  153. z.P34(&x)
  154. check := toBigInt(&x.A)
  155. check.Exp(check, p34, cln16prime)
  156. return check.Cmp(toBigInt(&z.A)) == 0
  157. }
  158. // This is more expensive; run fewer tests
  159. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  160. if err := quick.Check(p34MatchesBigInt, quickCheckConfig); err != nil {
  161. t.Error(err)
  162. }
  163. }
  164. func BenchmarkFp2ElementMul(b *testing.B) {
  165. z := &Fp2Element{A: bench_x, B: bench_y}
  166. w := new(Fp2Element)
  167. for n := 0; n < b.N; n++ {
  168. kFieldOps.Mul(w, z, z)
  169. }
  170. }
  171. func BenchmarkFp2ElementInv(b *testing.B) {
  172. z := &Fp2Element{A: bench_x, B: bench_y}
  173. w := new(Fp2Element)
  174. for n := 0; n < b.N; n++ {
  175. kFieldOps.Inv(w, z)
  176. }
  177. }
  178. func BenchmarkFp2ElementSquare(b *testing.B) {
  179. z := &Fp2Element{A: bench_x, B: bench_y}
  180. w := new(Fp2Element)
  181. for n := 0; n < b.N; n++ {
  182. kFieldOps.Square(w, z)
  183. }
  184. }
  185. func BenchmarkFp2ElementAdd(b *testing.B) {
  186. z := &Fp2Element{A: bench_x, B: bench_y}
  187. w := new(Fp2Element)
  188. for n := 0; n < b.N; n++ {
  189. kFieldOps.Add(w, z, z)
  190. }
  191. }
  192. func BenchmarkFp2ElementSub(b *testing.B) {
  193. z := &Fp2Element{A: bench_x, B: bench_y}
  194. w := new(Fp2Element)
  195. for n := 0; n < b.N; n++ {
  196. kFieldOps.Sub(w, z, z)
  197. }
  198. }
  199. func BenchmarkPrimeFieldElementMul(b *testing.B) {
  200. z := &primeFieldElement{A: bench_x}
  201. w := new(primeFieldElement)
  202. for n := 0; n < b.N; n++ {
  203. w.Mul(z, z)
  204. }
  205. }
  206. // --- field operation functions
  207. func BenchmarkFp751Multiply(b *testing.B) {
  208. for n := 0; n < b.N; n++ {
  209. fp751Mul(&benchmarkFpElementX2, &bench_x, &bench_y)
  210. }
  211. }
  212. func BenchmarkFp751MontgomeryReduce(b *testing.B) {
  213. z := bench_z
  214. // This benchmark actually computes garbage, because
  215. // fp751MontgomeryReduce mangles its input, but since it's
  216. // constant-time that shouldn't matter for the benchmarks.
  217. for n := 0; n < b.N; n++ {
  218. fp751MontgomeryReduce(&benchmarkFpElement, &z)
  219. }
  220. }
  221. func BenchmarkFp751AddReduced(b *testing.B) {
  222. for n := 0; n < b.N; n++ {
  223. fp751AddReduced(&benchmarkFpElement, &bench_x, &bench_y)
  224. }
  225. }
  226. func BenchmarkFp751SubReduced(b *testing.B) {
  227. for n := 0; n < b.N; n++ {
  228. fp751SubReduced(&benchmarkFpElement, &bench_x, &bench_y)
  229. }
  230. }
  231. func BenchmarkFp751ConditionalSwap(b *testing.B) {
  232. x, y := bench_x, bench_y
  233. for n := 0; n < b.N; n++ {
  234. fp751ConditionalSwap(&x, &y, 1)
  235. fp751ConditionalSwap(&x, &y, 0)
  236. }
  237. }
  238. func BenchmarkFp751StrongReduce(b *testing.B) {
  239. x := bench_x
  240. for n := 0; n < b.N; n++ {
  241. fp751StrongReduce(&x)
  242. }
  243. }
  244. func BenchmarkFp751AddLazy(b *testing.B) {
  245. var z FpElement
  246. x, y := bench_x, bench_y
  247. for n := 0; n < b.N; n++ {
  248. fp751AddLazy(&z, &x, &y)
  249. }
  250. }
  251. func BenchmarkFp751X2AddLazy(b *testing.B) {
  252. x, y, z := bench_z, bench_z, bench_z
  253. for n := 0; n < b.N; n++ {
  254. fp751X2AddLazy(&x, &y, &z)
  255. }
  256. }
  257. func BenchmarkFp751X2SubLazy(b *testing.B) {
  258. x, y, z := bench_z, bench_z, bench_z
  259. for n := 0; n < b.N; n++ {
  260. fp751X2SubLazy(&x, &y, &z)
  261. }
  262. }