Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

516 linhas
14 KiB

  1. package cln16sidh
  2. import (
  3. "math/big"
  4. "math/rand"
  5. "reflect"
  6. "testing"
  7. "testing/quick"
  8. )
  9. var quickCheckScaleFactor = uint8(3)
  10. var quickCheckConfig = &quick.Config{MaxCount: (1 << (12 + quickCheckScaleFactor))}
  11. var cln16prime, _ = new(big.Int).SetString("10354717741769305252977768237866805321427389645549071170116189679054678940682478846502882896561066713624553211618840202385203911976522554393044160468771151816976706840078913334358399730952774926980235086850991501872665651576831", 10)
  12. // Convert an fp751Element to a big.Int for testing. Because this is only
  13. // for testing, no big.Int to fp751Element conversion is provided.
  14. func radix64ToBigInt(x []uint64) *big.Int {
  15. radix := new(big.Int)
  16. // 2^64
  17. radix.UnmarshalText(([]byte)("18446744073709551616"))
  18. base := new(big.Int).SetUint64(1)
  19. val := new(big.Int).SetUint64(0)
  20. tmp := new(big.Int)
  21. for _, xi := range x {
  22. tmp.SetUint64(xi)
  23. tmp.Mul(tmp, base)
  24. val.Add(val, tmp)
  25. base.Mul(base, radix)
  26. }
  27. return val
  28. }
  29. func (x *PrimeFieldElement) toBigInt() *big.Int {
  30. // Convert from Montgomery form
  31. return x.a.toBigIntFromMontgomeryForm()
  32. }
  33. func (x *fp751Element) toBigIntFromMontgomeryForm() *big.Int {
  34. // Convert from Montgomery form
  35. a := fp751Element{}
  36. aR := fp751X2{}
  37. copy(aR[:], x[:]) // = a*R
  38. fp751MontgomeryReduce(&a, &aR) // = a mod p in [0,2p)
  39. fp751StrongReduce(&a) // = a mod p in [0,p)
  40. return radix64ToBigInt(a[:])
  41. }
  42. func TestPrimeFieldElementToBigInt(t *testing.T) {
  43. // Chosen so that p < xR < 2p
  44. x := PrimeFieldElement{a: fp751Element{
  45. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 140737488355328,
  46. }}
  47. // Computed using Sage:
  48. // sage: p = 2^372 * 3^239 - 1
  49. // sage: R = 2^768
  50. // sage: from_radix_64 = lambda xs: sum((xi * (2**64)**i for i,xi in enumerate(xs)))
  51. // sage: xR = from_radix_64([1]*11 + [2^47])
  52. // sage: assert(p < xR)
  53. // sage: assert(xR < 2*p)
  54. // sage: (xR / R) % p
  55. xBig, _ := new(big.Int).SetString("4469946751055876387821312289373600189787971305258234719850789711074696941114031433609871105823930699680637820852699269802003300352597419024286385747737509380032982821081644521634652750355306547718505685107272222083450567982240", 10)
  56. if xBig.Cmp(x.toBigInt()) != 0 {
  57. t.Error("Expected", xBig, "found", x.toBigInt())
  58. }
  59. }
  60. func generateFp751(rand *rand.Rand) fp751Element {
  61. // Generation strategy: low limbs taken from [0,2^64); high limb
  62. // taken from smaller range
  63. //
  64. // Size hint is ignored since all elements are fixed size.
  65. //
  66. // Field elements taken in range [0,2p). Emulate this by capping
  67. // the high limb by the top digit of 2*p-1:
  68. //
  69. // sage: (2*p-1).digits(2^64)[-1]
  70. // 246065832128056
  71. //
  72. // This still allows generating values >= 2p, but hopefully that
  73. // excess is OK (and if it's not, we'll find out, because it's for
  74. // testing...)
  75. //
  76. highLimb := rand.Uint64() % 246065832128056
  77. return fp751Element{
  78. rand.Uint64(),
  79. rand.Uint64(),
  80. rand.Uint64(),
  81. rand.Uint64(),
  82. rand.Uint64(),
  83. rand.Uint64(),
  84. rand.Uint64(),
  85. rand.Uint64(),
  86. rand.Uint64(),
  87. rand.Uint64(),
  88. rand.Uint64(),
  89. highLimb,
  90. }
  91. }
  92. func (x PrimeFieldElement) Generate(rand *rand.Rand, size int) reflect.Value {
  93. return reflect.ValueOf(PrimeFieldElement{a: generateFp751(rand)})
  94. }
  95. func (x ExtensionFieldElement) Generate(rand *rand.Rand, size int) reflect.Value {
  96. return reflect.ValueOf(ExtensionFieldElement{a: generateFp751(rand), b: generateFp751(rand)})
  97. }
  98. //------------------------------------------------------------------------------
  99. // Extension Field
  100. //------------------------------------------------------------------------------
  101. func TestExtensionFieldElementMulDistributesOverAdd(t *testing.T) {
  102. mulDistributesOverAdd := func(x, y, z ExtensionFieldElement) bool {
  103. // Compute t1 = (x+y)*z
  104. t1 := new(ExtensionFieldElement)
  105. t1.Add(&x, &y)
  106. t1.Mul(t1, &z)
  107. // Compute t2 = x*z + y*z
  108. t2 := new(ExtensionFieldElement)
  109. t3 := new(ExtensionFieldElement)
  110. t2.Mul(&x, &z)
  111. t3.Mul(&y, &z)
  112. t2.Add(t2, t3)
  113. return t1.VartimeEq(t2)
  114. }
  115. if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil {
  116. t.Error(err)
  117. }
  118. }
  119. func TestExtensionFieldElementMulIsAssociative(t *testing.T) {
  120. isAssociative := func(x, y, z ExtensionFieldElement) bool {
  121. // Compute t1 = (x*y)*z
  122. t1 := new(ExtensionFieldElement)
  123. t1.Mul(&x, &y)
  124. t1.Mul(t1, &z)
  125. // Compute t2 = (y*z)*x
  126. t2 := new(ExtensionFieldElement)
  127. t2.Mul(&y, &z)
  128. t2.Mul(t2, &x)
  129. return t1.VartimeEq(t2)
  130. }
  131. if err := quick.Check(isAssociative, quickCheckConfig); err != nil {
  132. t.Error(err)
  133. }
  134. }
  135. func TestExtensionFieldElementSquareMatchesMul(t *testing.T) {
  136. sqrMatchesMul := func(x ExtensionFieldElement) bool {
  137. // Compute t1 = (x*x)
  138. t1 := new(ExtensionFieldElement)
  139. t1.Mul(&x, &x)
  140. // Compute t2 = x^2
  141. t2 := new(ExtensionFieldElement)
  142. t2.Square(&x)
  143. return t1.VartimeEq(t2)
  144. }
  145. if err := quick.Check(sqrMatchesMul, quickCheckConfig); err != nil {
  146. t.Error(err)
  147. }
  148. }
  149. func TestExtensionFieldElementInv(t *testing.T) {
  150. inverseIsCorrect := func(x ExtensionFieldElement) bool {
  151. z := new(ExtensionFieldElement)
  152. z.Inv(&x)
  153. // Now z = (1/x), so (z * x) * x == x
  154. z.Mul(z, &x)
  155. z.Mul(z, &x)
  156. return z.VartimeEq(&x)
  157. }
  158. // This is more expensive; run fewer tests
  159. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  160. if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil {
  161. t.Error(err)
  162. }
  163. }
  164. func TestExtensionFieldElementBatch4Inv(t *testing.T) {
  165. batchInverseIsCorrect := func(x1, x2, x3, x4 ExtensionFieldElement) bool {
  166. var x1Inv, x2Inv, x3Inv, x4Inv ExtensionFieldElement
  167. x1Inv.Inv(&x1)
  168. x2Inv.Inv(&x2)
  169. x3Inv.Inv(&x3)
  170. x4Inv.Inv(&x4)
  171. var y1, y2, y3, y4 ExtensionFieldElement
  172. ExtensionFieldBatch4Inv(&x1, &x2, &x3, &x4, &y1, &y2, &y3, &y4)
  173. return (y1.VartimeEq(&x1Inv) && y2.VartimeEq(&x2Inv) &&
  174. y3.VartimeEq(&x3Inv) && y4.VartimeEq(&x4Inv))
  175. }
  176. // This is more expensive; run fewer tests
  177. var quickCheckConfig = &quick.Config{MaxCount: (1 << (5 + quickCheckScaleFactor))}
  178. if err := quick.Check(batchInverseIsCorrect, quickCheckConfig); err != nil {
  179. t.Error(err)
  180. }
  181. }
  182. //------------------------------------------------------------------------------
  183. // Prime Field
  184. //------------------------------------------------------------------------------
  185. func TestPrimeFieldElementSetUint64VersusBigInt(t *testing.T) {
  186. setUint64RoundTrips := func(x uint64) bool {
  187. z := new(PrimeFieldElement).SetUint64(x).toBigInt().Uint64()
  188. return x == z
  189. }
  190. if err := quick.Check(setUint64RoundTrips, quickCheckConfig); err != nil {
  191. t.Error(err)
  192. }
  193. }
  194. func TestPrimeFieldElementAddVersusBigInt(t *testing.T) {
  195. addMatchesBigInt := func(x, y PrimeFieldElement) bool {
  196. z := new(PrimeFieldElement)
  197. z.Add(&x, &y)
  198. check := new(big.Int)
  199. check.Add(x.toBigInt(), y.toBigInt())
  200. check.Mod(check, cln16prime)
  201. return check.Cmp(z.toBigInt()) == 0
  202. }
  203. if err := quick.Check(addMatchesBigInt, quickCheckConfig); err != nil {
  204. t.Error(err)
  205. }
  206. }
  207. func TestPrimeFieldElementSubVersusBigInt(t *testing.T) {
  208. subMatchesBigInt := func(x, y PrimeFieldElement) bool {
  209. z := new(PrimeFieldElement)
  210. z.Sub(&x, &y)
  211. check := new(big.Int)
  212. check.Sub(x.toBigInt(), y.toBigInt())
  213. check.Mod(check, cln16prime)
  214. return check.Cmp(z.toBigInt()) == 0
  215. }
  216. if err := quick.Check(subMatchesBigInt, quickCheckConfig); err != nil {
  217. t.Error(err)
  218. }
  219. }
  220. func TestPrimeFieldElementInv(t *testing.T) {
  221. inverseIsCorrect := func(x PrimeFieldElement) bool {
  222. z := new(PrimeFieldElement)
  223. z.Inv(&x)
  224. // Now z = (1/x), so (z * x) * x == x
  225. z.Mul(z, &x).Mul(z, &x)
  226. return z.VartimeEq(&x)
  227. }
  228. // This is more expensive; run fewer tests
  229. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  230. if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil {
  231. t.Error(err)
  232. }
  233. }
  234. func TestPrimeFieldElementSqrt(t *testing.T) {
  235. inverseIsCorrect := func(x PrimeFieldElement) bool {
  236. // Construct y = x^2 so we're sure y is square.
  237. y := new(PrimeFieldElement)
  238. y.Square(&x)
  239. z := new(PrimeFieldElement)
  240. z.Sqrt(y)
  241. // Now z = sqrt(y), so z^2 == y
  242. z.Square(z)
  243. return z.VartimeEq(y)
  244. }
  245. // This is more expensive; run fewer tests
  246. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  247. if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil {
  248. t.Error(err)
  249. }
  250. }
  251. func TestPrimeFieldElementMulVersusBigInt(t *testing.T) {
  252. mulMatchesBigInt := func(x, y PrimeFieldElement) bool {
  253. z := new(PrimeFieldElement)
  254. z.Mul(&x, &y)
  255. check := new(big.Int)
  256. check.Mul(x.toBigInt(), y.toBigInt())
  257. check.Mod(check, cln16prime)
  258. return check.Cmp(z.toBigInt()) == 0
  259. }
  260. if err := quick.Check(mulMatchesBigInt, quickCheckConfig); err != nil {
  261. t.Error(err)
  262. }
  263. }
  264. func TestPrimeFieldElementP34VersusBigInt(t *testing.T) {
  265. var p34, _ = new(big.Int).SetString("2588679435442326313244442059466701330356847411387267792529047419763669735170619711625720724140266678406138302904710050596300977994130638598261040117192787954244176710019728333589599932738193731745058771712747875468166412894207", 10)
  266. p34MatchesBigInt := func(x PrimeFieldElement) bool {
  267. z := new(PrimeFieldElement)
  268. z.P34(&x)
  269. check := x.toBigInt()
  270. check.Exp(check, p34, cln16prime)
  271. return check.Cmp(z.toBigInt()) == 0
  272. }
  273. // This is more expensive; run fewer tests
  274. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  275. if err := quick.Check(p34MatchesBigInt, quickCheckConfig); err != nil {
  276. t.Error(err)
  277. }
  278. }
  279. func TestFp751ElementConditionalSwap(t *testing.T) {
  280. var one = fp751Element{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
  281. var two = fp751Element{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
  282. var x = one
  283. var y = two
  284. fp751ConditionalSwap(&x, &y, 0)
  285. if !(x == one && y == two) {
  286. t.Error("Found", x, "expected", one)
  287. }
  288. fp751ConditionalSwap(&x, &y, 1)
  289. if !(x == two && y == one) {
  290. t.Error("Found", x, "expected", two)
  291. }
  292. }
  293. func TestFp751ElementConditionalAssign(t *testing.T) {
  294. var one = fp751Element{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
  295. var two = fp751Element{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
  296. var three = fp751Element{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}
  297. fp751ConditionalAssign(&one, &two, &three, 0)
  298. if one != two {
  299. t.Error("Found", one, "expected", two)
  300. }
  301. fp751ConditionalAssign(&one, &two, &three, 1)
  302. if one != three {
  303. t.Error("Found", one, "expected", three)
  304. }
  305. }
  306. // Package-level storage for this field element is intended to deter
  307. // compiler optimizations.
  308. var benchmarkFp751Element fp751Element
  309. var benchmarkFp751X2 fp751X2
  310. var bench_x = fp751Element{17026702066521327207, 5108203422050077993, 10225396685796065916, 11153620995215874678, 6531160855165088358, 15302925148404145445, 1248821577836769963, 9789766903037985294, 7493111552032041328, 10838999828319306046, 18103257655515297935, 27403304611634}
  311. var bench_y = fp751Element{4227467157325093378, 10699492810770426363, 13500940151395637365, 12966403950118934952, 16517692605450415877, 13647111148905630666, 14223628886152717087, 7167843152346903316, 15855377759596736571, 4300673881383687338, 6635288001920617779, 30486099554235}
  312. var bench_z = fp751X2{1595347748594595712, 10854920567160033970, 16877102267020034574, 12435724995376660096, 3757940912203224231, 8251999420280413600, 3648859773438820227, 17622716832674727914, 11029567000887241528, 11216190007549447055, 17606662790980286987, 4720707159513626555, 12887743598335030915, 14954645239176589309, 14178817688915225254, 1191346797768989683, 12629157932334713723, 6348851952904485603, 16444232588597434895, 7809979927681678066, 14642637672942531613, 3092657597757640067, 10160361564485285723, 240071237}
  313. func BenchmarkExtensionFieldElementMul(b *testing.B) {
  314. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  315. w := new(ExtensionFieldElement)
  316. for n := 0; n < b.N; n++ {
  317. w.Mul(z, z)
  318. }
  319. }
  320. func BenchmarkExtensionFieldElementInv(b *testing.B) {
  321. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  322. w := new(ExtensionFieldElement)
  323. for n := 0; n < b.N; n++ {
  324. w.Inv(z)
  325. }
  326. }
  327. func BenchmarkExtensionFieldElementSquare(b *testing.B) {
  328. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  329. w := new(ExtensionFieldElement)
  330. for n := 0; n < b.N; n++ {
  331. w.Square(z)
  332. }
  333. }
  334. func BenchmarkExtensionFieldElementAdd(b *testing.B) {
  335. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  336. w := new(ExtensionFieldElement)
  337. for n := 0; n < b.N; n++ {
  338. w.Add(z, z)
  339. }
  340. }
  341. func BenchmarkExtensionFieldElementSub(b *testing.B) {
  342. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  343. w := new(ExtensionFieldElement)
  344. for n := 0; n < b.N; n++ {
  345. w.Sub(z, z)
  346. }
  347. }
  348. func BenchmarkPrimeFieldElementMul(b *testing.B) {
  349. z := &PrimeFieldElement{a: bench_x}
  350. w := new(PrimeFieldElement)
  351. for n := 0; n < b.N; n++ {
  352. w.Mul(z, z)
  353. }
  354. }
  355. func BenchmarkPrimeFieldElementInv(b *testing.B) {
  356. z := &PrimeFieldElement{a: bench_x}
  357. w := new(PrimeFieldElement)
  358. for n := 0; n < b.N; n++ {
  359. w.Inv(z)
  360. }
  361. }
  362. func BenchmarkPrimeFieldElementSqrt(b *testing.B) {
  363. z := &PrimeFieldElement{a: bench_x}
  364. w := new(PrimeFieldElement)
  365. for n := 0; n < b.N; n++ {
  366. w.Sqrt(z)
  367. }
  368. }
  369. func BenchmarkPrimeFieldElementSquare(b *testing.B) {
  370. z := &PrimeFieldElement{a: bench_x}
  371. w := new(PrimeFieldElement)
  372. for n := 0; n < b.N; n++ {
  373. w.Square(z)
  374. }
  375. }
  376. func BenchmarkPrimeFieldElementAdd(b *testing.B) {
  377. z := &PrimeFieldElement{a: bench_x}
  378. w := new(PrimeFieldElement)
  379. for n := 0; n < b.N; n++ {
  380. w.Add(z, z)
  381. }
  382. }
  383. func BenchmarkPrimeFieldElementSub(b *testing.B) {
  384. z := &PrimeFieldElement{a: bench_x}
  385. w := new(PrimeFieldElement)
  386. for n := 0; n < b.N; n++ {
  387. w.Sub(z, z)
  388. }
  389. }
  390. func BenchmarkFp751Multiply(b *testing.B) {
  391. for n := 0; n < b.N; n++ {
  392. fp751Mul(&benchmarkFp751X2, &bench_x, &bench_y)
  393. }
  394. }
  395. func BenchmarkFp751MontgomeryReduce(b *testing.B) {
  396. z := bench_z
  397. // This benchmark actually computes garbage, because
  398. // fp751MontgomeryReduce mangles its input, but since it's
  399. // constant-time that shouldn't matter for the benchmarks.
  400. for n := 0; n < b.N; n++ {
  401. fp751MontgomeryReduce(&benchmarkFp751Element, &z)
  402. }
  403. }
  404. func BenchmarkFp751AddReduced(b *testing.B) {
  405. for n := 0; n < b.N; n++ {
  406. fp751AddReduced(&benchmarkFp751Element, &bench_x, &bench_y)
  407. }
  408. }
  409. func BenchmarkFp751SubReduced(b *testing.B) {
  410. for n := 0; n < b.N; n++ {
  411. fp751SubReduced(&benchmarkFp751Element, &bench_x, &bench_y)
  412. }
  413. }