Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

342 řádky
8.4 KiB

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