You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

295 lines
8.6 KiB

  1. import pytest
  2. try:
  3. import unittest2 as unittest
  4. except ImportError:
  5. import unittest
  6. from hypothesis import given, settings
  7. import hypothesis.strategies as st
  8. try:
  9. from hypothesis import HealthCheck
  10. HC_PRESENT = True
  11. except ImportError: # pragma: no cover
  12. HC_PRESENT = False
  13. from .numbertheory import inverse_mod
  14. from .ellipticcurve import CurveFp, INFINITY, Point, CurveEdTw
  15. HYP_SETTINGS = {}
  16. if HC_PRESENT: # pragma: no branch
  17. HYP_SETTINGS["suppress_health_check"] = [HealthCheck.too_slow]
  18. HYP_SETTINGS["deadline"] = 5000
  19. # NIST Curve P-192:
  20. p = 6277101735386680763835789423207666416083908700390324961279
  21. r = 6277101735386680763835789423176059013767194773182842284081
  22. # s = 0x3045ae6fc8422f64ed579528d38120eae12196d5
  23. # c = 0x3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65
  24. b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1
  25. Gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012
  26. Gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811
  27. c192 = CurveFp(p, -3, b)
  28. p192 = Point(c192, Gx, Gy, r)
  29. c_23 = CurveFp(23, 1, 1)
  30. g_23 = Point(c_23, 13, 7, 7)
  31. HYP_SLOW_SETTINGS = dict(HYP_SETTINGS)
  32. HYP_SLOW_SETTINGS["max_examples"] = 2
  33. @settings(**HYP_SLOW_SETTINGS)
  34. @given(st.integers(min_value=1, max_value=r - 1))
  35. def test_p192_mult_tests(multiple):
  36. inv_m = inverse_mod(multiple, r)
  37. p1 = p192 * multiple
  38. assert p1 * inv_m == p192
  39. def add_n_times(point, n):
  40. ret = INFINITY
  41. i = 0
  42. while i <= n:
  43. yield ret
  44. ret = ret + point
  45. i += 1
  46. # From X9.62 I.1 (p. 96):
  47. @pytest.mark.parametrize(
  48. "p, m, check",
  49. [(g_23, n, exp) for n, exp in enumerate(add_n_times(g_23, 8))],
  50. ids=["g_23 test with mult {0}".format(i) for i in range(9)],
  51. )
  52. def test_add_and_mult_equivalence(p, m, check):
  53. assert p * m == check
  54. class TestCurve(unittest.TestCase):
  55. @classmethod
  56. def setUpClass(cls):
  57. cls.c_23 = CurveFp(23, 1, 1)
  58. def test_equality_curves(self):
  59. self.assertEqual(self.c_23, CurveFp(23, 1, 1))
  60. def test_inequality_curves(self):
  61. c192 = CurveFp(p, -3, b)
  62. self.assertNotEqual(self.c_23, c192)
  63. def test_inequality_curves_by_b_only(self):
  64. a = CurveFp(23, 1, 0)
  65. b = CurveFp(23, 1, 1)
  66. self.assertNotEqual(a, b)
  67. def test_usability_in_a_hashed_collection_curves(self):
  68. {self.c_23: None}
  69. def test_hashability_curves(self):
  70. hash(self.c_23)
  71. def test_conflation_curves(self):
  72. ne1, ne2, ne3 = CurveFp(24, 1, 1), CurveFp(23, 2, 1), CurveFp(23, 1, 2)
  73. eq1, eq2, eq3 = CurveFp(23, 1, 1), CurveFp(23, 1, 1), self.c_23
  74. self.assertEqual(len(set((c_23, eq1, eq2, eq3))), 1)
  75. self.assertEqual(len(set((c_23, ne1, ne2, ne3))), 4)
  76. self.assertDictEqual({c_23: None}, {eq1: None})
  77. self.assertIn(eq2, {eq3: None})
  78. def test___str__(self):
  79. self.assertEqual(str(self.c_23), "CurveFp(p=23, a=1, b=1)")
  80. def test___str___with_cofactor(self):
  81. c = CurveFp(23, 1, 1, 4)
  82. self.assertEqual(str(c), "CurveFp(p=23, a=1, b=1, h=4)")
  83. class TestCurveEdTw(unittest.TestCase):
  84. @classmethod
  85. def setUpClass(cls):
  86. cls.c_23 = CurveEdTw(23, 1, 1)
  87. def test___str__(self):
  88. self.assertEqual(str(self.c_23), "CurveEdTw(p=23, a=1, d=1)")
  89. def test___str___with_cofactor(self):
  90. c = CurveEdTw(23, 1, 1, 4)
  91. self.assertEqual(str(c), "CurveEdTw(p=23, a=1, d=1, h=4)")
  92. def test_usability_in_a_hashed_collection_curves(self):
  93. {self.c_23: None}
  94. def test_hashability_curves(self):
  95. hash(self.c_23)
  96. class TestPoint(unittest.TestCase):
  97. @classmethod
  98. def setUpClass(cls):
  99. cls.c_23 = CurveFp(23, 1, 1)
  100. cls.g_23 = Point(cls.c_23, 13, 7, 7)
  101. p = 6277101735386680763835789423207666416083908700390324961279
  102. r = 6277101735386680763835789423176059013767194773182842284081
  103. # s = 0x3045ae6fc8422f64ed579528d38120eae12196d5
  104. # c = 0x3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65
  105. b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1
  106. Gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012
  107. Gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811
  108. cls.c192 = CurveFp(p, -3, b)
  109. cls.p192 = Point(cls.c192, Gx, Gy, r)
  110. def test_p192(self):
  111. # Checking against some sample computations presented
  112. # in X9.62:
  113. d = 651056770906015076056810763456358567190100156695615665659
  114. Q = d * self.p192
  115. self.assertEqual(
  116. Q.x(), 0x62B12D60690CDCF330BABAB6E69763B471F994DD702D16A5
  117. )
  118. k = 6140507067065001063065065565667405560006161556565665656654
  119. R = k * self.p192
  120. self.assertEqual(
  121. R.x(), 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD
  122. )
  123. self.assertEqual(
  124. R.y(), 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835
  125. )
  126. u1 = 2563697409189434185194736134579731015366492496392189760599
  127. u2 = 6266643813348617967186477710235785849136406323338782220568
  128. temp = u1 * self.p192 + u2 * Q
  129. self.assertEqual(
  130. temp.x(), 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD
  131. )
  132. self.assertEqual(
  133. temp.y(), 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835
  134. )
  135. def test_double_infinity(self):
  136. p1 = INFINITY
  137. p3 = p1.double()
  138. self.assertEqual(p1, p3)
  139. self.assertEqual(p3.x(), p1.x())
  140. self.assertEqual(p3.y(), p3.y())
  141. def test_double(self):
  142. x1, y1, x3, y3 = (3, 10, 7, 12)
  143. p1 = Point(self.c_23, x1, y1)
  144. p3 = p1.double()
  145. self.assertEqual(p3.x(), x3)
  146. self.assertEqual(p3.y(), y3)
  147. def test_double_to_infinity(self):
  148. p1 = Point(self.c_23, 11, 20)
  149. p2 = p1.double()
  150. self.assertEqual((p2.x(), p2.y()), (4, 0))
  151. self.assertNotEqual(p2, INFINITY)
  152. p3 = p2.double()
  153. self.assertEqual(p3, INFINITY)
  154. self.assertIs(p3, INFINITY)
  155. def test_add_self_to_infinity(self):
  156. p1 = Point(self.c_23, 11, 20)
  157. p2 = p1 + p1
  158. self.assertEqual((p2.x(), p2.y()), (4, 0))
  159. self.assertNotEqual(p2, INFINITY)
  160. p3 = p2 + p2
  161. self.assertEqual(p3, INFINITY)
  162. self.assertIs(p3, INFINITY)
  163. def test_mul_to_infinity(self):
  164. p1 = Point(self.c_23, 11, 20)
  165. p2 = p1 * 2
  166. self.assertEqual((p2.x(), p2.y()), (4, 0))
  167. self.assertNotEqual(p2, INFINITY)
  168. p3 = p2 * 2
  169. self.assertEqual(p3, INFINITY)
  170. self.assertIs(p3, INFINITY)
  171. def test_multiply(self):
  172. x1, y1, m, x3, y3 = (3, 10, 2, 7, 12)
  173. p1 = Point(self.c_23, x1, y1)
  174. p3 = p1 * m
  175. self.assertEqual(p3.x(), x3)
  176. self.assertEqual(p3.y(), y3)
  177. # Trivial tests from X9.62 B.3:
  178. def test_add(self):
  179. """We expect that on curve c, (x1,y1) + (x2, y2 ) = (x3, y3)."""
  180. x1, y1, x2, y2, x3, y3 = (3, 10, 9, 7, 17, 20)
  181. p1 = Point(self.c_23, x1, y1)
  182. p2 = Point(self.c_23, x2, y2)
  183. p3 = p1 + p2
  184. self.assertEqual(p3.x(), x3)
  185. self.assertEqual(p3.y(), y3)
  186. def test_add_as_double(self):
  187. """We expect that on curve c, (x1,y1) + (x2, y2 ) = (x3, y3)."""
  188. x1, y1, x2, y2, x3, y3 = (3, 10, 3, 10, 7, 12)
  189. p1 = Point(self.c_23, x1, y1)
  190. p2 = Point(self.c_23, x2, y2)
  191. p3 = p1 + p2
  192. self.assertEqual(p3.x(), x3)
  193. self.assertEqual(p3.y(), y3)
  194. def test_equality_points(self):
  195. self.assertEqual(self.g_23, Point(self.c_23, 13, 7, 7))
  196. def test_inequality_points(self):
  197. c = CurveFp(100, -3, 100)
  198. p = Point(c, 100, 100, 100)
  199. self.assertNotEqual(self.g_23, p)
  200. def test_inequality_points_diff_types(self):
  201. c = CurveFp(100, -3, 100)
  202. self.assertNotEqual(self.g_23, c)
  203. def test_inequality_diff_y(self):
  204. p1 = Point(self.c_23, 6, 4)
  205. p2 = Point(self.c_23, 6, 19)
  206. self.assertNotEqual(p1, p2)
  207. def test_to_bytes_from_bytes(self):
  208. p = Point(self.c_23, 3, 10)
  209. self.assertEqual(p, Point.from_bytes(self.c_23, p.to_bytes()))
  210. def test_add_to_neg_self(self):
  211. p = Point(self.c_23, 3, 10)
  212. self.assertEqual(INFINITY, p + (-p))
  213. def test_add_to_infinity(self):
  214. p = Point(self.c_23, 3, 10)
  215. self.assertIs(p, p + INFINITY)
  216. def test_mul_infinity_by_scalar(self):
  217. self.assertIs(INFINITY, INFINITY * 10)
  218. def test_mul_by_negative(self):
  219. p = Point(self.c_23, 3, 10)
  220. self.assertEqual(p * -5, (-p) * 5)
  221. def test_str_infinity(self):
  222. self.assertEqual(str(INFINITY), "infinity")
  223. def test_str_point(self):
  224. p = Point(self.c_23, 3, 10)
  225. self.assertEqual(str(p), "(3,10)")