您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

546 行
15 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 TestOneExtensionFieldToBytes(t *testing.T) {
  102. var x ExtensionFieldElement
  103. var xBytes [188]byte
  104. x.One()
  105. x.ToBytes(xBytes[:])
  106. if xBytes[0] != 1 {
  107. t.Error("Expected 1, got", xBytes[0])
  108. }
  109. for i := 1; i < 188; i++ {
  110. if xBytes[i] != 0 {
  111. t.Error("Expected 0, got", xBytes[0])
  112. }
  113. }
  114. }
  115. func TestExtensionFieldElementToBytesRoundTrip(t *testing.T) {
  116. roundTrips := func(x ExtensionFieldElement) bool {
  117. var xBytes [188]byte
  118. var xPrime ExtensionFieldElement
  119. x.ToBytes(xBytes[:])
  120. xPrime.FromBytes(xBytes[:])
  121. return x.VartimeEq(&xPrime)
  122. }
  123. if err := quick.Check(roundTrips, quickCheckConfig); err != nil {
  124. t.Error(err)
  125. }
  126. }
  127. func TestExtensionFieldElementMulDistributesOverAdd(t *testing.T) {
  128. mulDistributesOverAdd := func(x, y, z ExtensionFieldElement) bool {
  129. // Compute t1 = (x+y)*z
  130. t1 := new(ExtensionFieldElement)
  131. t1.Add(&x, &y)
  132. t1.Mul(t1, &z)
  133. // Compute t2 = x*z + y*z
  134. t2 := new(ExtensionFieldElement)
  135. t3 := new(ExtensionFieldElement)
  136. t2.Mul(&x, &z)
  137. t3.Mul(&y, &z)
  138. t2.Add(t2, t3)
  139. return t1.VartimeEq(t2)
  140. }
  141. if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil {
  142. t.Error(err)
  143. }
  144. }
  145. func TestExtensionFieldElementMulIsAssociative(t *testing.T) {
  146. isAssociative := func(x, y, z ExtensionFieldElement) bool {
  147. // Compute t1 = (x*y)*z
  148. t1 := new(ExtensionFieldElement)
  149. t1.Mul(&x, &y)
  150. t1.Mul(t1, &z)
  151. // Compute t2 = (y*z)*x
  152. t2 := new(ExtensionFieldElement)
  153. t2.Mul(&y, &z)
  154. t2.Mul(t2, &x)
  155. return t1.VartimeEq(t2)
  156. }
  157. if err := quick.Check(isAssociative, quickCheckConfig); err != nil {
  158. t.Error(err)
  159. }
  160. }
  161. func TestExtensionFieldElementSquareMatchesMul(t *testing.T) {
  162. sqrMatchesMul := func(x ExtensionFieldElement) bool {
  163. // Compute t1 = (x*x)
  164. t1 := new(ExtensionFieldElement)
  165. t1.Mul(&x, &x)
  166. // Compute t2 = x^2
  167. t2 := new(ExtensionFieldElement)
  168. t2.Square(&x)
  169. return t1.VartimeEq(t2)
  170. }
  171. if err := quick.Check(sqrMatchesMul, quickCheckConfig); err != nil {
  172. t.Error(err)
  173. }
  174. }
  175. func TestExtensionFieldElementInv(t *testing.T) {
  176. inverseIsCorrect := func(x ExtensionFieldElement) bool {
  177. z := new(ExtensionFieldElement)
  178. z.Inv(&x)
  179. // Now z = (1/x), so (z * x) * x == x
  180. z.Mul(z, &x)
  181. z.Mul(z, &x)
  182. return z.VartimeEq(&x)
  183. }
  184. // This is more expensive; run fewer tests
  185. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  186. if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil {
  187. t.Error(err)
  188. }
  189. }
  190. func TestExtensionFieldElementBatch3Inv(t *testing.T) {
  191. batchInverseIsCorrect := func(x1, x2, x3 ExtensionFieldElement) bool {
  192. var x1Inv, x2Inv, x3Inv ExtensionFieldElement
  193. x1Inv.Inv(&x1)
  194. x2Inv.Inv(&x2)
  195. x3Inv.Inv(&x3)
  196. var y1, y2, y3 ExtensionFieldElement
  197. ExtensionFieldBatch3Inv(&x1, &x2, &x3, &y1, &y2, &y3)
  198. return (y1.VartimeEq(&x1Inv) && y2.VartimeEq(&x2Inv) && y3.VartimeEq(&x3Inv))
  199. }
  200. // This is more expensive; run fewer tests
  201. var quickCheckConfig = &quick.Config{MaxCount: (1 << (5 + quickCheckScaleFactor))}
  202. if err := quick.Check(batchInverseIsCorrect, quickCheckConfig); err != nil {
  203. t.Error(err)
  204. }
  205. }
  206. //------------------------------------------------------------------------------
  207. // Prime Field
  208. //------------------------------------------------------------------------------
  209. func TestPrimeFieldElementSetUint64VersusBigInt(t *testing.T) {
  210. setUint64RoundTrips := func(x uint64) bool {
  211. z := new(PrimeFieldElement).SetUint64(x).toBigInt().Uint64()
  212. return x == z
  213. }
  214. if err := quick.Check(setUint64RoundTrips, quickCheckConfig); err != nil {
  215. t.Error(err)
  216. }
  217. }
  218. func TestPrimeFieldElementAddVersusBigInt(t *testing.T) {
  219. addMatchesBigInt := func(x, y PrimeFieldElement) bool {
  220. z := new(PrimeFieldElement)
  221. z.Add(&x, &y)
  222. check := new(big.Int)
  223. check.Add(x.toBigInt(), y.toBigInt())
  224. check.Mod(check, cln16prime)
  225. return check.Cmp(z.toBigInt()) == 0
  226. }
  227. if err := quick.Check(addMatchesBigInt, quickCheckConfig); err != nil {
  228. t.Error(err)
  229. }
  230. }
  231. func TestPrimeFieldElementSubVersusBigInt(t *testing.T) {
  232. subMatchesBigInt := func(x, y PrimeFieldElement) bool {
  233. z := new(PrimeFieldElement)
  234. z.Sub(&x, &y)
  235. check := new(big.Int)
  236. check.Sub(x.toBigInt(), y.toBigInt())
  237. check.Mod(check, cln16prime)
  238. return check.Cmp(z.toBigInt()) == 0
  239. }
  240. if err := quick.Check(subMatchesBigInt, quickCheckConfig); err != nil {
  241. t.Error(err)
  242. }
  243. }
  244. func TestPrimeFieldElementInv(t *testing.T) {
  245. inverseIsCorrect := func(x PrimeFieldElement) bool {
  246. z := new(PrimeFieldElement)
  247. z.Inv(&x)
  248. // Now z = (1/x), so (z * x) * x == x
  249. z.Mul(z, &x).Mul(z, &x)
  250. return z.VartimeEq(&x)
  251. }
  252. // This is more expensive; run fewer tests
  253. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  254. if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil {
  255. t.Error(err)
  256. }
  257. }
  258. func TestPrimeFieldElementSqrt(t *testing.T) {
  259. inverseIsCorrect := func(x PrimeFieldElement) bool {
  260. // Construct y = x^2 so we're sure y is square.
  261. y := new(PrimeFieldElement)
  262. y.Square(&x)
  263. z := new(PrimeFieldElement)
  264. z.Sqrt(y)
  265. // Now z = sqrt(y), so z^2 == y
  266. z.Square(z)
  267. return z.VartimeEq(y)
  268. }
  269. // This is more expensive; run fewer tests
  270. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  271. if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil {
  272. t.Error(err)
  273. }
  274. }
  275. func TestPrimeFieldElementMulVersusBigInt(t *testing.T) {
  276. mulMatchesBigInt := func(x, y PrimeFieldElement) bool {
  277. z := new(PrimeFieldElement)
  278. z.Mul(&x, &y)
  279. check := new(big.Int)
  280. check.Mul(x.toBigInt(), y.toBigInt())
  281. check.Mod(check, cln16prime)
  282. return check.Cmp(z.toBigInt()) == 0
  283. }
  284. if err := quick.Check(mulMatchesBigInt, quickCheckConfig); err != nil {
  285. t.Error(err)
  286. }
  287. }
  288. func TestPrimeFieldElementP34VersusBigInt(t *testing.T) {
  289. var p34, _ = new(big.Int).SetString("2588679435442326313244442059466701330356847411387267792529047419763669735170619711625720724140266678406138302904710050596300977994130638598261040117192787954244176710019728333589599932738193731745058771712747875468166412894207", 10)
  290. p34MatchesBigInt := func(x PrimeFieldElement) bool {
  291. z := new(PrimeFieldElement)
  292. z.P34(&x)
  293. check := x.toBigInt()
  294. check.Exp(check, p34, cln16prime)
  295. return check.Cmp(z.toBigInt()) == 0
  296. }
  297. // This is more expensive; run fewer tests
  298. var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))}
  299. if err := quick.Check(p34MatchesBigInt, quickCheckConfig); err != nil {
  300. t.Error(err)
  301. }
  302. }
  303. func TestFp751ElementConditionalSwap(t *testing.T) {
  304. var one = fp751Element{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
  305. var two = fp751Element{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
  306. var x = one
  307. var y = two
  308. fp751ConditionalSwap(&x, &y, 0)
  309. if !(x == one && y == two) {
  310. t.Error("Found", x, "expected", one)
  311. }
  312. fp751ConditionalSwap(&x, &y, 1)
  313. if !(x == two && y == one) {
  314. t.Error("Found", x, "expected", two)
  315. }
  316. }
  317. func TestFp751ElementConditionalAssign(t *testing.T) {
  318. var one = fp751Element{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
  319. var two = fp751Element{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
  320. var three = fp751Element{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}
  321. fp751ConditionalAssign(&one, &two, &three, 0)
  322. if one != two {
  323. t.Error("Found", one, "expected", two)
  324. }
  325. fp751ConditionalAssign(&one, &two, &three, 1)
  326. if one != three {
  327. t.Error("Found", one, "expected", three)
  328. }
  329. }
  330. // Package-level storage for this field element is intended to deter
  331. // compiler optimizations.
  332. var benchmarkFp751Element fp751Element
  333. var benchmarkFp751X2 fp751X2
  334. var bench_x = fp751Element{17026702066521327207, 5108203422050077993, 10225396685796065916, 11153620995215874678, 6531160855165088358, 15302925148404145445, 1248821577836769963, 9789766903037985294, 7493111552032041328, 10838999828319306046, 18103257655515297935, 27403304611634}
  335. var bench_y = fp751Element{4227467157325093378, 10699492810770426363, 13500940151395637365, 12966403950118934952, 16517692605450415877, 13647111148905630666, 14223628886152717087, 7167843152346903316, 15855377759596736571, 4300673881383687338, 6635288001920617779, 30486099554235}
  336. 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}
  337. func BenchmarkExtensionFieldElementMul(b *testing.B) {
  338. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  339. w := new(ExtensionFieldElement)
  340. for n := 0; n < b.N; n++ {
  341. w.Mul(z, z)
  342. }
  343. }
  344. func BenchmarkExtensionFieldElementInv(b *testing.B) {
  345. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  346. w := new(ExtensionFieldElement)
  347. for n := 0; n < b.N; n++ {
  348. w.Inv(z)
  349. }
  350. }
  351. func BenchmarkExtensionFieldElementSquare(b *testing.B) {
  352. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  353. w := new(ExtensionFieldElement)
  354. for n := 0; n < b.N; n++ {
  355. w.Square(z)
  356. }
  357. }
  358. func BenchmarkExtensionFieldElementAdd(b *testing.B) {
  359. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  360. w := new(ExtensionFieldElement)
  361. for n := 0; n < b.N; n++ {
  362. w.Add(z, z)
  363. }
  364. }
  365. func BenchmarkExtensionFieldElementSub(b *testing.B) {
  366. z := &ExtensionFieldElement{a: bench_x, b: bench_y}
  367. w := new(ExtensionFieldElement)
  368. for n := 0; n < b.N; n++ {
  369. w.Sub(z, z)
  370. }
  371. }
  372. func BenchmarkPrimeFieldElementMul(b *testing.B) {
  373. z := &PrimeFieldElement{a: bench_x}
  374. w := new(PrimeFieldElement)
  375. for n := 0; n < b.N; n++ {
  376. w.Mul(z, z)
  377. }
  378. }
  379. func BenchmarkPrimeFieldElementInv(b *testing.B) {
  380. z := &PrimeFieldElement{a: bench_x}
  381. w := new(PrimeFieldElement)
  382. for n := 0; n < b.N; n++ {
  383. w.Inv(z)
  384. }
  385. }
  386. func BenchmarkPrimeFieldElementSqrt(b *testing.B) {
  387. z := &PrimeFieldElement{a: bench_x}
  388. w := new(PrimeFieldElement)
  389. for n := 0; n < b.N; n++ {
  390. w.Sqrt(z)
  391. }
  392. }
  393. func BenchmarkPrimeFieldElementSquare(b *testing.B) {
  394. z := &PrimeFieldElement{a: bench_x}
  395. w := new(PrimeFieldElement)
  396. for n := 0; n < b.N; n++ {
  397. w.Square(z)
  398. }
  399. }
  400. func BenchmarkPrimeFieldElementAdd(b *testing.B) {
  401. z := &PrimeFieldElement{a: bench_x}
  402. w := new(PrimeFieldElement)
  403. for n := 0; n < b.N; n++ {
  404. w.Add(z, z)
  405. }
  406. }
  407. func BenchmarkPrimeFieldElementSub(b *testing.B) {
  408. z := &PrimeFieldElement{a: bench_x}
  409. w := new(PrimeFieldElement)
  410. for n := 0; n < b.N; n++ {
  411. w.Sub(z, z)
  412. }
  413. }
  414. func BenchmarkFp751Multiply(b *testing.B) {
  415. for n := 0; n < b.N; n++ {
  416. fp751Mul(&benchmarkFp751X2, &bench_x, &bench_y)
  417. }
  418. }
  419. func BenchmarkFp751MontgomeryReduce(b *testing.B) {
  420. z := bench_z
  421. // This benchmark actually computes garbage, because
  422. // fp751MontgomeryReduce mangles its input, but since it's
  423. // constant-time that shouldn't matter for the benchmarks.
  424. for n := 0; n < b.N; n++ {
  425. fp751MontgomeryReduce(&benchmarkFp751Element, &z)
  426. }
  427. }
  428. func BenchmarkFp751AddReduced(b *testing.B) {
  429. for n := 0; n < b.N; n++ {
  430. fp751AddReduced(&benchmarkFp751Element, &bench_x, &bench_y)
  431. }
  432. }
  433. func BenchmarkFp751SubReduced(b *testing.B) {
  434. for n := 0; n < b.N; n++ {
  435. fp751SubReduced(&benchmarkFp751Element, &bench_x, &bench_y)
  436. }
  437. }