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.
 
 
 
 

1139 line
38 KiB

  1. try:
  2. import unittest2 as unittest
  3. except ImportError:
  4. import unittest
  5. try:
  6. buffer
  7. except NameError:
  8. buffer = memoryview
  9. import os
  10. import array
  11. import pytest
  12. import hashlib
  13. from .keys import (
  14. VerifyingKey,
  15. SigningKey,
  16. MalformedPointError,
  17. BadSignatureError,
  18. )
  19. from .der import (
  20. unpem,
  21. UnexpectedDER,
  22. encode_sequence,
  23. encode_oid,
  24. encode_bitstring,
  25. encode_integer,
  26. encode_octet_string,
  27. )
  28. from .util import (
  29. sigencode_string,
  30. sigencode_der,
  31. sigencode_strings,
  32. sigdecode_string,
  33. sigdecode_der,
  34. sigdecode_strings,
  35. )
  36. from .curves import NIST256p, Curve, BRAINPOOLP160r1, Ed25519, Ed448
  37. from .ellipticcurve import Point, PointJacobi, CurveFp, INFINITY
  38. from .ecdsa import generator_brainpoolp160r1
  39. class TestVerifyingKeyFromString(unittest.TestCase):
  40. """
  41. Verify that ecdsa.keys.VerifyingKey.from_string() can be used with
  42. bytes-like objects
  43. """
  44. @classmethod
  45. def setUpClass(cls):
  46. cls.key_bytes = (
  47. b"\x04L\xa2\x95\xdb\xc7Z\xd7\x1f\x93\nz\xcf\x97\xcf"
  48. b"\xd7\xc2\xd9o\xfe8}X!\xae\xd4\xfah\xfa^\rpI\xba\xd1"
  49. b"Y\xfb\x92xa\xebo+\x9cG\xfav\xca"
  50. )
  51. cls.vk = VerifyingKey.from_string(cls.key_bytes)
  52. def test_bytes(self):
  53. self.assertIsNotNone(self.vk)
  54. self.assertIsInstance(self.vk, VerifyingKey)
  55. self.assertEqual(
  56. self.vk.pubkey.point.x(),
  57. 105419898848891948935835657980914000059957975659675736097,
  58. )
  59. self.assertEqual(
  60. self.vk.pubkey.point.y(),
  61. 4286866841217412202667522375431381222214611213481632495306,
  62. )
  63. def test_bytes_memoryview(self):
  64. vk = VerifyingKey.from_string(buffer(self.key_bytes))
  65. self.assertEqual(self.vk.to_string(), vk.to_string())
  66. def test_bytearray(self):
  67. vk = VerifyingKey.from_string(bytearray(self.key_bytes))
  68. self.assertEqual(self.vk.to_string(), vk.to_string())
  69. def test_bytesarray_memoryview(self):
  70. vk = VerifyingKey.from_string(buffer(bytearray(self.key_bytes)))
  71. self.assertEqual(self.vk.to_string(), vk.to_string())
  72. def test_array_array_of_bytes(self):
  73. arr = array.array("B", self.key_bytes)
  74. vk = VerifyingKey.from_string(arr)
  75. self.assertEqual(self.vk.to_string(), vk.to_string())
  76. def test_array_array_of_bytes_memoryview(self):
  77. arr = array.array("B", self.key_bytes)
  78. vk = VerifyingKey.from_string(buffer(arr))
  79. self.assertEqual(self.vk.to_string(), vk.to_string())
  80. def test_array_array_of_ints(self):
  81. arr = array.array("I", self.key_bytes)
  82. vk = VerifyingKey.from_string(arr)
  83. self.assertEqual(self.vk.to_string(), vk.to_string())
  84. def test_array_array_of_ints_memoryview(self):
  85. arr = array.array("I", self.key_bytes)
  86. vk = VerifyingKey.from_string(buffer(arr))
  87. self.assertEqual(self.vk.to_string(), vk.to_string())
  88. def test_bytes_uncompressed(self):
  89. vk = VerifyingKey.from_string(b"\x04" + self.key_bytes)
  90. self.assertEqual(self.vk.to_string(), vk.to_string())
  91. def test_bytearray_uncompressed(self):
  92. vk = VerifyingKey.from_string(bytearray(b"\x04" + self.key_bytes))
  93. self.assertEqual(self.vk.to_string(), vk.to_string())
  94. def test_bytes_compressed(self):
  95. vk = VerifyingKey.from_string(b"\x02" + self.key_bytes[:24])
  96. self.assertEqual(self.vk.to_string(), vk.to_string())
  97. def test_bytearray_compressed(self):
  98. vk = VerifyingKey.from_string(bytearray(b"\x02" + self.key_bytes[:24]))
  99. self.assertEqual(self.vk.to_string(), vk.to_string())
  100. def test_ed25519_VerifyingKey_from_string_imported(self):
  101. with self.assertRaises(MalformedPointError):
  102. VerifyingKey.from_string(b"AAA", Ed25519)
  103. class TestVerifyingKeyFromDer(unittest.TestCase):
  104. """
  105. Verify that ecdsa.keys.VerifyingKey.from_der() can be used with
  106. bytes-like objects.
  107. """
  108. @classmethod
  109. def setUpClass(cls):
  110. prv_key_str = (
  111. "-----BEGIN EC PRIVATE KEY-----\n"
  112. "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
  113. "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
  114. "bA==\n"
  115. "-----END EC PRIVATE KEY-----\n"
  116. )
  117. key_str = (
  118. "-----BEGIN PUBLIC KEY-----\n"
  119. "MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEuIF30ITvF/XkVjlAgCg2D59ZtKTX\n"
  120. "Jk5i2gZR3OR6NaTFtFz1FZNCOotVe5wgmfNs\n"
  121. "-----END PUBLIC KEY-----\n"
  122. )
  123. cls.key_pem = key_str
  124. cls.key_bytes = unpem(key_str)
  125. assert isinstance(cls.key_bytes, bytes)
  126. cls.vk = VerifyingKey.from_pem(key_str)
  127. cls.sk = SigningKey.from_pem(prv_key_str)
  128. key_str = (
  129. "-----BEGIN PUBLIC KEY-----\n"
  130. "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4H3iRbG4TSrsSRb/gusPQB/4YcN8\n"
  131. "Poqzgjau4kfxBPyZimeRfuY/9g/wMmPuhGl4BUve51DsnKJFRr8psk0ieA==\n"
  132. "-----END PUBLIC KEY-----\n"
  133. )
  134. cls.vk2 = VerifyingKey.from_pem(key_str)
  135. cls.sk2 = SigningKey.generate(vk.curve)
  136. def test_load_key_with_explicit_parameters(self):
  137. pub_key_str = (
  138. "-----BEGIN PUBLIC KEY-----\n"
  139. "MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA\n"
  140. "AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////\n"
  141. "///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd\n"
  142. "NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5\n"
  143. "RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
  144. "//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABIr1UkgYs5jmbFc7it1/YI2X\n"
  145. "T//IlaEjMNZft1owjqpBYH2ErJHk4U5Pp4WvWq1xmHwIZlsH7Ig4KmefCfR6SmU=\n"
  146. "-----END PUBLIC KEY-----"
  147. )
  148. pk = VerifyingKey.from_pem(pub_key_str)
  149. pk_exp = VerifyingKey.from_string(
  150. b"\x04\x8a\xf5\x52\x48\x18\xb3\x98\xe6\x6c\x57\x3b\x8a\xdd\x7f"
  151. b"\x60\x8d\x97\x4f\xff\xc8\x95\xa1\x23\x30\xd6\x5f\xb7\x5a\x30"
  152. b"\x8e\xaa\x41\x60\x7d\x84\xac\x91\xe4\xe1\x4e\x4f\xa7\x85\xaf"
  153. b"\x5a\xad\x71\x98\x7c\x08\x66\x5b\x07\xec\x88\x38\x2a\x67\x9f"
  154. b"\x09\xf4\x7a\x4a\x65",
  155. curve=NIST256p,
  156. )
  157. self.assertEqual(pk, pk_exp)
  158. def test_load_key_with_explicit_with_explicit_disabled(self):
  159. pub_key_str = (
  160. "-----BEGIN PUBLIC KEY-----\n"
  161. "MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA\n"
  162. "AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////\n"
  163. "///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd\n"
  164. "NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5\n"
  165. "RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
  166. "//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABIr1UkgYs5jmbFc7it1/YI2X\n"
  167. "T//IlaEjMNZft1owjqpBYH2ErJHk4U5Pp4WvWq1xmHwIZlsH7Ig4KmefCfR6SmU=\n"
  168. "-----END PUBLIC KEY-----"
  169. )
  170. with self.assertRaises(UnexpectedDER):
  171. VerifyingKey.from_pem(
  172. pub_key_str, valid_curve_encodings=["named_curve"]
  173. )
  174. def test_load_key_with_disabled_format(self):
  175. with self.assertRaises(MalformedPointError) as e:
  176. VerifyingKey.from_der(self.key_bytes, valid_encodings=["raw"])
  177. self.assertIn("enabled (raw) encodings", str(e.exception))
  178. def test_custom_hashfunc(self):
  179. vk = VerifyingKey.from_der(self.key_bytes, hashlib.sha256)
  180. self.assertIs(vk.default_hashfunc, hashlib.sha256)
  181. def test_from_pem_with_custom_hashfunc(self):
  182. vk = VerifyingKey.from_pem(self.key_pem, hashlib.sha256)
  183. self.assertIs(vk.default_hashfunc, hashlib.sha256)
  184. def test_bytes(self):
  185. vk = VerifyingKey.from_der(self.key_bytes)
  186. self.assertEqual(self.vk.to_string(), vk.to_string())
  187. def test_bytes_memoryview(self):
  188. vk = VerifyingKey.from_der(buffer(self.key_bytes))
  189. self.assertEqual(self.vk.to_string(), vk.to_string())
  190. def test_bytearray(self):
  191. vk = VerifyingKey.from_der(bytearray(self.key_bytes))
  192. self.assertEqual(self.vk.to_string(), vk.to_string())
  193. def test_bytesarray_memoryview(self):
  194. vk = VerifyingKey.from_der(buffer(bytearray(self.key_bytes)))
  195. self.assertEqual(self.vk.to_string(), vk.to_string())
  196. def test_array_array_of_bytes(self):
  197. arr = array.array("B", self.key_bytes)
  198. vk = VerifyingKey.from_der(arr)
  199. self.assertEqual(self.vk.to_string(), vk.to_string())
  200. def test_array_array_of_bytes_memoryview(self):
  201. arr = array.array("B", self.key_bytes)
  202. vk = VerifyingKey.from_der(buffer(arr))
  203. self.assertEqual(self.vk.to_string(), vk.to_string())
  204. def test_equality_on_verifying_keys(self):
  205. self.assertTrue(self.vk == self.sk.get_verifying_key())
  206. def test_inequality_on_verifying_keys(self):
  207. self.assertFalse(self.vk == self.vk2)
  208. def test_inequality_on_verifying_keys_not_implemented(self):
  209. self.assertFalse(self.vk == None)
  210. def test_VerifyingKey_inequality_on_same_curve(self):
  211. self.assertNotEqual(self.vk, self.sk2.verifying_key)
  212. def test_SigningKey_inequality_on_same_curve(self):
  213. self.assertNotEqual(self.sk, self.sk2)
  214. def test_inequality_on_wrong_types(self):
  215. self.assertFalse(self.vk == self.sk)
  216. def test_from_public_point_old(self):
  217. pj = self.vk.pubkey.point
  218. point = Point(pj.curve(), pj.x(), pj.y())
  219. vk = VerifyingKey.from_public_point(point, self.vk.curve)
  220. self.assertTrue(vk == self.vk)
  221. def test_ed25519_VerifyingKey_repr__(self):
  222. sk = SigningKey.from_string(Ed25519.generator.to_bytes(), Ed25519)
  223. string = repr(sk.verifying_key)
  224. self.assertEqual(
  225. "VerifyingKey.from_string("
  226. "bytearray(b'K\\x0c\\xfbZH\\x8e\\x8c\\x8c\\x07\\xee\\xda\\xfb"
  227. "\\xe1\\x97\\xcd\\x90\\x18\\x02\\x15h]\\xfe\\xbe\\xcbB\\xba\\xe6r"
  228. "\\x10\\xae\\xf1P'), Ed25519, None)",
  229. string,
  230. )
  231. def test_edwards_from_public_point(self):
  232. point = Ed25519.generator
  233. with self.assertRaises(ValueError) as e:
  234. VerifyingKey.from_public_point(point, Ed25519)
  235. self.assertIn("incompatible with Edwards", str(e.exception))
  236. def test_edwards_precompute_no_side_effect(self):
  237. sk = SigningKey.from_string(Ed25519.generator.to_bytes(), Ed25519)
  238. vk = sk.verifying_key
  239. vk2 = VerifyingKey.from_string(vk.to_string(), Ed25519)
  240. vk.precompute()
  241. self.assertEqual(vk, vk2)
  242. def test_parse_malfomed_eddsa_der_pubkey(self):
  243. der_str = encode_sequence(
  244. encode_sequence(encode_oid(*Ed25519.oid)),
  245. encode_bitstring(bytes(Ed25519.generator.to_bytes()), 0),
  246. encode_bitstring(b"\x00", 0),
  247. )
  248. with self.assertRaises(UnexpectedDER) as e:
  249. VerifyingKey.from_der(der_str)
  250. self.assertIn("trailing junk after public key", str(e.exception))
  251. def test_edwards_from_public_key_recovery(self):
  252. with self.assertRaises(ValueError) as e:
  253. VerifyingKey.from_public_key_recovery(b"", b"", Ed25519)
  254. self.assertIn("unsupported for Edwards", str(e.exception))
  255. def test_edwards_from_public_key_recovery_with_digest(self):
  256. with self.assertRaises(ValueError) as e:
  257. VerifyingKey.from_public_key_recovery_with_digest(
  258. b"", b"", Ed25519
  259. )
  260. self.assertIn("unsupported for Edwards", str(e.exception))
  261. def test_load_ed25519_from_pem(self):
  262. vk_pem = (
  263. "-----BEGIN PUBLIC KEY-----\n"
  264. "MCowBQYDK2VwAyEAIwBQ0NZkIiiO41WJfm5BV42u3kQm7lYnvIXmCy8qy2U=\n"
  265. "-----END PUBLIC KEY-----\n"
  266. )
  267. vk = VerifyingKey.from_pem(vk_pem)
  268. self.assertIsInstance(vk.curve, Curve)
  269. self.assertIs(vk.curve, Ed25519)
  270. vk_str = (
  271. b"\x23\x00\x50\xd0\xd6\x64\x22\x28\x8e\xe3\x55\x89\x7e\x6e\x41\x57"
  272. b"\x8d\xae\xde\x44\x26\xee\x56\x27\xbc\x85\xe6\x0b\x2f\x2a\xcb\x65"
  273. )
  274. vk_2 = VerifyingKey.from_string(vk_str, Ed25519)
  275. self.assertEqual(vk, vk_2)
  276. def test_export_ed255_to_pem(self):
  277. vk_str = (
  278. b"\x23\x00\x50\xd0\xd6\x64\x22\x28\x8e\xe3\x55\x89\x7e\x6e\x41\x57"
  279. b"\x8d\xae\xde\x44\x26\xee\x56\x27\xbc\x85\xe6\x0b\x2f\x2a\xcb\x65"
  280. )
  281. vk = VerifyingKey.from_string(vk_str, Ed25519)
  282. vk_pem = (
  283. b"-----BEGIN PUBLIC KEY-----\n"
  284. b"MCowBQYDK2VwAyEAIwBQ0NZkIiiO41WJfm5BV42u3kQm7lYnvIXmCy8qy2U=\n"
  285. b"-----END PUBLIC KEY-----\n"
  286. )
  287. self.assertEqual(vk_pem, vk.to_pem())
  288. def test_export_ed255_to_ssh(self):
  289. vk_str = (
  290. b"\x23\x00\x50\xd0\xd6\x64\x22\x28\x8e\xe3\x55\x89\x7e\x6e\x41\x57"
  291. b"\x8d\xae\xde\x44\x26\xee\x56\x27\xbc\x85\xe6\x0b\x2f\x2a\xcb\x65"
  292. )
  293. vk = VerifyingKey.from_string(vk_str, Ed25519)
  294. vk_ssh = b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICMAUNDWZCIojuNViX5uQVeNrt5EJu5WJ7yF5gsvKstl\n"
  295. self.assertEqual(vk_ssh, vk.to_ssh())
  296. def test_ed25519_export_import(self):
  297. sk = SigningKey.generate(Ed25519)
  298. vk = sk.verifying_key
  299. vk2 = VerifyingKey.from_pem(vk.to_pem())
  300. self.assertEqual(vk, vk2)
  301. def test_ed25519_sig_verify(self):
  302. vk_pem = (
  303. "-----BEGIN PUBLIC KEY-----\n"
  304. "MCowBQYDK2VwAyEAIwBQ0NZkIiiO41WJfm5BV42u3kQm7lYnvIXmCy8qy2U=\n"
  305. "-----END PUBLIC KEY-----\n"
  306. )
  307. vk = VerifyingKey.from_pem(vk_pem)
  308. data = b"data\n"
  309. # signature created by OpenSSL 3.0.0 beta1
  310. sig = (
  311. b"\x64\x47\xab\x6a\x33\xcd\x79\x45\xad\x98\x11\x6c\xb9\xf2\x20\xeb"
  312. b"\x90\xd6\x50\xe3\xc7\x8f\x9f\x60\x10\xec\x75\xe0\x2f\x27\xd3\x96"
  313. b"\xda\xe8\x58\x7f\xe0\xfe\x46\x5c\x81\xef\x50\xec\x29\x9f\xae\xd5"
  314. b"\xad\x46\x3c\x91\x68\x83\x4d\xea\x8d\xa8\x19\x04\x04\x79\x03\x0b"
  315. )
  316. self.assertTrue(vk.verify(sig, data))
  317. def test_ed25519_sig_verify_malformed(self):
  318. vk_pem = (
  319. "-----BEGIN PUBLIC KEY-----\n"
  320. "MCowBQYDK2VwAyEAIwBQ0NZkIiiO41WJfm5BV42u3kQm7lYnvIXmCy8qy2U=\n"
  321. "-----END PUBLIC KEY-----\n"
  322. )
  323. vk = VerifyingKey.from_pem(vk_pem)
  324. data = b"data\n"
  325. # modified signature from test_ed25519_sig_verify
  326. sig = (
  327. b"\xAA\x47\xab\x6a\x33\xcd\x79\x45\xad\x98\x11\x6c\xb9\xf2\x20\xeb"
  328. b"\x90\xd6\x50\xe3\xc7\x8f\x9f\x60\x10\xec\x75\xe0\x2f\x27\xd3\x96"
  329. b"\xda\xe8\x58\x7f\xe0\xfe\x46\x5c\x81\xef\x50\xec\x29\x9f\xae\xd5"
  330. b"\xad\x46\x3c\x91\x68\x83\x4d\xea\x8d\xa8\x19\x04\x04\x79\x03\x0b"
  331. )
  332. with self.assertRaises(BadSignatureError):
  333. vk.verify(sig, data)
  334. def test_ed448_from_pem(self):
  335. pem_str = (
  336. "-----BEGIN PUBLIC KEY-----\n"
  337. "MEMwBQYDK2VxAzoAeQtetSu7CMEzE+XWB10Bg47LCA0giNikOxHzdp+tZ/eK/En0\n"
  338. "dTdYD2ll94g58MhSnBiBQB9A1MMA\n"
  339. "-----END PUBLIC KEY-----\n"
  340. )
  341. vk = VerifyingKey.from_pem(pem_str)
  342. self.assertIsInstance(vk.curve, Curve)
  343. self.assertIs(vk.curve, Ed448)
  344. vk_str = (
  345. b"\x79\x0b\x5e\xb5\x2b\xbb\x08\xc1\x33\x13\xe5\xd6\x07\x5d\x01\x83"
  346. b"\x8e\xcb\x08\x0d\x20\x88\xd8\xa4\x3b\x11\xf3\x76\x9f\xad\x67\xf7"
  347. b"\x8a\xfc\x49\xf4\x75\x37\x58\x0f\x69\x65\xf7\x88\x39\xf0\xc8\x52"
  348. b"\x9c\x18\x81\x40\x1f\x40\xd4\xc3\x00"
  349. )
  350. vk2 = VerifyingKey.from_string(vk_str, Ed448)
  351. self.assertEqual(vk, vk2)
  352. def test_ed448_to_pem(self):
  353. vk_str = (
  354. b"\x79\x0b\x5e\xb5\x2b\xbb\x08\xc1\x33\x13\xe5\xd6\x07\x5d\x01\x83"
  355. b"\x8e\xcb\x08\x0d\x20\x88\xd8\xa4\x3b\x11\xf3\x76\x9f\xad\x67\xf7"
  356. b"\x8a\xfc\x49\xf4\x75\x37\x58\x0f\x69\x65\xf7\x88\x39\xf0\xc8\x52"
  357. b"\x9c\x18\x81\x40\x1f\x40\xd4\xc3\x00"
  358. )
  359. vk = VerifyingKey.from_string(vk_str, Ed448)
  360. vk_pem = (
  361. b"-----BEGIN PUBLIC KEY-----\n"
  362. b"MEMwBQYDK2VxAzoAeQtetSu7CMEzE+XWB10Bg47LCA0giNikOxHzdp+tZ/eK/En0dTdYD2ll94g5\n"
  363. b"8MhSnBiBQB9A1MMA\n"
  364. b"-----END PUBLIC KEY-----\n"
  365. )
  366. self.assertEqual(vk_pem, vk.to_pem())
  367. def test_ed448_export_import(self):
  368. sk = SigningKey.generate(Ed448)
  369. vk = sk.verifying_key
  370. vk2 = VerifyingKey.from_pem(vk.to_pem())
  371. self.assertEqual(vk, vk2)
  372. def test_ed448_sig_verify(self):
  373. pem_str = (
  374. "-----BEGIN PUBLIC KEY-----\n"
  375. "MEMwBQYDK2VxAzoAeQtetSu7CMEzE+XWB10Bg47LCA0giNikOxHzdp+tZ/eK/En0\n"
  376. "dTdYD2ll94g58MhSnBiBQB9A1MMA\n"
  377. "-----END PUBLIC KEY-----\n"
  378. )
  379. vk = VerifyingKey.from_pem(pem_str)
  380. data = b"data\n"
  381. # signature created by OpenSSL 3.0.0 beta1
  382. sig = (
  383. b"\x68\xed\x2c\x70\x35\x22\xca\x1c\x35\x03\xf3\xaa\x51\x33\x3d\x00"
  384. b"\xc0\xae\xb0\x54\xc5\xdc\x7f\x6f\x30\x57\xb4\x1d\xcb\xe9\xec\xfa"
  385. b"\xc8\x45\x3e\x51\xc1\xcb\x60\x02\x6a\xd0\x43\x11\x0b\x5f\x9b\xfa"
  386. b"\x32\x88\xb2\x38\x6b\xed\xac\x09\x00\x78\xb1\x7b\x5d\x7e\xf8\x16"
  387. b"\x31\xdd\x1b\x3f\x98\xa0\xce\x19\xe7\xd8\x1c\x9f\x30\xac\x2f\xd4"
  388. b"\x1e\x55\xbf\x21\x98\xf6\x4c\x8c\xbe\x81\xa5\x2d\x80\x4c\x62\x53"
  389. b"\x91\xd5\xee\x03\x30\xc6\x17\x66\x4b\x9e\x0c\x8d\x40\xd0\xad\xae"
  390. b"\x0a\x00"
  391. )
  392. self.assertTrue(vk.verify(sig, data))
  393. class TestSigningKey(unittest.TestCase):
  394. """
  395. Verify that ecdsa.keys.SigningKey.from_der() can be used with
  396. bytes-like objects.
  397. """
  398. @classmethod
  399. def setUpClass(cls):
  400. prv_key_str = (
  401. "-----BEGIN EC PRIVATE KEY-----\n"
  402. "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
  403. "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
  404. "bA==\n"
  405. "-----END EC PRIVATE KEY-----\n"
  406. )
  407. cls.sk1 = SigningKey.from_pem(prv_key_str)
  408. prv_key_str = (
  409. "-----BEGIN PRIVATE KEY-----\n"
  410. "MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBheyEIL1u+SUqlC6YkE\n"
  411. "PKKfVh+lJXcOscWhNAMyAAS4gXfQhO8X9eRWOUCAKDYPn1m0pNcmTmLaBlHc5Ho1\n"
  412. "pMW0XPUVk0I6i1V7nCCZ82w=\n"
  413. "-----END PRIVATE KEY-----\n"
  414. )
  415. cls.sk1_pkcs8 = SigningKey.from_pem(prv_key_str)
  416. prv_key_str = (
  417. "-----BEGIN EC PRIVATE KEY-----\n"
  418. "MHcCAQEEIKlL2EAm5NPPZuXwxRf4nXMk0A80y6UUbiQ17be/qFhRoAoGCCqGSM49\n"
  419. "AwEHoUQDQgAE4H3iRbG4TSrsSRb/gusPQB/4YcN8Poqzgjau4kfxBPyZimeRfuY/\n"
  420. "9g/wMmPuhGl4BUve51DsnKJFRr8psk0ieA==\n"
  421. "-----END EC PRIVATE KEY-----\n"
  422. )
  423. cls.sk2 = SigningKey.from_pem(prv_key_str)
  424. def test_to_der_pkcs8(self):
  425. self.assertEqual(
  426. self.sk1.to_der(format="pkcs8"),
  427. b"0o\x02\x01\x010\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H"
  428. b"\xce=\x03\x01\x01\x04U0S\x02\x01\x01\x04\x18^\xc8B\x0b\xd6\xef"
  429. b"\x92R\xa9B\xe9\x89\x04<\xa2\x9fV\x1f\xa5%w\x0e\xb1\xc5\xa14\x03"
  430. b"2\x00\x04\xb8\x81w\xd0\x84\xef\x17\xf5\xe4V9@\x80(6\x0f\x9fY"
  431. b"\xb4\xa4\xd7&Nb\xda\x06Q\xdc\xe4z5\xa4\xc5\xb4\\\xf5\x15\x93B:"
  432. b"\x8bU{\x9c \x99\xf3l",
  433. )
  434. def test_decoding_explicit_curve_parameters(self):
  435. prv_key_str = (
  436. "-----BEGIN PRIVATE KEY-----\n"
  437. "MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB\n"
  438. "AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA\n"
  439. "///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV\n"
  440. "AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg\n"
  441. "9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A\n"
  442. "AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgIXtREfUmR16r\n"
  443. "ZbmvDGD2lAEFPZa2DLPyz0czSja58yChRANCAASK9VJIGLOY5mxXO4rdf2CNl0//\n"
  444. "yJWhIzDWX7daMI6qQWB9hKyR5OFOT6eFr1qtcZh8CGZbB+yIOCpnnwn0ekpl\n"
  445. "-----END PRIVATE KEY-----\n"
  446. )
  447. sk = SigningKey.from_pem(prv_key_str)
  448. sk2 = SigningKey.from_string(
  449. b"\x21\x7b\x51\x11\xf5\x26\x47\x5e\xab\x65\xb9\xaf\x0c\x60\xf6"
  450. b"\x94\x01\x05\x3d\x96\xb6\x0c\xb3\xf2\xcf\x47\x33\x4a\x36\xb9"
  451. b"\xf3\x20",
  452. curve=NIST256p,
  453. )
  454. self.assertEqual(sk, sk2)
  455. def test_decoding_explicit_curve_parameters_with_explicit_disabled(self):
  456. prv_key_str = (
  457. "-----BEGIN PRIVATE KEY-----\n"
  458. "MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB\n"
  459. "AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA\n"
  460. "///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV\n"
  461. "AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg\n"
  462. "9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A\n"
  463. "AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgIXtREfUmR16r\n"
  464. "ZbmvDGD2lAEFPZa2DLPyz0czSja58yChRANCAASK9VJIGLOY5mxXO4rdf2CNl0//\n"
  465. "yJWhIzDWX7daMI6qQWB9hKyR5OFOT6eFr1qtcZh8CGZbB+yIOCpnnwn0ekpl\n"
  466. "-----END PRIVATE KEY-----\n"
  467. )
  468. with self.assertRaises(UnexpectedDER):
  469. SigningKey.from_pem(
  470. prv_key_str, valid_curve_encodings=["named_curve"]
  471. )
  472. def test_equality_on_signing_keys(self):
  473. sk = SigningKey.from_secret_exponent(
  474. self.sk1.privkey.secret_multiplier, self.sk1.curve
  475. )
  476. self.assertEqual(self.sk1, sk)
  477. self.assertEqual(self.sk1_pkcs8, sk)
  478. def test_verify_with_empty_message(self):
  479. sig = self.sk1.sign(b"")
  480. self.assertTrue(sig)
  481. vk = self.sk1.verifying_key
  482. self.assertTrue(vk.verify(sig, b""))
  483. def test_verify_with_precompute(self):
  484. sig = self.sk1.sign(b"message")
  485. vk = self.sk1.verifying_key
  486. vk.precompute()
  487. self.assertTrue(vk.verify(sig, b"message"))
  488. def test_compare_verifying_key_with_precompute(self):
  489. vk1 = self.sk1.verifying_key
  490. vk1.precompute()
  491. vk2 = self.sk1_pkcs8.verifying_key
  492. self.assertEqual(vk1, vk2)
  493. def test_verify_with_lazy_precompute(self):
  494. sig = self.sk2.sign(b"other message")
  495. vk = self.sk2.verifying_key
  496. vk.precompute(lazy=True)
  497. self.assertTrue(vk.verify(sig, b"other message"))
  498. def test_inequality_on_signing_keys(self):
  499. self.assertNotEqual(self.sk1, self.sk2)
  500. def test_inequality_on_signing_keys_not_implemented(self):
  501. self.assertNotEqual(self.sk1, None)
  502. def test_ed25519_from_pem(self):
  503. pem_str = (
  504. "-----BEGIN PRIVATE KEY-----\n"
  505. "MC4CAQAwBQYDK2VwBCIEIDS6x9FO1PG8T4xIPg8Zd0z8uL6sVGZFEZrX17gHC/XU\n"
  506. "-----END PRIVATE KEY-----\n"
  507. )
  508. sk = SigningKey.from_pem(pem_str)
  509. sk_str = SigningKey.from_string(
  510. b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
  511. b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
  512. Ed25519,
  513. )
  514. self.assertEqual(sk, sk_str)
  515. def test_ed25519_from_der_bad_alg_id_params(self):
  516. der_str = encode_sequence(
  517. encode_integer(1),
  518. encode_sequence(encode_oid(*Ed25519.oid), encode_integer(1)),
  519. encode_octet_string(encode_octet_string(b"A" * 32)),
  520. )
  521. with self.assertRaises(UnexpectedDER) as e:
  522. SigningKey.from_der(der_str)
  523. self.assertIn("Non NULL parameters", str(e.exception))
  524. def test_ed25519_from_der_junk_after_priv_key(self):
  525. der_str = encode_sequence(
  526. encode_integer(1),
  527. encode_sequence(
  528. encode_oid(*Ed25519.oid),
  529. ),
  530. encode_octet_string(encode_octet_string(b"A" * 32) + b"B"),
  531. )
  532. with self.assertRaises(UnexpectedDER) as e:
  533. SigningKey.from_der(der_str)
  534. self.assertIn(
  535. "trailing junk after the encoded private key", str(e.exception)
  536. )
  537. def test_ed25519_sign(self):
  538. sk_str = SigningKey.from_string(
  539. b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
  540. b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
  541. Ed25519,
  542. )
  543. msg = b"message"
  544. sig = sk_str.sign(msg, sigencode=sigencode_der)
  545. self.assertEqual(
  546. sig,
  547. b"\xe1,v\xc9>%\xda\xd2~>\xc3&\na\xf4@|\x9e`X\x11\x13@<\x987\xd4"
  548. b"\r\xb1\xf5\xb3\x15\x7f%i{\xdf}\xdd\xb1\xf3\x02\x7f\x80\x02\xc2"
  549. b'|\xe5\xd6\x06\xc4\n\xa3\xb0\xf6}\xc0\xed)"+E\xaf\x00',
  550. )
  551. def test_ed25519_sign_digest_deterministic(self):
  552. sk_str = SigningKey.from_string(
  553. b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
  554. b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
  555. Ed25519,
  556. )
  557. with self.assertRaises(ValueError) as e:
  558. sk_str.sign_digest_deterministic(b"a" * 20)
  559. self.assertIn("Method unsupported for Edwards", str(e.exception))
  560. def test_ed25519_sign_digest(self):
  561. sk_str = SigningKey.from_string(
  562. b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
  563. b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
  564. Ed25519,
  565. )
  566. with self.assertRaises(ValueError) as e:
  567. sk_str.sign_digest(b"a" * 20)
  568. self.assertIn("Method unsupported for Edwards", str(e.exception))
  569. def test_ed25519_sign_number(self):
  570. sk_str = SigningKey.from_string(
  571. b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
  572. b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
  573. Ed25519,
  574. )
  575. with self.assertRaises(ValueError) as e:
  576. sk_str.sign_number(20)
  577. self.assertIn("Method unsupported for Edwards", str(e.exception))
  578. def test_ed25519_to_der_ssleay(self):
  579. pem_str = (
  580. "-----BEGIN PRIVATE KEY-----\n"
  581. "MC4CAQAwBQYDK2VwBCIEIDS6x9FO1PG8T4xIPg8Zd0z8uL6sVGZFEZrX17gHC/XU\n"
  582. "-----END PRIVATE KEY-----\n"
  583. )
  584. sk = SigningKey.from_pem(pem_str)
  585. with self.assertRaises(ValueError) as e:
  586. sk.to_der(format="ssleay")
  587. self.assertIn("Only PKCS#8 format", str(e.exception))
  588. def test_ed25519_to_pem(self):
  589. sk = SigningKey.from_string(
  590. b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
  591. b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
  592. Ed25519,
  593. )
  594. pem_str = (
  595. b"-----BEGIN PRIVATE KEY-----\n"
  596. b"MC4CAQAwBQYDK2VwBCIEIDS6x9FO1PG8T4xIPg8Zd0z8uL6sVGZFEZrX17gHC/XU\n"
  597. b"-----END PRIVATE KEY-----\n"
  598. )
  599. self.assertEqual(sk.to_pem(format="pkcs8"), pem_str)
  600. def test_ed25519_to_ssh(self):
  601. sk = SigningKey.from_string(
  602. b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
  603. b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
  604. Ed25519,
  605. )
  606. ssh_str = (
  607. b"-----BEGIN OPENSSH PRIVATE KEY-----\n"
  608. b"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZWQyNTUx\n"
  609. b"OQAAACAjAFDQ1mQiKI7jVYl+bkFXja7eRCbuVie8heYLLyrLZQAAAIgAAAAAAAAAAAAAAAtzc2gt\n"
  610. b"ZWQyNTUxOQAAACAjAFDQ1mQiKI7jVYl+bkFXja7eRCbuVie8heYLLyrLZQAAAEA0usfRTtTxvE+M\n"
  611. b"SD4PGXdM/Li+rFRmRRGa19e4Bwv11CMAUNDWZCIojuNViX5uQVeNrt5EJu5WJ7yF5gsvKstlAAAA\n"
  612. b"AAECAwQF\n"
  613. b"-----END OPENSSH PRIVATE KEY-----\n"
  614. )
  615. self.assertEqual(sk.to_ssh(), ssh_str)
  616. def test_ed25519_to_and_from_pem(self):
  617. sk = SigningKey.generate(Ed25519)
  618. decoded = SigningKey.from_pem(sk.to_pem(format="pkcs8"))
  619. self.assertEqual(sk, decoded)
  620. def test_ed25519_custom_entropy(self):
  621. sk = SigningKey.generate(Ed25519, entropy=os.urandom)
  622. self.assertIsNotNone(sk)
  623. def test_ed25519_from_secret_exponent(self):
  624. with self.assertRaises(ValueError) as e:
  625. SigningKey.from_secret_exponent(1234567890, curve=Ed25519)
  626. self.assertIn("don't support setting the secret", str(e.exception))
  627. def test_ed448_from_pem(self):
  628. pem_str = (
  629. "-----BEGIN PRIVATE KEY-----\n"
  630. "MEcCAQAwBQYDK2VxBDsEOTyFuXqFLXgJlV8uDqcOw9nG4IqzLiZ/i5NfBDoHPzmP\n"
  631. "OP0JMYaLGlTzwovmvCDJ2zLaezu9NLz9aQ==\n"
  632. "-----END PRIVATE KEY-----\n"
  633. )
  634. sk = SigningKey.from_pem(pem_str)
  635. sk_str = SigningKey.from_string(
  636. b"\x3C\x85\xB9\x7A\x85\x2D\x78\x09\x95\x5F\x2E\x0E\xA7\x0E\xC3\xD9"
  637. b"\xC6\xE0\x8A\xB3\x2E\x26\x7F\x8B\x93\x5F\x04\x3A\x07\x3F\x39\x8F"
  638. b"\x38\xFD\x09\x31\x86\x8B\x1A\x54\xF3\xC2\x8B\xE6\xBC\x20\xC9\xDB"
  639. b"\x32\xDA\x7B\x3B\xBD\x34\xBC\xFD\x69",
  640. Ed448,
  641. )
  642. self.assertEqual(sk, sk_str)
  643. def test_ed448_to_pem(self):
  644. sk = SigningKey.from_string(
  645. b"\x3C\x85\xB9\x7A\x85\x2D\x78\x09\x95\x5F\x2E\x0E\xA7\x0E\xC3\xD9"
  646. b"\xC6\xE0\x8A\xB3\x2E\x26\x7F\x8B\x93\x5F\x04\x3A\x07\x3F\x39\x8F"
  647. b"\x38\xFD\x09\x31\x86\x8B\x1A\x54\xF3\xC2\x8B\xE6\xBC\x20\xC9\xDB"
  648. b"\x32\xDA\x7B\x3B\xBD\x34\xBC\xFD\x69",
  649. Ed448,
  650. )
  651. pem_str = (
  652. b"-----BEGIN PRIVATE KEY-----\n"
  653. b"MEcCAQAwBQYDK2VxBDsEOTyFuXqFLXgJlV8uDqcOw9nG4IqzLiZ/i5NfBDoHPzmPOP0JMYaLGlTz\n"
  654. b"wovmvCDJ2zLaezu9NLz9aQ==\n"
  655. b"-----END PRIVATE KEY-----\n"
  656. )
  657. self.assertEqual(sk.to_pem(format="pkcs8"), pem_str)
  658. def test_ed448_encode_decode(self):
  659. sk = SigningKey.generate(Ed448)
  660. decoded = SigningKey.from_pem(sk.to_pem(format="pkcs8"))
  661. self.assertEqual(decoded, sk)
  662. class TestTrivialCurve(unittest.TestCase):
  663. @classmethod
  664. def setUpClass(cls):
  665. # To test what happens with r or s in signing happens to be zero we
  666. # need to find a scalar that creates one of the points on a curve that
  667. # has x coordinate equal to zero.
  668. # Even for secp112r2 curve that's non trivial so use this toy
  669. # curve, for which we can iterate over all points quickly
  670. curve = CurveFp(163, 84, 58)
  671. gen = PointJacobi(curve, 2, 87, 1, 167, generator=True)
  672. cls.toy_curve = Curve("toy_p8", curve, gen, (1, 2, 0))
  673. cls.sk = SigningKey.from_secret_exponent(
  674. 140,
  675. cls.toy_curve,
  676. hashfunc=hashlib.sha1,
  677. )
  678. def test_generator_sanity(self):
  679. gen = self.toy_curve.generator
  680. self.assertEqual(gen * gen.order(), INFINITY)
  681. def test_public_key_sanity(self):
  682. self.assertEqual(self.sk.verifying_key.to_string(), b"\x98\x1e")
  683. def test_deterministic_sign(self):
  684. sig = self.sk.sign_deterministic(b"message")
  685. self.assertEqual(sig, b"-.")
  686. self.assertTrue(self.sk.verifying_key.verify(sig, b"message"))
  687. def test_deterministic_sign_random_message(self):
  688. msg = os.urandom(32)
  689. sig = self.sk.sign_deterministic(msg)
  690. self.assertEqual(len(sig), 2)
  691. self.assertTrue(self.sk.verifying_key.verify(sig, msg))
  692. def test_deterministic_sign_that_rises_R_zero_error(self):
  693. # the raised RSZeroError is caught and handled internally by
  694. # sign_deterministic methods
  695. msg = b"\x00\x4f"
  696. sig = self.sk.sign_deterministic(msg)
  697. self.assertEqual(sig, b"\x36\x9e")
  698. self.assertTrue(self.sk.verifying_key.verify(sig, msg))
  699. def test_deterministic_sign_that_rises_S_zero_error(self):
  700. msg = b"\x01\x6d"
  701. sig = self.sk.sign_deterministic(msg)
  702. self.assertEqual(sig, b"\x49\x6c")
  703. self.assertTrue(self.sk.verifying_key.verify(sig, msg))
  704. # test VerifyingKey.verify()
  705. prv_key_str = (
  706. "-----BEGIN EC PRIVATE KEY-----\n"
  707. "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
  708. "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
  709. "bA==\n"
  710. "-----END EC PRIVATE KEY-----\n"
  711. )
  712. key_bytes = unpem(prv_key_str)
  713. assert isinstance(key_bytes, bytes)
  714. sk = SigningKey.from_der(key_bytes)
  715. vk = sk.verifying_key
  716. data = (
  717. b"some string for signing"
  718. b"contents don't really matter"
  719. b"but do include also some crazy values: "
  720. b"\x00\x01\t\r\n\x00\x00\x00\xff\xf0"
  721. )
  722. assert len(data) % 4 == 0
  723. sha1 = hashlib.sha1()
  724. sha1.update(data)
  725. data_hash = sha1.digest()
  726. assert isinstance(data_hash, bytes)
  727. sig_raw = sk.sign(data, sigencode=sigencode_string)
  728. assert isinstance(sig_raw, bytes)
  729. sig_der = sk.sign(data, sigencode=sigencode_der)
  730. assert isinstance(sig_der, bytes)
  731. sig_strings = sk.sign(data, sigencode=sigencode_strings)
  732. assert isinstance(sig_strings[0], bytes)
  733. verifiers = []
  734. for modifier, fun in [
  735. ("bytes", lambda x: x),
  736. ("bytes memoryview", buffer),
  737. ("bytearray", bytearray),
  738. ("bytearray memoryview", lambda x: buffer(bytearray(x))),
  739. ("array.array of bytes", lambda x: array.array("B", x)),
  740. ("array.array of bytes memoryview", lambda x: buffer(array.array("B", x))),
  741. ("array.array of ints", lambda x: array.array("I", x)),
  742. ("array.array of ints memoryview", lambda x: buffer(array.array("I", x))),
  743. ]:
  744. if "ints" in modifier:
  745. conv = lambda x: x
  746. else:
  747. conv = fun
  748. for sig_format, signature, decoder, mod_apply in [
  749. ("raw", sig_raw, sigdecode_string, lambda x: conv(x)),
  750. ("der", sig_der, sigdecode_der, lambda x: conv(x)),
  751. (
  752. "strings",
  753. sig_strings,
  754. sigdecode_strings,
  755. lambda x: tuple(conv(i) for i in x),
  756. ),
  757. ]:
  758. for method_name, vrf_mthd, vrf_data in [
  759. ("verify", vk.verify, data),
  760. ("verify_digest", vk.verify_digest, data_hash),
  761. ]:
  762. verifiers.append(
  763. pytest.param(
  764. signature,
  765. decoder,
  766. mod_apply,
  767. fun,
  768. vrf_mthd,
  769. vrf_data,
  770. id="{2}-{0}-{1}".format(modifier, sig_format, method_name),
  771. )
  772. )
  773. @pytest.mark.parametrize(
  774. "signature,decoder,mod_apply,fun,vrf_mthd,vrf_data", verifiers
  775. )
  776. def test_VerifyingKey_verify(
  777. signature, decoder, mod_apply, fun, vrf_mthd, vrf_data
  778. ):
  779. sig = mod_apply(signature)
  780. assert vrf_mthd(sig, fun(vrf_data), sigdecode=decoder)
  781. # test SigningKey.from_string()
  782. prv_key_bytes = (
  783. b"^\xc8B\x0b\xd6\xef\x92R\xa9B\xe9\x89\x04<\xa2"
  784. b"\x9fV\x1f\xa5%w\x0e\xb1\xc5"
  785. )
  786. assert len(prv_key_bytes) == 24
  787. converters = []
  788. for modifier, convert in [
  789. ("bytes", lambda x: x),
  790. ("bytes memoryview", buffer),
  791. ("bytearray", bytearray),
  792. ("bytearray memoryview", lambda x: buffer(bytearray(x))),
  793. ("array.array of bytes", lambda x: array.array("B", x)),
  794. ("array.array of bytes memoryview", lambda x: buffer(array.array("B", x))),
  795. ("array.array of ints", lambda x: array.array("I", x)),
  796. ("array.array of ints memoryview", lambda x: buffer(array.array("I", x))),
  797. ]:
  798. converters.append(pytest.param(convert, id=modifier))
  799. @pytest.mark.parametrize("convert", converters)
  800. def test_SigningKey_from_string(convert):
  801. key = convert(prv_key_bytes)
  802. sk = SigningKey.from_string(key)
  803. assert sk.to_string() == prv_key_bytes
  804. # test SigningKey.from_der()
  805. prv_key_str = (
  806. "-----BEGIN EC PRIVATE KEY-----\n"
  807. "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
  808. "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
  809. "bA==\n"
  810. "-----END EC PRIVATE KEY-----\n"
  811. )
  812. key_bytes = unpem(prv_key_str)
  813. assert isinstance(key_bytes, bytes)
  814. # last two converters are for array.array of ints, those require input
  815. # that's multiple of 4, which no curve we support produces
  816. @pytest.mark.parametrize("convert", converters[:-2])
  817. def test_SigningKey_from_der(convert):
  818. key = convert(key_bytes)
  819. sk = SigningKey.from_der(key)
  820. assert sk.to_string() == prv_key_bytes
  821. # test SigningKey.sign_deterministic()
  822. extra_entropy = b"\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11"
  823. @pytest.mark.parametrize("convert", converters)
  824. def test_SigningKey_sign_deterministic(convert):
  825. sig = sk.sign_deterministic(
  826. convert(data), extra_entropy=convert(extra_entropy)
  827. )
  828. vk.verify(sig, data)
  829. # test SigningKey.sign_digest_deterministic()
  830. @pytest.mark.parametrize("convert", converters)
  831. def test_SigningKey_sign_digest_deterministic(convert):
  832. sig = sk.sign_digest_deterministic(
  833. convert(data_hash), extra_entropy=convert(extra_entropy)
  834. )
  835. vk.verify(sig, data)
  836. @pytest.mark.parametrize("convert", converters)
  837. def test_SigningKey_sign(convert):
  838. sig = sk.sign(convert(data))
  839. vk.verify(sig, data)
  840. @pytest.mark.parametrize("convert", converters)
  841. def test_SigningKey_sign_digest(convert):
  842. sig = sk.sign_digest(convert(data_hash))
  843. vk.verify(sig, data)
  844. def test_SigningKey_with_unlikely_value():
  845. sk = SigningKey.from_secret_exponent(NIST256p.order - 1, curve=NIST256p)
  846. vk = sk.verifying_key
  847. sig = sk.sign(b"hello")
  848. assert vk.verify(sig, b"hello")
  849. def test_SigningKey_with_custom_curve_old_point():
  850. generator = generator_brainpoolp160r1
  851. generator = Point(
  852. generator.curve(),
  853. generator.x(),
  854. generator.y(),
  855. generator.order(),
  856. )
  857. curve = Curve(
  858. "BRAINPOOLP160r1",
  859. generator.curve(),
  860. generator,
  861. (1, 3, 36, 3, 3, 2, 8, 1, 1, 1),
  862. )
  863. sk = SigningKey.from_secret_exponent(12, curve)
  864. sk2 = SigningKey.from_secret_exponent(12, BRAINPOOLP160r1)
  865. assert sk.privkey == sk2.privkey
  866. def test_VerifyingKey_inequality_with_different_curves():
  867. sk1 = SigningKey.from_secret_exponent(2, BRAINPOOLP160r1)
  868. sk2 = SigningKey.from_secret_exponent(2, NIST256p)
  869. assert not (sk1.verifying_key == sk2.verifying_key)
  870. def test_VerifyingKey_inequality_with_different_secret_points():
  871. sk1 = SigningKey.from_secret_exponent(2, BRAINPOOLP160r1)
  872. sk2 = SigningKey.from_secret_exponent(3, BRAINPOOLP160r1)
  873. assert not (sk1.verifying_key == sk2.verifying_key)
  874. def test_SigningKey_from_pem_pkcs8v2_EdDSA():
  875. pem = """-----BEGIN PRIVATE KEY-----
  876. MFMCAQEwBQYDK2VwBCIEICc2F2ag1n1QP0jY+g9qWx5sDkx0s/HdNi3cSRHw+zsI
  877. oSMDIQA+HQ2xCif8a/LMWR2m5HaCm5I2pKe/cc8OiRANMHxjKQ==
  878. -----END PRIVATE KEY-----"""
  879. sk = SigningKey.from_pem(pem)
  880. assert sk.curve == Ed25519