test_bignum.py 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. #!/usr/bin/python
  2. import ctypes
  3. import itertools
  4. import os
  5. import random
  6. from ctypes import (
  7. c_bool,
  8. c_char,
  9. c_int,
  10. c_size_t,
  11. c_uint,
  12. c_uint8,
  13. c_uint16,
  14. c_uint32,
  15. c_uint64,
  16. )
  17. from math import floor, log, sqrt
  18. import pytest
  19. dir = os.path.abspath(os.path.dirname(__file__))
  20. lib = ctypes.cdll.LoadLibrary(os.path.join(dir, "libtrezor-crypto.so"))
  21. limbs_number = 9
  22. bits_per_limb = 29
  23. @pytest.fixture()
  24. def prime(request):
  25. return 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
  26. @pytest.fixture(params=range(limbs_number * bits_per_limb))
  27. def bignum_bit_index(request):
  28. return request.param
  29. max_decimal_digits = floor(limbs_number * bits_per_limb * log(2, 10))
  30. @pytest.fixture(params=range(max_decimal_digits))
  31. def bignum_decimal_digit_index(request):
  32. return request.param
  33. iterations = int(os.environ.get("ITERS", 1000))
  34. @pytest.fixture(params=range(iterations))
  35. def r(request):
  36. return Random(request.param)
  37. def implication(p, c):
  38. return not p or c
  39. def uint32_p_to_int(pointer):
  40. return pointer.contents.value
  41. def uint32_p():
  42. return ctypes.POINTER(c_int)(c_int())
  43. limb_type = c_uint32
  44. def bignum(limbs_number=limbs_number):
  45. return (limbs_number * limb_type)()
  46. def limbs_to_bignum(limbs):
  47. return (limbs_number * limb_type)(*limbs)
  48. def int_to_bignum(number, limbs_number=limbs_number):
  49. assert number >= 0
  50. assert number.bit_length() <= limbs_number * bits_per_limb
  51. bn = (limbs_number * limb_type)()
  52. for i in range(limbs_number):
  53. bn[i] = number % 2**bits_per_limb
  54. number //= 2**bits_per_limb
  55. return bn
  56. def bignum_to_int(bignum, limbs_number=limbs_number):
  57. number = 0
  58. for i in reversed(range(limbs_number)):
  59. number *= 2**bits_per_limb
  60. number += bignum[i]
  61. return number
  62. def raw_number():
  63. return (32 * c_uint8)()
  64. def raw_number_to_integer(raw_number, endianess):
  65. return int.from_bytes(raw_number, endianess)
  66. def integer_to_raw_number(number, endianess):
  67. return (32 * c_uint8)(*number.to_bytes(32, endianess))
  68. def bignum_is_normalised(bignum):
  69. for limb in bignum:
  70. if limb > 2**bits_per_limb:
  71. return False
  72. return True
  73. def number_is_partly_reduced(number, prime):
  74. return number < 2 * prime
  75. def number_is_fully_reduced(number, prime):
  76. return number < prime
  77. class Random(random.Random):
  78. def rand_int_normalized(self):
  79. return self.randrange(0, 2 ** (limbs_number * bits_per_limb))
  80. def rand_int_256(self):
  81. return self.randrange(0, 2**256)
  82. def rand_int_reduced(self, p):
  83. return self.randrange(0, 2 * p)
  84. def rand_int_bitsize(self, bitsize):
  85. return self.randrange(0, 2**bitsize)
  86. def rand_bit_index(self):
  87. return self.randrange(0, limbs_number * bits_per_limb)
  88. def rand_bignum(self, limbs_number=limbs_number):
  89. return (limb_type * limbs_number)(
  90. *[self.randrange(0, 256**4) for _ in range(limbs_number)]
  91. )
  92. def assert_bn_read_be(in_number):
  93. raw_in_number = integer_to_raw_number(in_number, "big")
  94. bn_out_number = bignum()
  95. lib.bn_read_be(raw_in_number, bn_out_number)
  96. out_number = bignum_to_int(bn_out_number)
  97. assert bignum_is_normalised(bn_out_number)
  98. assert out_number == in_number
  99. def assert_bn_read_le(in_number):
  100. raw_in_number = integer_to_raw_number(in_number, "little")
  101. bn_out_number = bignum()
  102. lib.bn_read_le(raw_in_number, bn_out_number)
  103. out_number = bignum_to_int(bn_out_number)
  104. assert bignum_is_normalised(bn_out_number)
  105. assert out_number == in_number
  106. def assert_bn_write_be(in_number):
  107. bn_in_number = int_to_bignum(in_number)
  108. raw_out_number = raw_number()
  109. lib.bn_write_be(bn_in_number, raw_out_number)
  110. out_number = raw_number_to_integer(raw_out_number, "big")
  111. assert out_number == in_number
  112. def assert_bn_write_le(in_number):
  113. bn_in_number = int_to_bignum(in_number)
  114. raw_out_number = raw_number()
  115. lib.bn_write_le(bn_in_number, raw_out_number)
  116. out_number = raw_number_to_integer(raw_out_number, "little")
  117. assert out_number == in_number
  118. def assert_bn_read_uint32(x):
  119. bn_out_number = bignum()
  120. lib.bn_read_uint32(c_uint32(x), bn_out_number)
  121. out_number = bignum_to_int(bn_out_number)
  122. assert bignum_is_normalised(bn_out_number)
  123. assert out_number == x
  124. def assert_bn_read_uint64(x):
  125. bn_out_number = bignum()
  126. lib.bn_read_uint64(c_uint64(x), bn_out_number)
  127. out_number = bignum_to_int(bn_out_number)
  128. assert bignum_is_normalised(bn_out_number)
  129. assert out_number == x
  130. def assert_bn_bitcount(x):
  131. bn_x = int_to_bignum(x)
  132. return_value = lib.bn_bitcount(bn_x)
  133. assert return_value == x.bit_length()
  134. def assert_bn_digitcount(x):
  135. bn_x = int_to_bignum(x)
  136. return_value = lib.bn_digitcount(bn_x)
  137. assert return_value == len(str(x))
  138. def assert_bn_zero():
  139. bn_x = bignum()
  140. lib.bn_zero(bn_x)
  141. x = bignum_to_int(bn_x)
  142. assert bignum_is_normalised(bn_x)
  143. assert x == 0
  144. def assert_bn_one():
  145. bn_x = bignum()
  146. lib.bn_one(bn_x)
  147. x = bignum_to_int(bn_x)
  148. assert bignum_is_normalised(bn_x)
  149. assert x == 1
  150. def assert_bn_is_zero(x):
  151. bn_x = int_to_bignum(x)
  152. return_value = lib.bn_is_zero(bn_x)
  153. assert return_value == (x == 0)
  154. def assert_bn_is_one(x):
  155. bn_x = int_to_bignum(x)
  156. return_value = lib.bn_is_one(bn_x)
  157. assert return_value == (x == 1)
  158. def assert_bn_is_less(x, y):
  159. bn_x = int_to_bignum(x)
  160. bn_y = int_to_bignum(y)
  161. return_value = lib.bn_is_less(bn_x, bn_y)
  162. assert return_value == (x < y)
  163. def assert_bn_is_equal(x, y):
  164. bn_x = int_to_bignum(x)
  165. bn_y = int_to_bignum(y)
  166. return_value = lib.bn_is_equal(bn_x, bn_y)
  167. assert return_value == (x == y)
  168. def assert_bn_cmov(cond, truecase, falsecase):
  169. bn_res = bignum()
  170. bn_truecase = int_to_bignum(truecase)
  171. bn_falsecase = int_to_bignum(falsecase)
  172. lib.bn_cmov(bn_res, c_uint32(cond), bn_truecase, bn_falsecase)
  173. res = bignum_to_int(bn_res)
  174. assert res == truecase if cond else falsecase
  175. def assert_bn_cnegate(cond, x_old, prime):
  176. bn_x = int_to_bignum(x_old)
  177. bn_prime = int_to_bignum(prime)
  178. lib.bn_cnegate(c_uint32(cond), bn_x, bn_prime)
  179. x_new = bignum_to_int(bn_x)
  180. assert bignum_is_normalised(bn_x)
  181. assert number_is_partly_reduced(x_new, prime)
  182. assert x_new % prime == -x_old % prime if cond else x_old % prime
  183. def assert_bn_lshift(x_old):
  184. bn_x = int_to_bignum(x_old)
  185. lib.bn_lshift(bn_x)
  186. x_new = bignum_to_int(bn_x)
  187. assert bignum_is_normalised(bn_x)
  188. assert x_new == (x_old << 1)
  189. def assert_bn_rshift(x_old):
  190. bn_x = int_to_bignum(x_old)
  191. lib.bn_rshift(bn_x)
  192. x_new = bignum_to_int(bn_x)
  193. assert bignum_is_normalised(bn_x)
  194. assert x_new == (x_old >> 1)
  195. def assert_bn_setbit(x_old, i):
  196. bn_x = int_to_bignum(x_old)
  197. lib.bn_setbit(bn_x, c_uint16(i))
  198. x_new = bignum_to_int(bn_x)
  199. assert bignum_is_normalised(bn_x)
  200. assert x_new == x_old | (1 << i)
  201. def assert_bn_clearbit(x_old, i):
  202. bn_x = int_to_bignum(x_old)
  203. lib.bn_clearbit(bn_x, c_uint16(i))
  204. x_new = bignum_to_int(bn_x)
  205. assert bignum_is_normalised(bn_x)
  206. assert x_new == x_old & ~(1 << i)
  207. def assert_bn_testbit(x_old, i):
  208. bn_x = int_to_bignum(x_old)
  209. return_value = lib.bn_testbit(bn_x, c_uint16(i))
  210. assert return_value == x_old >> i & 1
  211. def assert_bn_xor(x, y):
  212. bn_res = bignum()
  213. bn_x = int_to_bignum(x)
  214. bn_y = int_to_bignum(y)
  215. lib.bn_xor(bn_res, bn_x, bn_y)
  216. res = bignum_to_int(bn_res)
  217. assert res == x ^ y
  218. def assert_bn_mult_half(x_old, prime):
  219. bn_x = int_to_bignum(x_old)
  220. bn_prime = int_to_bignum(prime)
  221. lib.bn_mult_half(bn_x, bn_prime)
  222. x_new = bignum_to_int(bn_x)
  223. assert implication(
  224. number_is_partly_reduced(x_old, prime), number_is_partly_reduced(x_new, prime)
  225. )
  226. assert x_new == (x_old + prime) >> 1 if x_old & 1 else x_old >> 1
  227. def assert_bn_mult_k(x_old, k, prime):
  228. bn_x = int_to_bignum(x_old)
  229. bn_prime = int_to_bignum(prime)
  230. lib.bn_mult_k(bn_x, c_uint8(k), bn_prime)
  231. x_new = bignum_to_int(bn_x)
  232. assert bignum_is_normalised(bn_x)
  233. assert number_is_partly_reduced(x_new, prime)
  234. assert x_new == (x_old * k) % prime
  235. def assert_bn_mod(x_old, prime):
  236. bn_x = int_to_bignum(x_old)
  237. bn_prime = int_to_bignum(prime)
  238. lib.bn_mod(bn_x, bn_prime)
  239. x_new = bignum_to_int(bn_x)
  240. assert bignum_is_normalised(bn_x)
  241. assert number_is_fully_reduced(x_new, prime)
  242. assert x_new == x_old % prime
  243. def assert_bn_multiply_long(k_old, x_old):
  244. bn_k = int_to_bignum(k_old)
  245. bn_x = int_to_bignum(x_old)
  246. bn_res = bignum(2 * limbs_number)
  247. lib.bn_multiply_long(bn_k, bn_x, bn_res)
  248. res = bignum_to_int(bn_res, 2 * limbs_number)
  249. assert res == k_old * x_old
  250. def assert_bn_multiply_reduce_step(res_old, prime, d):
  251. bn_res = int_to_bignum(res_old, 2 * limbs_number)
  252. bn_prime = int_to_bignum(prime)
  253. lib.bn_multiply_reduce_step(bn_res, bn_prime, d)
  254. res_new = bignum_to_int(bn_res, 2 * limbs_number)
  255. assert bignum_is_normalised(bn_res)
  256. assert res_new < 2 * prime * 2 ** (d * bits_per_limb)
  257. def assert_bn_multiply(k, x_old, prime):
  258. bn_k = int_to_bignum(k)
  259. bn_x = int_to_bignum(x_old)
  260. bn_prime = int_to_bignum(prime)
  261. lib.bn_multiply(bn_k, bn_x, bn_prime)
  262. x_new = bignum_to_int(bn_x)
  263. assert bignum_is_normalised(bn_x)
  264. assert number_is_partly_reduced(x_new, prime)
  265. assert x_new == (k * x_old) % prime
  266. def assert_bn_fast_mod(x_old, prime):
  267. bn_x = int_to_bignum(x_old)
  268. bn_prime = int_to_bignum(prime)
  269. lib.bn_fast_mod(bn_x, bn_prime)
  270. x_new = bignum_to_int(bn_x)
  271. assert bignum_is_normalised(bn_x)
  272. assert number_is_partly_reduced(x_new, prime)
  273. assert x_new % prime == x_old % prime
  274. def assert_bn_fast_mod_bn(bn_x, prime):
  275. bn_x
  276. x_old = bignum_to_int(bn_x)
  277. bn_prime = int_to_bignum(prime)
  278. lib.bn_fast_mod(bn_x, bn_prime)
  279. x_new = bignum_to_int(bn_x)
  280. assert bignum_is_normalised(bn_x)
  281. assert number_is_partly_reduced(x_new, prime)
  282. assert x_new % prime == x_old % prime
  283. def assert_bn_power_mod(x, e, prime):
  284. bn_x = int_to_bignum(x)
  285. bn_e = int_to_bignum(e)
  286. bn_prime = int_to_bignum(prime)
  287. bn_res_new = bignum()
  288. lib.bn_power_mod(bn_x, bn_e, bn_prime, bn_res_new)
  289. res_new = bignum_to_int(bn_res_new)
  290. assert bignum_is_normalised(bn_res_new)
  291. assert number_is_partly_reduced(res_new, prime)
  292. assert res_new % prime == pow(x, e, prime)
  293. def assert_bn_sqrt(x_old, prime):
  294. bn_x = int_to_bignum(x_old)
  295. bn_prime = int_to_bignum(prime)
  296. lib.bn_sqrt(bn_x, bn_prime)
  297. x_new = bignum_to_int(bn_x)
  298. assert bignum_is_normalised(bn_x)
  299. assert number_is_fully_reduced(x_new, prime)
  300. assert x_new**2 % prime == x_old % prime
  301. def assert_inverse_mod_power_two(x, m):
  302. return_value = lib.inverse_mod_power_two(c_uint32(x), c_uint32(m))
  303. assert return_value * x % 2**m == 1
  304. def assert_bn_divide_base(x_old, prime):
  305. bn_x = int_to_bignum(x_old)
  306. bn_prime = int_to_bignum(prime)
  307. lib.bn_divide_base(bn_x, bn_prime)
  308. x_new = bignum_to_int(bn_x)
  309. assert implication(
  310. number_is_fully_reduced(x_old, prime), number_is_fully_reduced(x_new, prime)
  311. )
  312. assert implication(
  313. number_is_partly_reduced(x_old, prime), number_is_partly_reduced(x_new, prime)
  314. )
  315. assert x_new * 2**bits_per_limb % prime == x_old % prime
  316. def assert_bn_inverse(x_old, prime):
  317. bn_x = int_to_bignum(x_old)
  318. bn_prime = int_to_bignum(prime)
  319. lib.bn_inverse(bn_x, bn_prime)
  320. x_new = bignum_to_int(bn_x)
  321. assert bignum_is_normalised(bn_x)
  322. assert number_is_fully_reduced(x_new, prime)
  323. assert (x_old == 0 and x_new == 0) or (x_old != 0 and (x_old * x_new) % prime == 1)
  324. def assert_bn_normalize(bn_x):
  325. x_old = bignum_to_int(bn_x)
  326. lib.bn_normalize(bn_x)
  327. x_new = bignum_to_int(bn_x)
  328. assert x_new == x_old % 2 ** (bits_per_limb * limbs_number)
  329. assert bignum_is_normalised(bn_x)
  330. def assert_bn_add(x_old, y):
  331. bn_x = int_to_bignum(x_old)
  332. bn_y = int_to_bignum(y)
  333. lib.bn_add(bn_x, bn_y)
  334. x_new = bignum_to_int(bn_x)
  335. y = bignum_to_int(bn_y)
  336. assert bignum_is_normalised(bn_x)
  337. assert x_new == x_old + y
  338. def assert_bn_addmod(x_old, y, prime):
  339. bn_x = int_to_bignum(x_old)
  340. bn_y = int_to_bignum(y)
  341. bn_prime = int_to_bignum(prime)
  342. lib.bn_addmod(bn_x, bn_y, bn_prime)
  343. x_new = bignum_to_int(bn_x)
  344. assert bignum_is_normalised(bn_x)
  345. assert number_is_partly_reduced(x_new, prime)
  346. assert x_new % prime == (x_old + y) % prime
  347. def assert_bn_addi(x_old, y):
  348. bn_x = int_to_bignum(x_old)
  349. lib.bn_addi(bn_x, c_uint32(y))
  350. x_new = bignum_to_int(bn_x)
  351. assert bignum_is_normalised(bn_x)
  352. assert x_new == x_old + y
  353. def assert_bn_subi(x_old, y, prime):
  354. bn_x = int_to_bignum(x_old)
  355. bn_prime = int_to_bignum(prime)
  356. lib.bn_subi(bn_x, c_uint32(y), bn_prime)
  357. x_new = bignum_to_int(bn_x)
  358. assert bignum_is_normalised(bn_x)
  359. assert implication(
  360. number_is_fully_reduced(x_old, prime), number_is_partly_reduced(x_new, prime)
  361. )
  362. assert x_new % prime == (x_old - y) % prime
  363. def assert_bn_subtractmod(x, y, prime):
  364. bn_x = int_to_bignum(x)
  365. bn_y = int_to_bignum(y)
  366. bn_prime = int_to_bignum(prime)
  367. bn_res = bignum()
  368. lib.bn_subtractmod(bn_x, bn_y, bn_res, bn_prime)
  369. res = bignum_to_int(bn_res)
  370. assert bignum_is_normalised(bn_x)
  371. assert res % prime == (x - y) % prime
  372. def assert_bn_subtract(x, y):
  373. bn_x = int_to_bignum(x)
  374. bn_y = int_to_bignum(y)
  375. bn_res = bignum()
  376. lib.bn_subtract(bn_x, bn_y, bn_res)
  377. res = bignum_to_int(bn_res)
  378. assert bignum_is_normalised(bn_x)
  379. assert res == x - y
  380. def assert_bn_long_division(x, d):
  381. bn_x = int_to_bignum(x)
  382. bn_q = bignum()
  383. uint32_p_r = uint32_p()
  384. lib.bn_long_division(bn_x, d, bn_q, uint32_p_r)
  385. r = uint32_p_to_int(uint32_p_r)
  386. q = bignum_to_int(bn_q)
  387. assert bignum_is_normalised(bn_q)
  388. assert q == x // d
  389. assert r == x % d
  390. def assert_bn_divmod58(x_old):
  391. bn_x = int_to_bignum(x_old)
  392. uint32_p_r = uint32_p()
  393. lib.bn_divmod58(bn_x, uint32_p_r)
  394. x_new = bignum_to_int(bn_x)
  395. r = uint32_p_to_int(uint32_p_r)
  396. assert bignum_is_normalised(bn_x)
  397. assert x_new == x_old // 58
  398. assert r == x_old % 58
  399. def assert_bn_divmod1000(x_old):
  400. bn_x = int_to_bignum(x_old)
  401. uint32_p_r = uint32_p()
  402. lib.bn_divmod1000(bn_x, uint32_p_r)
  403. x_new = bignum_to_int(bn_x)
  404. r = uint32_p_to_int(uint32_p_r)
  405. assert bignum_is_normalised(bn_x)
  406. assert x_new == x_old // 1000
  407. assert r == x_old % 1000
  408. def assert_bn_divmod10(x_old):
  409. bn_x = int_to_bignum(x_old)
  410. uint32_p_r = uint32_p()
  411. lib.bn_divmod10(bn_x, uint32_p_r)
  412. x_new = bignum_to_int(bn_x)
  413. r = uint32_p_to_int(uint32_p_r)
  414. assert bignum_is_normalised(bn_x)
  415. assert x_new == x_old // 10
  416. assert r == x_old % 10
  417. def assert_bn_format(x, prefix, suffix, decimals, exponent, trailing, thousands):
  418. def format(amount, prefix, suffix, decimals, exponent, trailing, thousands):
  419. if exponent >= 0:
  420. amount *= 10**exponent
  421. else:
  422. amount //= 10 ** (-exponent)
  423. d = pow(10, decimals)
  424. integer_part = amount // d
  425. integer_str = f"{integer_part:,}".replace(",", thousands or "")
  426. if decimals:
  427. decimal_part = amount % d
  428. decimal_str = f".{decimal_part:0{decimals}d}"
  429. if not trailing:
  430. decimal_str = decimal_str.rstrip("0").rstrip(".")
  431. else:
  432. decimal_str = ""
  433. return prefix + integer_str + decimal_str + suffix
  434. def string_to_char_p(string):
  435. return ctypes.create_string_buffer(string.encode("ascii"))
  436. def char_p_to_string(pointer):
  437. return str(pointer.value, "ascii")
  438. bn_x = int_to_bignum(x)
  439. output_length = 100
  440. output = string_to_char_p("?" * output_length)
  441. return_value = lib.bn_format(
  442. bn_x,
  443. string_to_char_p(prefix),
  444. string_to_char_p(suffix),
  445. c_uint(decimals),
  446. c_int(exponent),
  447. c_bool(trailing),
  448. c_char(0),
  449. output,
  450. c_size_t(output_length),
  451. )
  452. correct_output = format(x, prefix, suffix, decimals, exponent, trailing, "")
  453. correct_return_value = len(correct_output)
  454. if len(correct_output) >= output_length:
  455. correct_output = ""
  456. correct_return_value = 0
  457. assert char_p_to_string(output) == correct_output
  458. assert return_value == correct_return_value
  459. def test_bn_read_be(r):
  460. assert_bn_read_be(r.rand_int_256())
  461. def test_bn_read_le(r):
  462. assert_bn_read_le(r.rand_int_256())
  463. def test_bn_write_be(r):
  464. assert_bn_write_be(r.rand_int_256())
  465. def test_bn_write_le(r):
  466. assert_bn_write_le(r.rand_int_256())
  467. def test_bn_read_uint32(r):
  468. assert_bn_read_uint32(r.rand_int_bitsize(32))
  469. def test_bn_read_uint64(r):
  470. assert_bn_read_uint64(r.rand_int_bitsize(64))
  471. def test_bn_bitcount_1(r):
  472. assert_bn_bitcount(r.rand_int_normalized())
  473. def test_bn_bitcount_2(bignum_bit_index):
  474. assert_bn_bitcount(2**bignum_bit_index - 1)
  475. assert_bn_bitcount(2**bignum_bit_index)
  476. def test_bn_digitcount_1(r):
  477. assert_bn_digitcount(r.rand_int_normalized())
  478. def test_bn_digitcount_2(bignum_decimal_digit_index):
  479. assert_bn_digitcount(10**bignum_decimal_digit_index - 1)
  480. assert_bn_digitcount(10**bignum_decimal_digit_index)
  481. def test_bn_zero():
  482. assert_bn_zero()
  483. def test_bn_one():
  484. assert_bn_one()
  485. def test_bn_is_zero_1():
  486. assert_bn_is_zero(0)
  487. assert_bn_is_zero(1)
  488. def test_bn_is_zero_2(bignum_bit_index):
  489. assert_bn_is_zero(2**bignum_bit_index)
  490. def test_bn_is_one_1():
  491. assert_bn_is_one(0)
  492. assert_bn_is_one(1)
  493. def test_bn_is_one_2(bignum_bit_index):
  494. assert_bn_is_one(2**bignum_bit_index)
  495. def test_bn_is_less_1(r):
  496. a = r.rand_int_normalized()
  497. b = r.rand_int_normalized()
  498. assert_bn_is_less(a, a)
  499. assert_bn_is_less(a, b)
  500. assert_bn_is_less(b, a)
  501. def test_bn_is_less_2(r):
  502. a = r.rand_int_normalized()
  503. i = r.rand_bit_index()
  504. b = a ^ 2**i
  505. assert_bn_is_less(a, b)
  506. def test_bn_is_less_3():
  507. assert_bn_is_less(0, 0)
  508. assert_bn_is_less(1, 0)
  509. assert_bn_is_less(0, 1)
  510. assert_bn_is_less(1, 1)
  511. def test_bn_is_equal_1(r):
  512. a = r.rand_int_normalized()
  513. b = r.rand_int_normalized()
  514. assert_bn_is_equal(a, a)
  515. assert_bn_is_equal(a, b)
  516. def test_bn_is_equal_2():
  517. assert_bn_is_equal(0, 0)
  518. assert_bn_is_equal(1, 0)
  519. assert_bn_is_equal(0, 1)
  520. assert_bn_is_equal(1, 1)
  521. def test_bn_cmov(r):
  522. a = r.rand_int_normalized()
  523. b = r.rand_int_normalized()
  524. assert_bn_cmov(0, a, b)
  525. assert_bn_cmov(1, a, b)
  526. def test_bn_cnegate(r, prime):
  527. a = r.rand_int_reduced(prime)
  528. assert_bn_cnegate(0, a, prime)
  529. assert_bn_cnegate(1, a, prime)
  530. def test_bn_lshift(r):
  531. assert_bn_lshift(r.rand_int_normalized() // 2)
  532. def test_bn_rshift(r):
  533. assert_bn_rshift(r.rand_int_normalized())
  534. def test_bn_testbit(r):
  535. assert_bn_testbit(r.rand_int_normalized(), r.rand_bit_index())
  536. def test_bn_setbit(r):
  537. assert_bn_setbit(r.rand_int_normalized(), r.rand_bit_index())
  538. def test_bn_clearbit(r):
  539. assert_bn_clearbit(r.rand_int_normalized(), r.rand_bit_index())
  540. def test_bn_xor(r):
  541. assert_bn_xor(r.rand_int_normalized(), r.rand_int_normalized())
  542. def test_bn_mult_half_1(r, prime):
  543. assert_bn_mult_half(r.rand_int_reduced(prime), prime)
  544. def test_bn_mult_half_2(r, prime):
  545. assert_bn_mult_half(r.rand_int_normalized(), prime)
  546. def test_bn_mult_k(r, prime):
  547. assert_bn_mult_k(r.rand_int_normalized(), r.randrange(9), prime)
  548. def test_bn_mod_1(r, prime):
  549. assert_bn_mod(r.rand_int_reduced(prime), prime)
  550. def test_bn_mod_2(r, prime):
  551. for x in [
  552. 0,
  553. 1,
  554. 2,
  555. prime - 2,
  556. prime - 1,
  557. prime,
  558. prime + 1,
  559. prime + 2,
  560. 2 * prime - 2,
  561. 2 * prime - 1,
  562. ]:
  563. assert_bn_mod(x, prime)
  564. def test_bn_multiply_long(r, prime):
  565. x = r.randrange(floor(sqrt(2**519)))
  566. k = r.randrange(floor(sqrt(2**519)))
  567. assert_bn_multiply_long(k, x)
  568. def test_bn_multiply_reduce_step(r, prime):
  569. k = r.randrange(0, limbs_number)
  570. res = r.randrange(2 ** (256 + 29 * k + 31))
  571. assert_bn_multiply_reduce_step(res, prime, k)
  572. def test_bn_multiply(r, prime):
  573. x = r.randrange(floor(sqrt(2**519)))
  574. k = r.randrange(floor(sqrt(2**519)))
  575. assert_bn_multiply(k, x, prime)
  576. def test_bn_fast_mod_1(r, prime):
  577. assert_bn_fast_mod(r.rand_int_normalized(), prime)
  578. def test_bn_fast_mod_2(r, prime):
  579. bn_x = r.rand_bignum()
  580. assert_bn_fast_mod_bn(bn_x, prime)
  581. def test_bn_power_mod(r, prime):
  582. x = r.rand_int_bitsize(259)
  583. e = r.rand_int_normalized()
  584. assert_bn_power_mod(x, e, prime)
  585. def test_bn_sqrt_1(prime):
  586. assert_bn_sqrt(0, prime)
  587. assert_bn_sqrt(1, prime)
  588. def test_bn_sqrt_2(r, prime):
  589. def is_quadratic_residuum(x, p):
  590. return pow(x, (p - 1) // 2, p) == 1
  591. while True:
  592. x = r.rand_int_bitsize(259)
  593. if is_quadratic_residuum(x, prime):
  594. break
  595. assert_bn_sqrt(x, prime)
  596. def test_inverse_mod_power_two(r):
  597. m = r.randrange(1, 33)
  598. i = r.randrange(1, 2**29, 2)
  599. assert_inverse_mod_power_two(i, m)
  600. def test_bn_divide_base(r, prime):
  601. assert_bn_divide_base(r.rand_int_256(), prime)
  602. def test_bn_inverse_1(prime):
  603. assert_bn_inverse(0, prime)
  604. assert_bn_inverse(1, prime)
  605. def test_bn_inverse_2(r, prime):
  606. from math import gcd
  607. while True:
  608. n = r.randrange(0, prime)
  609. if gcd(n, prime) == 1:
  610. break
  611. assert_bn_inverse(n, prime)
  612. def test_bn_normalize(r):
  613. assert_bn_normalize(r.rand_bignum())
  614. def test_bn_add_1(r):
  615. assert_bn_add(r.rand_int_256(), r.rand_int_256())
  616. def test_bn_add_2(r):
  617. while True:
  618. a = r.rand_int_normalized()
  619. b = r.rand_int_normalized()
  620. if a + b < 2 ** (limbs_number * bits_per_limb):
  621. break
  622. assert_bn_add(a, b)
  623. def test_bn_add_3():
  624. a = Random().rand_int_normalized()
  625. b = 2 ** (limbs_number * bits_per_limb) - 1 - a
  626. assert_bn_add(a, b)
  627. def test_bn_addmod(r, prime):
  628. assert_bn_addmod(r.rand_int_normalized(), r.rand_int_normalized(), prime)
  629. def test_bn_addi_1(r):
  630. while True:
  631. a = r.rand_int_normalized()
  632. b = r.randrange(2**32 - 2**bits_per_limb + 1)
  633. if a + b < 2 ** (limbs_number * bits_per_limb):
  634. break
  635. assert_bn_addi(a, b)
  636. def test_bn_addi_2():
  637. b = 2**32 - 2**bits_per_limb
  638. a = 2 ** (limbs_number * bits_per_limb) - 1 - b
  639. assert_bn_addi(a, b)
  640. def test_bn_subi_1(r, prime):
  641. while True:
  642. a = r.rand_int_normalized()
  643. b = r.randrange(prime % 2**bits_per_limb)
  644. if a + prime - b < 2 ** (limbs_number * bits_per_limb):
  645. break
  646. assert_bn_subi(a, b, prime)
  647. def test_bn_subi_2(prime):
  648. b = (prime % 2**bits_per_limb) - 1
  649. a = 2 ** (limbs_number * bits_per_limb) - 1 - prime + b
  650. assert_bn_subi(a, b, prime)
  651. def test_bn_subtractmod_1(r, prime):
  652. assert_bn_subtractmod(r.rand_int_256(), r.rand_int_256(), prime)
  653. def test_bn_subtractmod_2(r, prime):
  654. while True:
  655. a = r.rand_int_normalized()
  656. b = r.rand_int_reduced(prime)
  657. if a + 2 * prime - b < 2 ** (limbs_number * bits_per_limb):
  658. break
  659. assert_bn_subtractmod(a, b, prime)
  660. def test_bn_subtractmod_3(prime):
  661. b = 2 * prime - 1
  662. a = 2 ** (limbs_number * bits_per_limb) - 1 - (2 * prime - b)
  663. assert_bn_subtractmod(a, b, prime)
  664. def test_bn_subtract_1(r):
  665. a = r.rand_int_256()
  666. b = r.rand_int_256()
  667. if a < b:
  668. a, b = b, a
  669. assert_bn_subtract(a, b)
  670. def test_bn_subtract_2(r):
  671. a = r.rand_int_normalized()
  672. b = r.rand_int_normalized()
  673. if a < b:
  674. a, b = b, a
  675. assert_bn_subtract(a, b)
  676. def test_bn_long_division(r):
  677. x = r.rand_int_normalized()
  678. d = r.randrange(1, 61304 + 1)
  679. assert_bn_long_division(x, d)
  680. def test_bn_divmod58(r):
  681. x = r.rand_int_normalized()
  682. assert_bn_divmod58(x)
  683. def test_bn_divmod1000(r):
  684. x = r.rand_int_normalized()
  685. assert_bn_divmod1000(x)
  686. def test_bn_divmod10(r):
  687. x = r.rand_int_normalized()
  688. assert_bn_divmod10(x)
  689. @pytest.mark.parametrize(
  690. "decimals,exponent,trailing,prefix,suffix,thousands,value",
  691. itertools.product(
  692. range(0, 5),
  693. range(-5, 5),
  694. [True, False],
  695. ["", "prefix"],
  696. ["", "suffix"],
  697. ["", ",", " "],
  698. [123, 120, 123_456, 12_345, 100001, 10001000],
  699. ),
  700. )
  701. def test_bn_format(decimals, exponent, trailing, prefix, suffix, thousands, value):
  702. assert_bn_format(value, prefix, suffix, decimals, exponent, trailing, thousands)