test_ECC.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. # ===================================================================
  2. #
  3. # Copyright (c) 2015, Legrandin <helderijs@gmail.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions
  8. # are met:
  9. #
  10. # 1. Redistributions of source code must retain the above copyright
  11. # notice, this list of conditions and the following disclaimer.
  12. # 2. Redistributions in binary form must reproduce the above copyright
  13. # notice, this list of conditions and the following disclaimer in
  14. # the documentation and/or other materials provided with the
  15. # distribution.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. # POSSIBILITY OF SUCH DAMAGE.
  29. # ===================================================================
  30. import unittest
  31. import time
  32. from Cryptodome.SelfTest.st_common import list_test_cases
  33. from Cryptodome.SelfTest.loader import load_tests
  34. from Cryptodome.PublicKey import ECC
  35. from Cryptodome.PublicKey.ECC import EccPoint, _curve, EccKey
  36. class TestEccPoint_NIST(unittest.TestCase):
  37. """Tests defined in section 4.3 of https://www.nsa.gov/ia/_files/nist-routines.pdf"""
  38. pointS = EccPoint(
  39. 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9,
  40. 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256)
  41. pointT = EccPoint(
  42. 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b,
  43. 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316)
  44. def test_set(self):
  45. pointW = EccPoint(0, 0)
  46. pointW.set(self.pointS)
  47. self.assertEqual(pointW, self.pointS)
  48. def test_copy(self):
  49. pointW = self.pointS.copy()
  50. self.assertEqual(pointW, self.pointS)
  51. pointW.set(self.pointT)
  52. self.assertEqual(pointW, self.pointT)
  53. self.assertNotEqual(self.pointS, self.pointT)
  54. def test_addition(self):
  55. pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e
  56. pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264
  57. pointR = self.pointS + self.pointT
  58. self.assertEqual(pointR.x, pointRx)
  59. self.assertEqual(pointR.y, pointRy)
  60. pai = EccPoint.point_at_infinity()
  61. # S + 0
  62. pointR = self.pointS + pai
  63. self.assertEqual(pointR, self.pointS)
  64. # 0 + S
  65. pointR = pai + self.pointS
  66. self.assertEqual(pointR, self.pointS)
  67. # 0 + 0
  68. pointR = pai + pai
  69. self.assertEqual(pointR, pai)
  70. def test_inplace_addition(self):
  71. pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e
  72. pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264
  73. pointR = self.pointS.copy()
  74. pointR += self.pointT
  75. self.assertEqual(pointR.x, pointRx)
  76. self.assertEqual(pointR.y, pointRy)
  77. pai = EccPoint.point_at_infinity()
  78. # S + 0
  79. pointR = self.pointS.copy()
  80. pointR += pai
  81. self.assertEqual(pointR, self.pointS)
  82. # 0 + S
  83. pointR = pai.copy()
  84. pointR += self.pointS
  85. self.assertEqual(pointR, self.pointS)
  86. # 0 + 0
  87. pointR = pai.copy()
  88. pointR += pai
  89. self.assertEqual(pointR, pai)
  90. def test_doubling(self):
  91. pointRx = 0x7669e6901606ee3ba1a8eef1e0024c33df6c22f3b17481b82a860ffcdb6127b0
  92. pointRy = 0xfa878162187a54f6c39f6ee0072f33de389ef3eecd03023de10ca2c1db61d0c7
  93. pointR = self.pointS.copy()
  94. pointR.double()
  95. self.assertEqual(pointR.x, pointRx)
  96. self.assertEqual(pointR.y, pointRy)
  97. # 2*0
  98. pai = self.pointS.point_at_infinity()
  99. pointR = pai.copy()
  100. pointR.double()
  101. self.assertEqual(pointR, pai)
  102. # S + S
  103. pointR = self.pointS.copy()
  104. pointR += pointR
  105. self.assertEqual(pointR.x, pointRx)
  106. self.assertEqual(pointR.y, pointRy)
  107. def test_scalar_multiply(self):
  108. d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd
  109. pointRx = 0x51d08d5f2d4278882946d88d83c97d11e62becc3cfc18bedacc89ba34eeca03f
  110. pointRy = 0x75ee68eb8bf626aa5b673ab51f6e744e06f8fcf8a6c0cf3035beca956a7b41d5
  111. pointR = self.pointS * d
  112. self.assertEqual(pointR.x, pointRx)
  113. self.assertEqual(pointR.y, pointRy)
  114. # 0*S
  115. pai = self.pointS.point_at_infinity()
  116. pointR = self.pointS * 0
  117. self.assertEqual(pointR, pai)
  118. # -1*S
  119. self.assertRaises(ValueError, lambda: self.pointS * -1)
  120. def test_joing_scalar_multiply(self):
  121. d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd
  122. e = 0xd37f628ece72a462f0145cbefe3f0b355ee8332d37acdd83a358016aea029db7
  123. pointRx = 0xd867b4679221009234939221b8046245efcf58413daacbeff857b8588341f6b8
  124. pointRy = 0xf2504055c03cede12d22720dad69c745106b6607ec7e50dd35d54bd80f615275
  125. pointR = self.pointS * d + self.pointT * e
  126. self.assertEqual(pointR.x, pointRx)
  127. self.assertEqual(pointR.y, pointRy)
  128. class TestEccPoint_PAI(unittest.TestCase):
  129. """Test vectors from http://point-at-infinity.org/ecc/nisttv"""
  130. pointG = EccPoint(_curve.Gx, _curve.Gy)
  131. tv_pai = load_tests(("Cryptodome", "SelfTest", "PublicKey", "test_vectors", "ECC"),
  132. "point-at-infinity.org-P256.txt",
  133. "P-256 tests from point-at-infinity.org",
  134. { "k" : lambda k: int(k),
  135. "x" : lambda x: int(x, 16),
  136. "y" : lambda y: int(y, 16)} )
  137. assert(tv_pai)
  138. for tv in tv_pai:
  139. def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
  140. result = self.pointG * scalar
  141. self.assertEqual(result.x, x)
  142. self.assertEqual(result.y, y)
  143. setattr(TestEccPoint_PAI, "test_%d" % tv.count, new_test)
  144. class TestEccKey(unittest.TestCase):
  145. def test_private_key(self):
  146. key = EccKey(curve="P-256", d=1)
  147. self.assertEqual(key.d, 1)
  148. self.failUnless(key.has_private())
  149. self.assertEqual(key.pointQ.x, _curve.Gx)
  150. self.assertEqual(key.pointQ.y, _curve.Gy)
  151. point = EccPoint(_curve.Gx, _curve.Gy)
  152. key = EccKey(curve="P-256", d=1, point=point)
  153. self.assertEqual(key.d, 1)
  154. self.failUnless(key.has_private())
  155. self.assertEqual(key.pointQ, point)
  156. # Other names
  157. key = EccKey(curve="secp256r1", d=1)
  158. key = EccKey(curve="prime256v1", d=1)
  159. def test_public_key(self):
  160. point = EccPoint(_curve.Gx, _curve.Gy)
  161. key = EccKey(curve="P-256", point=point)
  162. self.failIf(key.has_private())
  163. self.assertEqual(key.pointQ, point)
  164. def test_public_key_derived(self):
  165. priv_key = EccKey(curve="P-256", d=3)
  166. pub_key = priv_key.public_key()
  167. self.failIf(pub_key.has_private())
  168. self.assertEqual(priv_key.pointQ, pub_key.pointQ)
  169. def test_invalid_curve(self):
  170. self.assertRaises(ValueError, lambda: EccKey(curve="P-257", d=1))
  171. def test_invalid_d(self):
  172. self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=0))
  173. self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=_curve.order))
  174. def test_equality(self):
  175. private_key = ECC.construct(d=3, curve="P-256")
  176. private_key2 = ECC.construct(d=3, curve="P-256")
  177. private_key3 = ECC.construct(d=4, curve="P-256")
  178. public_key = private_key.public_key()
  179. public_key2 = private_key2.public_key()
  180. public_key3 = private_key3.public_key()
  181. self.assertEqual(private_key, private_key2)
  182. self.assertNotEqual(private_key, private_key3)
  183. self.assertEqual(public_key, public_key2)
  184. self.assertNotEqual(public_key, public_key3)
  185. self.assertNotEqual(public_key, private_key)
  186. class TestEccModule(unittest.TestCase):
  187. def test_generate(self):
  188. key = ECC.generate(curve="P-256")
  189. self.failUnless(key.has_private())
  190. self.assertEqual(key.pointQ, EccPoint(_curve.Gx, _curve.Gy) * key.d)
  191. # Other names
  192. ECC.generate(curve="secp256r1")
  193. ECC.generate(curve="prime256v1")
  194. def test_construct(self):
  195. key = ECC.construct(curve="P-256", d=1)
  196. self.failUnless(key.has_private())
  197. self.assertEqual(key.pointQ, _curve.G)
  198. key = ECC.construct(curve="P-256", point_x=_curve.Gx, point_y=_curve.Gy)
  199. self.failIf(key.has_private())
  200. self.assertEqual(key.pointQ, _curve.G)
  201. # Other names
  202. ECC.construct(curve="secp256r1", d=1)
  203. ECC.construct(curve="prime256v1", d=1)
  204. def test_negative_construct(self):
  205. coord = dict(point_x=10, point_y=4)
  206. coordG = dict(point_x=_curve.Gx, point_y=_curve.Gy)
  207. self.assertRaises(ValueError, ECC.construct, curve="P-256", **coord)
  208. self.assertRaises(ValueError, ECC.construct, curve="P-256", d=2, **coordG)
  209. def get_tests(config={}):
  210. tests = []
  211. tests += list_test_cases(TestEccPoint_NIST)
  212. tests += list_test_cases(TestEccPoint_PAI)
  213. tests += list_test_cases(TestEccKey)
  214. tests += list_test_cases(TestEccModule)
  215. return tests
  216. if __name__ == '__main__':
  217. suite = lambda: unittest.TestSuite(get_tests())
  218. unittest.main(defaultTest='suite')