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

2565 行
89 KiB

  1. from __future__ import with_statement, division, print_function
  2. try:
  3. import unittest2 as unittest
  4. except ImportError:
  5. import unittest
  6. import os
  7. import shutil
  8. import subprocess
  9. import pytest
  10. import sys
  11. from binascii import hexlify, unhexlify
  12. import hashlib
  13. from functools import partial
  14. from hypothesis import given, settings
  15. import hypothesis.strategies as st
  16. from six import binary_type
  17. from .keys import SigningKey, VerifyingKey
  18. from .keys import BadSignatureError, MalformedPointError, BadDigestError
  19. from . import util
  20. from .util import (
  21. sigencode_der,
  22. sigencode_strings,
  23. sigencode_strings_canonize,
  24. sigencode_string_canonize,
  25. sigencode_der_canonize,
  26. )
  27. from .util import sigdecode_der, sigdecode_strings, sigdecode_string
  28. from .util import number_to_string, encoded_oid_ecPublicKey, MalformedSignature
  29. from .curves import Curve, UnknownCurveError
  30. from .curves import (
  31. SECP112r1,
  32. SECP112r2,
  33. SECP128r1,
  34. SECP160r1,
  35. NIST192p,
  36. NIST224p,
  37. NIST256p,
  38. NIST384p,
  39. NIST521p,
  40. SECP256k1,
  41. BRAINPOOLP160r1,
  42. BRAINPOOLP192r1,
  43. BRAINPOOLP224r1,
  44. BRAINPOOLP256r1,
  45. BRAINPOOLP320r1,
  46. BRAINPOOLP384r1,
  47. BRAINPOOLP512r1,
  48. BRAINPOOLP160t1,
  49. BRAINPOOLP192t1,
  50. BRAINPOOLP224t1,
  51. BRAINPOOLP256t1,
  52. BRAINPOOLP320t1,
  53. BRAINPOOLP384t1,
  54. BRAINPOOLP512t1,
  55. Ed25519,
  56. Ed448,
  57. curves,
  58. )
  59. from .ecdsa import (
  60. curve_brainpoolp224r1,
  61. curve_brainpoolp256r1,
  62. curve_brainpoolp384r1,
  63. curve_brainpoolp512r1,
  64. )
  65. from .ellipticcurve import Point
  66. from . import der
  67. from . import rfc6979
  68. from . import ecdsa
  69. class SubprocessError(Exception):
  70. pass
  71. HYP_SETTINGS = {}
  72. if "--fast" in sys.argv: # pragma: no cover
  73. HYP_SETTINGS["max_examples"] = 2
  74. def run_openssl(cmd):
  75. OPENSSL = "openssl"
  76. p = subprocess.Popen(
  77. [OPENSSL] + cmd.split(),
  78. stdout=subprocess.PIPE,
  79. stderr=subprocess.STDOUT,
  80. )
  81. stdout, ignored = p.communicate()
  82. if p.returncode != 0:
  83. raise SubprocessError(
  84. "cmd '%s %s' failed: rc=%s, stdout/err was %s"
  85. % (OPENSSL, cmd, p.returncode, stdout)
  86. )
  87. return stdout.decode()
  88. class ECDSA(unittest.TestCase):
  89. def test_basic(self):
  90. priv = SigningKey.generate()
  91. pub = priv.get_verifying_key()
  92. data = b"blahblah"
  93. sig = priv.sign(data)
  94. self.assertTrue(pub.verify(sig, data))
  95. self.assertRaises(BadSignatureError, pub.verify, sig, data + b"bad")
  96. pub2 = VerifyingKey.from_string(pub.to_string())
  97. self.assertTrue(pub2.verify(sig, data))
  98. def test_deterministic(self):
  99. data = b"blahblah"
  100. secexp = int("9d0219792467d7d37b4d43298a7d0c05", 16)
  101. priv = SigningKey.from_secret_exponent(
  102. secexp, SECP256k1, hashlib.sha256
  103. )
  104. pub = priv.get_verifying_key()
  105. k = rfc6979.generate_k(
  106. SECP256k1.generator.order(),
  107. secexp,
  108. hashlib.sha256,
  109. hashlib.sha256(data).digest(),
  110. )
  111. sig1 = priv.sign(data, k=k)
  112. self.assertTrue(pub.verify(sig1, data))
  113. sig2 = priv.sign(data, k=k)
  114. self.assertTrue(pub.verify(sig2, data))
  115. sig3 = priv.sign_deterministic(data, hashlib.sha256)
  116. self.assertTrue(pub.verify(sig3, data))
  117. self.assertEqual(sig1, sig2)
  118. self.assertEqual(sig1, sig3)
  119. def test_bad_usage(self):
  120. # sk=SigningKey() is wrong
  121. self.assertRaises(TypeError, SigningKey)
  122. self.assertRaises(TypeError, VerifyingKey)
  123. def test_lengths_default(self):
  124. default = NIST192p
  125. priv = SigningKey.generate()
  126. pub = priv.get_verifying_key()
  127. self.assertEqual(len(pub.to_string()), default.verifying_key_length)
  128. sig = priv.sign(b"data")
  129. self.assertEqual(len(sig), default.signature_length)
  130. def test_serialize(self):
  131. seed = b"secret"
  132. curve = NIST192p
  133. secexp1 = util.randrange_from_seed__trytryagain(seed, curve.order)
  134. secexp2 = util.randrange_from_seed__trytryagain(seed, curve.order)
  135. self.assertEqual(secexp1, secexp2)
  136. priv1 = SigningKey.from_secret_exponent(secexp1, curve)
  137. priv2 = SigningKey.from_secret_exponent(secexp2, curve)
  138. self.assertEqual(
  139. hexlify(priv1.to_string()), hexlify(priv2.to_string())
  140. )
  141. self.assertEqual(priv1.to_pem(), priv2.to_pem())
  142. pub1 = priv1.get_verifying_key()
  143. pub2 = priv2.get_verifying_key()
  144. data = b"data"
  145. sig1 = priv1.sign(data)
  146. sig2 = priv2.sign(data)
  147. self.assertTrue(pub1.verify(sig1, data))
  148. self.assertTrue(pub2.verify(sig1, data))
  149. self.assertTrue(pub1.verify(sig2, data))
  150. self.assertTrue(pub2.verify(sig2, data))
  151. self.assertEqual(hexlify(pub1.to_string()), hexlify(pub2.to_string()))
  152. def test_nonrandom(self):
  153. s = b"all the entropy in the entire world, compressed into one line"
  154. def not_much_entropy(numbytes):
  155. return s[:numbytes]
  156. # we control the entropy source, these two keys should be identical:
  157. priv1 = SigningKey.generate(entropy=not_much_entropy)
  158. priv2 = SigningKey.generate(entropy=not_much_entropy)
  159. self.assertEqual(
  160. hexlify(priv1.get_verifying_key().to_string()),
  161. hexlify(priv2.get_verifying_key().to_string()),
  162. )
  163. # likewise, signatures should be identical. Obviously you'd never
  164. # want to do this with keys you care about, because the secrecy of
  165. # the private key depends upon using different random numbers for
  166. # each signature
  167. sig1 = priv1.sign(b"data", entropy=not_much_entropy)
  168. sig2 = priv2.sign(b"data", entropy=not_much_entropy)
  169. self.assertEqual(hexlify(sig1), hexlify(sig2))
  170. def assertTruePrivkeysEqual(self, priv1, priv2):
  171. self.assertEqual(
  172. priv1.privkey.secret_multiplier, priv2.privkey.secret_multiplier
  173. )
  174. self.assertEqual(
  175. priv1.privkey.public_key.generator,
  176. priv2.privkey.public_key.generator,
  177. )
  178. def test_privkey_creation(self):
  179. s = b"all the entropy in the entire world, compressed into one line"
  180. def not_much_entropy(numbytes):
  181. return s[:numbytes]
  182. priv1 = SigningKey.generate()
  183. self.assertEqual(priv1.baselen, NIST192p.baselen)
  184. priv1 = SigningKey.generate(curve=NIST224p)
  185. self.assertEqual(priv1.baselen, NIST224p.baselen)
  186. priv1 = SigningKey.generate(entropy=not_much_entropy)
  187. self.assertEqual(priv1.baselen, NIST192p.baselen)
  188. priv2 = SigningKey.generate(entropy=not_much_entropy)
  189. self.assertEqual(priv2.baselen, NIST192p.baselen)
  190. self.assertTruePrivkeysEqual(priv1, priv2)
  191. priv1 = SigningKey.from_secret_exponent(secexp=3)
  192. self.assertEqual(priv1.baselen, NIST192p.baselen)
  193. priv2 = SigningKey.from_secret_exponent(secexp=3)
  194. self.assertTruePrivkeysEqual(priv1, priv2)
  195. priv1 = SigningKey.from_secret_exponent(secexp=4, curve=NIST224p)
  196. self.assertEqual(priv1.baselen, NIST224p.baselen)
  197. def test_privkey_strings(self):
  198. priv1 = SigningKey.generate()
  199. s1 = priv1.to_string()
  200. self.assertEqual(type(s1), binary_type)
  201. self.assertEqual(len(s1), NIST192p.baselen)
  202. priv2 = SigningKey.from_string(s1)
  203. self.assertTruePrivkeysEqual(priv1, priv2)
  204. s1 = priv1.to_pem()
  205. self.assertEqual(type(s1), binary_type)
  206. self.assertTrue(s1.startswith(b"-----BEGIN EC PRIVATE KEY-----"))
  207. self.assertTrue(s1.strip().endswith(b"-----END EC PRIVATE KEY-----"))
  208. priv2 = SigningKey.from_pem(s1)
  209. self.assertTruePrivkeysEqual(priv1, priv2)
  210. s1 = priv1.to_der()
  211. self.assertEqual(type(s1), binary_type)
  212. priv2 = SigningKey.from_der(s1)
  213. self.assertTruePrivkeysEqual(priv1, priv2)
  214. priv1 = SigningKey.generate(curve=NIST256p)
  215. s1 = priv1.to_pem()
  216. self.assertEqual(type(s1), binary_type)
  217. self.assertTrue(s1.startswith(b"-----BEGIN EC PRIVATE KEY-----"))
  218. self.assertTrue(s1.strip().endswith(b"-----END EC PRIVATE KEY-----"))
  219. priv2 = SigningKey.from_pem(s1)
  220. self.assertTruePrivkeysEqual(priv1, priv2)
  221. s1 = priv1.to_der()
  222. self.assertEqual(type(s1), binary_type)
  223. priv2 = SigningKey.from_der(s1)
  224. self.assertTruePrivkeysEqual(priv1, priv2)
  225. def test_privkey_strings_brainpool(self):
  226. priv1 = SigningKey.generate(curve=BRAINPOOLP512r1)
  227. s1 = priv1.to_pem()
  228. self.assertEqual(type(s1), binary_type)
  229. self.assertTrue(s1.startswith(b"-----BEGIN EC PRIVATE KEY-----"))
  230. self.assertTrue(s1.strip().endswith(b"-----END EC PRIVATE KEY-----"))
  231. priv2 = SigningKey.from_pem(s1)
  232. self.assertTruePrivkeysEqual(priv1, priv2)
  233. s1 = priv1.to_der()
  234. self.assertEqual(type(s1), binary_type)
  235. priv2 = SigningKey.from_der(s1)
  236. self.assertTruePrivkeysEqual(priv1, priv2)
  237. def assertTruePubkeysEqual(self, pub1, pub2):
  238. self.assertEqual(pub1.pubkey.point, pub2.pubkey.point)
  239. self.assertEqual(pub1.pubkey.generator, pub2.pubkey.generator)
  240. self.assertEqual(pub1.curve, pub2.curve)
  241. def test_pubkey_strings(self):
  242. priv1 = SigningKey.generate()
  243. pub1 = priv1.get_verifying_key()
  244. s1 = pub1.to_string()
  245. self.assertEqual(type(s1), binary_type)
  246. self.assertEqual(len(s1), NIST192p.verifying_key_length)
  247. pub2 = VerifyingKey.from_string(s1)
  248. self.assertTruePubkeysEqual(pub1, pub2)
  249. priv1 = SigningKey.generate(curve=NIST256p)
  250. pub1 = priv1.get_verifying_key()
  251. s1 = pub1.to_string()
  252. self.assertEqual(type(s1), binary_type)
  253. self.assertEqual(len(s1), NIST256p.verifying_key_length)
  254. pub2 = VerifyingKey.from_string(s1, curve=NIST256p)
  255. self.assertTruePubkeysEqual(pub1, pub2)
  256. pub1_der = pub1.to_der()
  257. self.assertEqual(type(pub1_der), binary_type)
  258. pub2 = VerifyingKey.from_der(pub1_der)
  259. self.assertTruePubkeysEqual(pub1, pub2)
  260. self.assertRaises(
  261. der.UnexpectedDER, VerifyingKey.from_der, pub1_der + b"junk"
  262. )
  263. badpub = VerifyingKey.from_der(pub1_der)
  264. class FakeGenerator:
  265. def order(self):
  266. return 123456789
  267. class FakeCurveFp:
  268. def p(self):
  269. return int(
  270. "6525534529039240705020950546962731340"
  271. "4541085228058844382513856749047873406763"
  272. )
  273. badcurve = Curve(
  274. "unknown", FakeCurveFp(), FakeGenerator(), (1, 2, 3, 4, 5, 6), None
  275. )
  276. badpub.curve = badcurve
  277. badder = badpub.to_der()
  278. self.assertRaises(UnknownCurveError, VerifyingKey.from_der, badder)
  279. pem = pub1.to_pem()
  280. self.assertEqual(type(pem), binary_type)
  281. self.assertTrue(pem.startswith(b"-----BEGIN PUBLIC KEY-----"), pem)
  282. self.assertTrue(pem.strip().endswith(b"-----END PUBLIC KEY-----"), pem)
  283. pub2 = VerifyingKey.from_pem(pem)
  284. self.assertTruePubkeysEqual(pub1, pub2)
  285. def test_pubkey_strings_brainpool(self):
  286. priv1 = SigningKey.generate(curve=BRAINPOOLP512r1)
  287. pub1 = priv1.get_verifying_key()
  288. s1 = pub1.to_string()
  289. self.assertEqual(type(s1), binary_type)
  290. self.assertEqual(len(s1), BRAINPOOLP512r1.verifying_key_length)
  291. pub2 = VerifyingKey.from_string(s1, curve=BRAINPOOLP512r1)
  292. self.assertTruePubkeysEqual(pub1, pub2)
  293. pub1_der = pub1.to_der()
  294. self.assertEqual(type(pub1_der), binary_type)
  295. pub2 = VerifyingKey.from_der(pub1_der)
  296. self.assertTruePubkeysEqual(pub1, pub2)
  297. def test_vk_to_der_with_invalid_point_encoding(self):
  298. sk = SigningKey.generate()
  299. vk = sk.verifying_key
  300. with self.assertRaises(ValueError):
  301. vk.to_der("raw")
  302. def test_sk_to_der_with_invalid_point_encoding(self):
  303. sk = SigningKey.generate()
  304. with self.assertRaises(ValueError):
  305. sk.to_der("raw")
  306. def test_vk_from_der_garbage_after_curve_oid(self):
  307. type_oid_der = encoded_oid_ecPublicKey
  308. curve_oid_der = (
  309. der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1)) + b"garbage"
  310. )
  311. enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
  312. point_der = der.encode_bitstring(b"\x00\xff", None)
  313. to_decode = der.encode_sequence(enc_type_der, point_der)
  314. with self.assertRaises(der.UnexpectedDER):
  315. VerifyingKey.from_der(to_decode)
  316. def test_vk_from_der_invalid_key_type(self):
  317. type_oid_der = der.encode_oid(*(1, 2, 3))
  318. curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
  319. enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
  320. point_der = der.encode_bitstring(b"\x00\xff", None)
  321. to_decode = der.encode_sequence(enc_type_der, point_der)
  322. with self.assertRaises(der.UnexpectedDER):
  323. VerifyingKey.from_der(to_decode)
  324. def test_vk_from_der_garbage_after_point_string(self):
  325. type_oid_der = encoded_oid_ecPublicKey
  326. curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
  327. enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
  328. point_der = der.encode_bitstring(b"\x00\xff", None) + b"garbage"
  329. to_decode = der.encode_sequence(enc_type_der, point_der)
  330. with self.assertRaises(der.UnexpectedDER):
  331. VerifyingKey.from_der(to_decode)
  332. def test_vk_from_der_invalid_bitstring(self):
  333. type_oid_der = encoded_oid_ecPublicKey
  334. curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
  335. enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
  336. point_der = der.encode_bitstring(b"\x08\xff", None)
  337. to_decode = der.encode_sequence(enc_type_der, point_der)
  338. with self.assertRaises(der.UnexpectedDER):
  339. VerifyingKey.from_der(to_decode)
  340. def test_vk_from_der_with_invalid_length_of_encoding(self):
  341. type_oid_der = encoded_oid_ecPublicKey
  342. curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
  343. enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
  344. point_der = der.encode_bitstring(b"\xff" * 64, 0)
  345. to_decode = der.encode_sequence(enc_type_der, point_der)
  346. with self.assertRaises(MalformedPointError):
  347. VerifyingKey.from_der(to_decode)
  348. def test_vk_from_der_with_raw_encoding(self):
  349. type_oid_der = encoded_oid_ecPublicKey
  350. curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
  351. enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
  352. point_der = der.encode_bitstring(b"\xff" * 48, 0)
  353. to_decode = der.encode_sequence(enc_type_der, point_der)
  354. with self.assertRaises(der.UnexpectedDER):
  355. VerifyingKey.from_der(to_decode)
  356. def test_signature_strings(self):
  357. priv1 = SigningKey.generate()
  358. pub1 = priv1.get_verifying_key()
  359. data = b"data"
  360. sig = priv1.sign(data)
  361. self.assertEqual(type(sig), binary_type)
  362. self.assertEqual(len(sig), NIST192p.signature_length)
  363. self.assertTrue(pub1.verify(sig, data))
  364. sig = priv1.sign(data, sigencode=sigencode_strings)
  365. self.assertEqual(type(sig), tuple)
  366. self.assertEqual(len(sig), 2)
  367. self.assertEqual(type(sig[0]), binary_type)
  368. self.assertEqual(type(sig[1]), binary_type)
  369. self.assertEqual(len(sig[0]), NIST192p.baselen)
  370. self.assertEqual(len(sig[1]), NIST192p.baselen)
  371. self.assertTrue(pub1.verify(sig, data, sigdecode=sigdecode_strings))
  372. sig_der = priv1.sign(data, sigencode=sigencode_der)
  373. self.assertEqual(type(sig_der), binary_type)
  374. self.assertTrue(pub1.verify(sig_der, data, sigdecode=sigdecode_der))
  375. def test_sigencode_string_canonize_no_change(self):
  376. r = 12
  377. s = 400
  378. order = SECP112r1.order
  379. new_r, new_s = sigdecode_string(
  380. sigencode_string_canonize(r, s, order), order
  381. )
  382. self.assertEqual(r, new_r)
  383. self.assertEqual(s, new_s)
  384. def test_sigencode_string_canonize(self):
  385. r = 12
  386. order = SECP112r1.order
  387. s = order - 10
  388. new_r, new_s = sigdecode_string(
  389. sigencode_string_canonize(r, s, order), order
  390. )
  391. self.assertEqual(r, new_r)
  392. self.assertEqual(order - s, new_s)
  393. def test_sigencode_strings_canonize_no_change(self):
  394. r = 12
  395. s = 400
  396. order = SECP112r1.order
  397. new_r, new_s = sigdecode_strings(
  398. sigencode_strings_canonize(r, s, order), order
  399. )
  400. self.assertEqual(r, new_r)
  401. self.assertEqual(s, new_s)
  402. def test_sigencode_strings_canonize(self):
  403. r = 12
  404. order = SECP112r1.order
  405. s = order - 10
  406. new_r, new_s = sigdecode_strings(
  407. sigencode_strings_canonize(r, s, order), order
  408. )
  409. self.assertEqual(r, new_r)
  410. self.assertEqual(order - s, new_s)
  411. def test_sigencode_der_canonize_no_change(self):
  412. r = 13
  413. s = 200
  414. order = SECP112r1.order
  415. new_r, new_s = sigdecode_der(
  416. sigencode_der_canonize(r, s, order), order
  417. )
  418. self.assertEqual(r, new_r)
  419. self.assertEqual(s, new_s)
  420. def test_sigencode_der_canonize(self):
  421. r = 13
  422. order = SECP112r1.order
  423. s = order - 14
  424. new_r, new_s = sigdecode_der(
  425. sigencode_der_canonize(r, s, order), order
  426. )
  427. self.assertEqual(r, new_r)
  428. self.assertEqual(order - s, new_s)
  429. def test_sigencode_der_canonize_with_close_to_half_order(self):
  430. r = 13
  431. order = SECP112r1.order
  432. s = order // 2 + 1
  433. regular_encode = sigencode_der(r, s, order)
  434. canonical_encode = sigencode_der_canonize(r, s, order)
  435. self.assertNotEqual(regular_encode, canonical_encode)
  436. new_r, new_s = sigdecode_der(
  437. sigencode_der_canonize(r, s, order), order
  438. )
  439. self.assertEqual(r, new_r)
  440. self.assertEqual(order - s, new_s)
  441. def test_sig_decode_strings_with_invalid_count(self):
  442. with self.assertRaises(MalformedSignature):
  443. sigdecode_strings([b"one", b"two", b"three"], 0xFF)
  444. def test_sig_decode_strings_with_wrong_r_len(self):
  445. with self.assertRaises(MalformedSignature):
  446. sigdecode_strings([b"one", b"two"], 0xFF)
  447. def test_sig_decode_strings_with_wrong_s_len(self):
  448. with self.assertRaises(MalformedSignature):
  449. sigdecode_strings([b"\xa0", b"\xb0\xff"], 0xFF)
  450. def test_verify_with_too_long_input(self):
  451. sk = SigningKey.generate()
  452. vk = sk.verifying_key
  453. with self.assertRaises(BadDigestError):
  454. vk.verify_digest(None, b"\x00" * 128)
  455. def test_sk_from_secret_exponent_with_wrong_sec_exponent(self):
  456. with self.assertRaises(MalformedPointError):
  457. SigningKey.from_secret_exponent(0)
  458. def test_sk_from_string_with_wrong_len_string(self):
  459. with self.assertRaises(MalformedPointError):
  460. SigningKey.from_string(b"\x01")
  461. def test_sk_from_der_with_junk_after_sequence(self):
  462. ver_der = der.encode_integer(1)
  463. to_decode = der.encode_sequence(ver_der) + b"garbage"
  464. with self.assertRaises(der.UnexpectedDER):
  465. SigningKey.from_der(to_decode)
  466. def test_sk_from_der_with_wrong_version(self):
  467. ver_der = der.encode_integer(0)
  468. to_decode = der.encode_sequence(ver_der)
  469. with self.assertRaises(der.UnexpectedDER):
  470. SigningKey.from_der(to_decode)
  471. def test_sk_from_der_invalid_const_tag(self):
  472. ver_der = der.encode_integer(1)
  473. privkey_der = der.encode_octet_string(b"\x00\xff")
  474. curve_oid_der = der.encode_oid(*(1, 2, 3))
  475. const_der = der.encode_constructed(1, curve_oid_der)
  476. to_decode = der.encode_sequence(
  477. ver_der, privkey_der, const_der, curve_oid_der
  478. )
  479. with self.assertRaises(der.UnexpectedDER):
  480. SigningKey.from_der(to_decode)
  481. def test_sk_from_der_garbage_after_privkey_oid(self):
  482. ver_der = der.encode_integer(1)
  483. privkey_der = der.encode_octet_string(b"\x00\xff")
  484. curve_oid_der = der.encode_oid(*(1, 2, 3)) + b"garbage"
  485. const_der = der.encode_constructed(0, curve_oid_der)
  486. to_decode = der.encode_sequence(
  487. ver_der, privkey_der, const_der, curve_oid_der
  488. )
  489. with self.assertRaises(der.UnexpectedDER):
  490. SigningKey.from_der(to_decode)
  491. def test_sk_from_der_with_short_privkey(self):
  492. ver_der = der.encode_integer(1)
  493. privkey_der = der.encode_octet_string(b"\x00\xff")
  494. curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
  495. const_der = der.encode_constructed(0, curve_oid_der)
  496. to_decode = der.encode_sequence(
  497. ver_der, privkey_der, const_der, curve_oid_der
  498. )
  499. sk = SigningKey.from_der(to_decode)
  500. self.assertEqual(sk.privkey.secret_multiplier, 255)
  501. def test_sk_from_p8_der_with_wrong_version(self):
  502. ver_der = der.encode_integer(2)
  503. algorithm_der = der.encode_sequence(
  504. der.encode_oid(1, 2, 840, 10045, 2, 1),
  505. der.encode_oid(1, 2, 840, 10045, 3, 1, 1),
  506. )
  507. privkey_der = der.encode_octet_string(
  508. der.encode_sequence(
  509. der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
  510. )
  511. )
  512. to_decode = der.encode_sequence(ver_der, algorithm_der, privkey_der)
  513. with self.assertRaises(der.UnexpectedDER):
  514. SigningKey.from_der(to_decode)
  515. def test_sk_from_p8_der_with_wrong_algorithm(self):
  516. ver_der = der.encode_integer(1)
  517. algorithm_der = der.encode_sequence(
  518. der.encode_oid(1, 2, 3), der.encode_oid(1, 2, 840, 10045, 3, 1, 1)
  519. )
  520. privkey_der = der.encode_octet_string(
  521. der.encode_sequence(
  522. der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
  523. )
  524. )
  525. to_decode = der.encode_sequence(ver_der, algorithm_der, privkey_der)
  526. with self.assertRaises(der.UnexpectedDER):
  527. SigningKey.from_der(to_decode)
  528. def test_sk_from_p8_der_with_trailing_junk_after_algorithm(self):
  529. ver_der = der.encode_integer(1)
  530. algorithm_der = der.encode_sequence(
  531. der.encode_oid(1, 2, 840, 10045, 2, 1),
  532. der.encode_oid(1, 2, 840, 10045, 3, 1, 1),
  533. der.encode_octet_string(b"junk"),
  534. )
  535. privkey_der = der.encode_octet_string(
  536. der.encode_sequence(
  537. der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
  538. )
  539. )
  540. to_decode = der.encode_sequence(ver_der, algorithm_der, privkey_der)
  541. with self.assertRaises(der.UnexpectedDER):
  542. SigningKey.from_der(to_decode)
  543. def test_sk_from_p8_der_with_trailing_junk_after_key(self):
  544. ver_der = der.encode_integer(1)
  545. algorithm_der = der.encode_sequence(
  546. der.encode_oid(1, 2, 840, 10045, 2, 1),
  547. der.encode_oid(1, 2, 840, 10045, 3, 1, 1),
  548. )
  549. privkey_der = der.encode_octet_string(
  550. der.encode_sequence(
  551. der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
  552. )
  553. + der.encode_integer(999)
  554. )
  555. to_decode = der.encode_sequence(
  556. ver_der,
  557. algorithm_der,
  558. privkey_der,
  559. der.encode_octet_string(b"junk"),
  560. )
  561. with self.assertRaises(der.UnexpectedDER):
  562. SigningKey.from_der(to_decode)
  563. def test_sign_with_too_long_hash(self):
  564. sk = SigningKey.from_secret_exponent(12)
  565. with self.assertRaises(BadDigestError):
  566. sk.sign_digest(b"\xff" * 64)
  567. def test_hashfunc(self):
  568. sk = SigningKey.generate(curve=NIST256p, hashfunc=hashlib.sha256)
  569. data = b"security level is 128 bits"
  570. sig = sk.sign(data)
  571. vk = VerifyingKey.from_string(
  572. sk.get_verifying_key().to_string(),
  573. curve=NIST256p,
  574. hashfunc=hashlib.sha256,
  575. )
  576. self.assertTrue(vk.verify(sig, data))
  577. sk2 = SigningKey.generate(curve=NIST256p)
  578. sig2 = sk2.sign(data, hashfunc=hashlib.sha256)
  579. vk2 = VerifyingKey.from_string(
  580. sk2.get_verifying_key().to_string(),
  581. curve=NIST256p,
  582. hashfunc=hashlib.sha256,
  583. )
  584. self.assertTrue(vk2.verify(sig2, data))
  585. vk3 = VerifyingKey.from_string(
  586. sk.get_verifying_key().to_string(), curve=NIST256p
  587. )
  588. self.assertTrue(vk3.verify(sig, data, hashfunc=hashlib.sha256))
  589. def test_public_key_recovery(self):
  590. # Create keys
  591. curve = BRAINPOOLP160r1
  592. sk = SigningKey.generate(curve=curve)
  593. vk = sk.get_verifying_key()
  594. # Sign a message
  595. data = b"blahblah"
  596. signature = sk.sign(data)
  597. # Recover verifying keys
  598. recovered_vks = VerifyingKey.from_public_key_recovery(
  599. signature, data, curve
  600. )
  601. # Test if each pk is valid
  602. for recovered_vk in recovered_vks:
  603. # Test if recovered vk is valid for the data
  604. self.assertTrue(recovered_vk.verify(signature, data))
  605. # Test if properties are equal
  606. self.assertEqual(vk.curve, recovered_vk.curve)
  607. self.assertEqual(
  608. vk.default_hashfunc, recovered_vk.default_hashfunc
  609. )
  610. # Test if original vk is the list of recovered keys
  611. self.assertIn(
  612. vk.pubkey.point,
  613. [recovered_vk.pubkey.point for recovered_vk in recovered_vks],
  614. )
  615. def test_public_key_recovery_with_custom_hash(self):
  616. # Create keys
  617. curve = BRAINPOOLP160r1
  618. sk = SigningKey.generate(curve=curve, hashfunc=hashlib.sha256)
  619. vk = sk.get_verifying_key()
  620. # Sign a message
  621. data = b"blahblah"
  622. signature = sk.sign(data)
  623. # Recover verifying keys
  624. recovered_vks = VerifyingKey.from_public_key_recovery(
  625. signature,
  626. data,
  627. curve,
  628. hashfunc=hashlib.sha256,
  629. allow_truncate=True,
  630. )
  631. # Test if each pk is valid
  632. for recovered_vk in recovered_vks:
  633. # Test if recovered vk is valid for the data
  634. self.assertTrue(recovered_vk.verify(signature, data))
  635. # Test if properties are equal
  636. self.assertEqual(vk.curve, recovered_vk.curve)
  637. self.assertEqual(hashlib.sha256, recovered_vk.default_hashfunc)
  638. # Test if original vk is the list of recovered keys
  639. self.assertIn(
  640. vk.pubkey.point,
  641. [recovered_vk.pubkey.point for recovered_vk in recovered_vks],
  642. )
  643. def test_encoding(self):
  644. sk = SigningKey.from_secret_exponent(123456789)
  645. vk = sk.verifying_key
  646. exp = (
  647. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  648. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  649. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  650. )
  651. self.assertEqual(vk.to_string(), exp)
  652. self.assertEqual(vk.to_string("raw"), exp)
  653. self.assertEqual(vk.to_string("uncompressed"), b"\x04" + exp)
  654. self.assertEqual(vk.to_string("compressed"), b"\x02" + exp[:24])
  655. self.assertEqual(vk.to_string("hybrid"), b"\x06" + exp)
  656. def test_decoding(self):
  657. sk = SigningKey.from_secret_exponent(123456789)
  658. vk = sk.verifying_key
  659. enc = (
  660. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  661. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  662. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  663. )
  664. from_raw = VerifyingKey.from_string(enc)
  665. self.assertEqual(from_raw.pubkey.point, vk.pubkey.point)
  666. from_uncompressed = VerifyingKey.from_string(b"\x04" + enc)
  667. self.assertEqual(from_uncompressed.pubkey.point, vk.pubkey.point)
  668. from_compressed = VerifyingKey.from_string(b"\x02" + enc[:24])
  669. self.assertEqual(from_compressed.pubkey.point, vk.pubkey.point)
  670. from_uncompressed = VerifyingKey.from_string(b"\x06" + enc)
  671. self.assertEqual(from_uncompressed.pubkey.point, vk.pubkey.point)
  672. def test_uncompressed_decoding_as_only_alowed(self):
  673. enc = (
  674. b"\x04"
  675. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  676. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  677. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  678. )
  679. vk = VerifyingKey.from_string(enc, valid_encodings=("uncompressed",))
  680. sk = SigningKey.from_secret_exponent(123456789)
  681. self.assertEqual(vk, sk.verifying_key)
  682. def test_raw_decoding_with_blocked_format(self):
  683. enc = (
  684. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  685. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  686. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  687. )
  688. with self.assertRaises(MalformedPointError) as exp:
  689. VerifyingKey.from_string(enc, valid_encodings=("hybrid",))
  690. self.assertIn("hybrid", str(exp.exception))
  691. def test_decoding_with_unknown_format(self):
  692. with self.assertRaises(ValueError) as e:
  693. VerifyingKey.from_string(b"", valid_encodings=("raw", "foobar"))
  694. self.assertIn("Only uncompressed, compressed", str(e.exception))
  695. def test_uncompressed_decoding_with_blocked_format(self):
  696. enc = (
  697. b"\x04"
  698. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  699. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  700. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  701. )
  702. with self.assertRaises(MalformedPointError) as exp:
  703. VerifyingKey.from_string(enc, valid_encodings=("hybrid",))
  704. self.assertIn("Invalid X9.62 encoding", str(exp.exception))
  705. def test_hybrid_decoding_with_blocked_format(self):
  706. enc = (
  707. b"\x06"
  708. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  709. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  710. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  711. )
  712. with self.assertRaises(MalformedPointError) as exp:
  713. VerifyingKey.from_string(enc, valid_encodings=("uncompressed",))
  714. self.assertIn("Invalid X9.62 encoding", str(exp.exception))
  715. def test_hybrid_decoding_with_inconsistent_encoding_and_no_validation(
  716. self,
  717. ):
  718. sk = SigningKey.from_secret_exponent(123456789)
  719. vk = sk.verifying_key
  720. enc = vk.to_string("hybrid")
  721. self.assertEqual(enc[:1], b"\x06")
  722. enc = b"\x07" + enc[1:]
  723. b = VerifyingKey.from_string(
  724. enc, valid_encodings=("hybrid",), validate_point=False
  725. )
  726. self.assertEqual(vk, b)
  727. def test_compressed_decoding_with_blocked_format(self):
  728. enc = (
  729. b"\x02"
  730. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  731. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  732. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  733. )[:25]
  734. with self.assertRaises(MalformedPointError) as exp:
  735. VerifyingKey.from_string(enc, valid_encodings=("hybrid", "raw"))
  736. self.assertIn("(hybrid, raw)", str(exp.exception))
  737. def test_decoding_with_malformed_uncompressed(self):
  738. enc = (
  739. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  740. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  741. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  742. )
  743. with self.assertRaises(MalformedPointError):
  744. VerifyingKey.from_string(b"\x02" + enc)
  745. def test_decoding_with_malformed_compressed(self):
  746. enc = (
  747. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  748. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  749. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  750. )
  751. with self.assertRaises(MalformedPointError):
  752. VerifyingKey.from_string(b"\x01" + enc[:24])
  753. def test_decoding_with_inconsistent_hybrid(self):
  754. enc = (
  755. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  756. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  757. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  758. )
  759. with self.assertRaises(MalformedPointError):
  760. VerifyingKey.from_string(b"\x07" + enc)
  761. def test_decoding_with_inconsistent_hybrid_odd_point(self):
  762. sk = SigningKey.from_secret_exponent(123456791)
  763. vk = sk.verifying_key
  764. enc = vk.to_string("hybrid")
  765. self.assertEqual(enc[:1], b"\x07")
  766. enc = b"\x06" + enc[1:]
  767. with self.assertRaises(MalformedPointError):
  768. b = VerifyingKey.from_string(enc, valid_encodings=("hybrid",))
  769. def test_decoding_with_point_not_on_curve(self):
  770. enc = (
  771. b"\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
  772. b"\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
  773. b"z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
  774. )
  775. with self.assertRaises(MalformedPointError):
  776. VerifyingKey.from_string(enc[:47] + b"\x00")
  777. def test_decoding_with_point_at_infinity(self):
  778. # decoding it is unsupported, as it's not necessary to encode it
  779. with self.assertRaises(MalformedPointError):
  780. VerifyingKey.from_string(b"\x00")
  781. def test_not_lying_on_curve(self):
  782. enc = number_to_string(NIST192p.curve.p(), NIST192p.curve.p() + 1)
  783. with self.assertRaises(MalformedPointError):
  784. VerifyingKey.from_string(b"\x02" + enc)
  785. def test_from_string_with_invalid_curve_too_short_ver_key_len(self):
  786. # both verifying_key_length and baselen are calculated internally
  787. # by the Curve constructor, but since we depend on them verify
  788. # that inconsistent values are detected
  789. curve = Curve("test", ecdsa.curve_192, ecdsa.generator_192, (1, 2))
  790. curve.verifying_key_length = 16
  791. curve.baselen = 32
  792. with self.assertRaises(MalformedPointError):
  793. VerifyingKey.from_string(b"\x00" * 16, curve)
  794. def test_from_string_with_invalid_curve_too_long_ver_key_len(self):
  795. # both verifying_key_length and baselen are calculated internally
  796. # by the Curve constructor, but since we depend on them verify
  797. # that inconsistent values are detected
  798. curve = Curve("test", ecdsa.curve_192, ecdsa.generator_192, (1, 2))
  799. curve.verifying_key_length = 16
  800. curve.baselen = 16
  801. with self.assertRaises(MalformedPointError):
  802. VerifyingKey.from_string(b"\x00" * 16, curve)
  803. @pytest.mark.parametrize(
  804. "val,even", [(i, j) for i in range(256) for j in [True, False]]
  805. )
  806. def test_VerifyingKey_decode_with_small_values(val, even):
  807. enc = number_to_string(val, NIST192p.order)
  808. if even:
  809. enc = b"\x02" + enc
  810. else:
  811. enc = b"\x03" + enc
  812. # small values can both be actual valid public keys and not, verify that
  813. # only expected exceptions are raised if they are not
  814. try:
  815. vk = VerifyingKey.from_string(enc)
  816. assert isinstance(vk, VerifyingKey)
  817. except MalformedPointError:
  818. assert True
  819. params = []
  820. for curve in curves:
  821. for enc in ["raw", "uncompressed", "compressed", "hybrid"]:
  822. params.append(
  823. pytest.param(curve, enc, id="{0}-{1}".format(curve.name, enc))
  824. )
  825. @pytest.mark.parametrize("curve,encoding", params)
  826. def test_VerifyingKey_encode_decode(curve, encoding):
  827. sk = SigningKey.generate(curve=curve)
  828. vk = sk.verifying_key
  829. encoded = vk.to_string(encoding)
  830. from_enc = VerifyingKey.from_string(encoded, curve=curve)
  831. assert vk.pubkey.point == from_enc.pubkey.point
  832. if "--fast" in sys.argv: # pragma: no cover
  833. params = [NIST192p, BRAINPOOLP160r1]
  834. else:
  835. params = curves
  836. @pytest.mark.parametrize("curve", params)
  837. def test_lengths(curve):
  838. priv = SigningKey.generate(curve=curve)
  839. pub1 = priv.get_verifying_key()
  840. pub2 = VerifyingKey.from_string(pub1.to_string(), curve)
  841. assert pub1.to_string() == pub2.to_string()
  842. assert len(pub1.to_string()) == curve.verifying_key_length
  843. sig = priv.sign(b"data")
  844. assert len(sig) == curve.signature_length
  845. @pytest.mark.slow
  846. class OpenSSL(unittest.TestCase):
  847. # test interoperability with OpenSSL tools. Note that openssl's ECDSA
  848. # sign/verify arguments changed between 0.9.8 and 1.0.0: the early
  849. # versions require "-ecdsa-with-SHA1", the later versions want just
  850. # "-SHA1" (or to leave out that argument entirely, which means the
  851. # signature will use some default digest algorithm, probably determined
  852. # by the key, probably always SHA1).
  853. #
  854. # openssl ecparam -name secp224r1 -genkey -out privkey.pem
  855. # openssl ec -in privkey.pem -text -noout # get the priv/pub keys
  856. # openssl dgst -ecdsa-with-SHA1 -sign privkey.pem -out data.sig data.txt
  857. # openssl asn1parse -in data.sig -inform DER
  858. # data.sig is 64 bytes, probably 56b plus ASN1 overhead
  859. # openssl dgst -ecdsa-with-SHA1 -prverify privkey.pem -signature data.sig data.txt ; echo $?
  860. # openssl ec -in privkey.pem -pubout -out pubkey.pem
  861. # openssl ec -in privkey.pem -pubout -outform DER -out pubkey.der
  862. OPENSSL_SUPPORTED_CURVES = set(
  863. c.split(":")[0].strip()
  864. for c in run_openssl("ecparam -list_curves").split("\n")
  865. )
  866. def get_openssl_messagedigest_arg(self, hash_name):
  867. v = run_openssl("version")
  868. # e.g. "OpenSSL 1.0.0 29 Mar 2010", or "OpenSSL 1.0.0a 1 Jun 2010",
  869. # or "OpenSSL 0.9.8o 01 Jun 2010"
  870. vs = v.split()[1].split(".")
  871. if vs >= ["1", "0", "0"]: # pragma: no cover
  872. return "-{0}".format(hash_name)
  873. else: # pragma: no cover
  874. return "-ecdsa-with-{0}".format(hash_name)
  875. # sk: 1:OpenSSL->python 2:python->OpenSSL
  876. # vk: 3:OpenSSL->python 4:python->OpenSSL
  877. # sig: 5:OpenSSL->python 6:python->OpenSSL
  878. @pytest.mark.slow
  879. @pytest.mark.skipif(
  880. "secp112r1" not in OPENSSL_SUPPORTED_CURVES,
  881. reason="system openssl does not support secp112r1",
  882. )
  883. def test_from_openssl_secp112r1(self):
  884. return self.do_test_from_openssl(SECP112r1)
  885. @pytest.mark.slow
  886. @pytest.mark.skipif(
  887. "secp112r2" not in OPENSSL_SUPPORTED_CURVES,
  888. reason="system openssl does not support secp112r2",
  889. )
  890. def test_from_openssl_secp112r2(self):
  891. return self.do_test_from_openssl(SECP112r2)
  892. @pytest.mark.slow
  893. @pytest.mark.skipif(
  894. "secp128r1" not in OPENSSL_SUPPORTED_CURVES,
  895. reason="system openssl does not support secp128r1",
  896. )
  897. def test_from_openssl_secp128r1(self):
  898. return self.do_test_from_openssl(SECP128r1)
  899. @pytest.mark.slow
  900. @pytest.mark.skipif(
  901. "secp160r1" not in OPENSSL_SUPPORTED_CURVES,
  902. reason="system openssl does not support secp160r1",
  903. )
  904. def test_from_openssl_secp160r1(self):
  905. return self.do_test_from_openssl(SECP160r1)
  906. @pytest.mark.slow
  907. @pytest.mark.skipif(
  908. "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
  909. reason="system openssl does not support prime192v1",
  910. )
  911. def test_from_openssl_nist192p(self):
  912. return self.do_test_from_openssl(NIST192p)
  913. @pytest.mark.slow
  914. @pytest.mark.skipif(
  915. "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
  916. reason="system openssl does not support prime192v1",
  917. )
  918. def test_from_openssl_nist192p_sha256(self):
  919. return self.do_test_from_openssl(NIST192p, "SHA256")
  920. @pytest.mark.slow
  921. @pytest.mark.skipif(
  922. "secp224r1" not in OPENSSL_SUPPORTED_CURVES,
  923. reason="system openssl does not support secp224r1",
  924. )
  925. def test_from_openssl_nist224p(self):
  926. return self.do_test_from_openssl(NIST224p)
  927. @pytest.mark.slow
  928. @pytest.mark.skipif(
  929. "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
  930. reason="system openssl does not support prime256v1",
  931. )
  932. def test_from_openssl_nist256p(self):
  933. return self.do_test_from_openssl(NIST256p)
  934. @pytest.mark.slow
  935. @pytest.mark.skipif(
  936. "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
  937. reason="system openssl does not support prime256v1",
  938. )
  939. def test_from_openssl_nist256p_sha384(self):
  940. return self.do_test_from_openssl(NIST256p, "SHA384")
  941. @pytest.mark.slow
  942. @pytest.mark.skipif(
  943. "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
  944. reason="system openssl does not support prime256v1",
  945. )
  946. def test_from_openssl_nist256p_sha512(self):
  947. return self.do_test_from_openssl(NIST256p, "SHA512")
  948. @pytest.mark.slow
  949. @pytest.mark.skipif(
  950. "secp384r1" not in OPENSSL_SUPPORTED_CURVES,
  951. reason="system openssl does not support secp384r1",
  952. )
  953. def test_from_openssl_nist384p(self):
  954. return self.do_test_from_openssl(NIST384p)
  955. @pytest.mark.slow
  956. @pytest.mark.skipif(
  957. "secp521r1" not in OPENSSL_SUPPORTED_CURVES,
  958. reason="system openssl does not support secp521r1",
  959. )
  960. def test_from_openssl_nist521p(self):
  961. return self.do_test_from_openssl(NIST521p)
  962. @pytest.mark.slow
  963. @pytest.mark.skipif(
  964. "secp256k1" not in OPENSSL_SUPPORTED_CURVES,
  965. reason="system openssl does not support secp256k1",
  966. )
  967. def test_from_openssl_secp256k1(self):
  968. return self.do_test_from_openssl(SECP256k1)
  969. @pytest.mark.slow
  970. @pytest.mark.skipif(
  971. "brainpoolP160r1" not in OPENSSL_SUPPORTED_CURVES,
  972. reason="system openssl does not support brainpoolP160r1",
  973. )
  974. def test_from_openssl_brainpoolp160r1(self):
  975. return self.do_test_from_openssl(BRAINPOOLP160r1)
  976. @pytest.mark.slow
  977. @pytest.mark.skipif(
  978. "brainpoolP192r1" not in OPENSSL_SUPPORTED_CURVES,
  979. reason="system openssl does not support brainpoolP192r1",
  980. )
  981. def test_from_openssl_brainpoolp192r1(self):
  982. return self.do_test_from_openssl(BRAINPOOLP192r1)
  983. @pytest.mark.slow
  984. @pytest.mark.skipif(
  985. "brainpoolP224r1" not in OPENSSL_SUPPORTED_CURVES,
  986. reason="system openssl does not support brainpoolP224r1",
  987. )
  988. def test_from_openssl_brainpoolp224r1(self):
  989. return self.do_test_from_openssl(BRAINPOOLP224r1)
  990. @pytest.mark.slow
  991. @pytest.mark.skipif(
  992. "brainpoolP256r1" not in OPENSSL_SUPPORTED_CURVES,
  993. reason="system openssl does not support brainpoolP256r1",
  994. )
  995. def test_from_openssl_brainpoolp256r1(self):
  996. return self.do_test_from_openssl(BRAINPOOLP256r1)
  997. @pytest.mark.slow
  998. @pytest.mark.skipif(
  999. "brainpoolP320r1" not in OPENSSL_SUPPORTED_CURVES,
  1000. reason="system openssl does not support brainpoolP320r1",
  1001. )
  1002. def test_from_openssl_brainpoolp320r1(self):
  1003. return self.do_test_from_openssl(BRAINPOOLP320r1)
  1004. @pytest.mark.slow
  1005. @pytest.mark.skipif(
  1006. "brainpoolP384r1" not in OPENSSL_SUPPORTED_CURVES,
  1007. reason="system openssl does not support brainpoolP384r1",
  1008. )
  1009. def test_from_openssl_brainpoolp384r1(self):
  1010. return self.do_test_from_openssl(BRAINPOOLP384r1)
  1011. @pytest.mark.slow
  1012. @pytest.mark.skipif(
  1013. "brainpoolP512r1" not in OPENSSL_SUPPORTED_CURVES,
  1014. reason="system openssl does not support brainpoolP512r1",
  1015. )
  1016. def test_from_openssl_brainpoolp512r1(self):
  1017. return self.do_test_from_openssl(BRAINPOOLP512r1)
  1018. @pytest.mark.slow
  1019. @pytest.mark.skipif(
  1020. "brainpoolP160t1" not in OPENSSL_SUPPORTED_CURVES,
  1021. reason="system openssl does not support brainpoolP160t1",
  1022. )
  1023. def test_from_openssl_brainpoolp160t1(self):
  1024. return self.do_test_from_openssl(BRAINPOOLP160t1)
  1025. @pytest.mark.slow
  1026. @pytest.mark.skipif(
  1027. "brainpoolP192t1" not in OPENSSL_SUPPORTED_CURVES,
  1028. reason="system openssl does not support brainpoolP192t1",
  1029. )
  1030. def test_from_openssl_brainpoolp192t1(self):
  1031. return self.do_test_from_openssl(BRAINPOOLP192t1)
  1032. @pytest.mark.slow
  1033. @pytest.mark.skipif(
  1034. "brainpoolP224t1" not in OPENSSL_SUPPORTED_CURVES,
  1035. reason="system openssl does not support brainpoolP224t1",
  1036. )
  1037. def test_from_openssl_brainpoolp224t1(self):
  1038. return self.do_test_from_openssl(BRAINPOOLP224t1)
  1039. @pytest.mark.slow
  1040. @pytest.mark.skipif(
  1041. "brainpoolP256t1" not in OPENSSL_SUPPORTED_CURVES,
  1042. reason="system openssl does not support brainpoolP256t1",
  1043. )
  1044. def test_from_openssl_brainpoolp256t1(self):
  1045. return self.do_test_from_openssl(BRAINPOOLP256t1)
  1046. @pytest.mark.slow
  1047. @pytest.mark.skipif(
  1048. "brainpoolP320t1" not in OPENSSL_SUPPORTED_CURVES,
  1049. reason="system openssl does not support brainpoolP320t1",
  1050. )
  1051. def test_from_openssl_brainpoolp320t1(self):
  1052. return self.do_test_from_openssl(BRAINPOOLP320t1)
  1053. @pytest.mark.slow
  1054. @pytest.mark.skipif(
  1055. "brainpoolP384t1" not in OPENSSL_SUPPORTED_CURVES,
  1056. reason="system openssl does not support brainpoolP384t1",
  1057. )
  1058. def test_from_openssl_brainpoolp384t1(self):
  1059. return self.do_test_from_openssl(BRAINPOOLP384t1)
  1060. @pytest.mark.slow
  1061. @pytest.mark.skipif(
  1062. "brainpoolP512t1" not in OPENSSL_SUPPORTED_CURVES,
  1063. reason="system openssl does not support brainpoolP512t1",
  1064. )
  1065. def test_from_openssl_brainpoolp512t1(self):
  1066. return self.do_test_from_openssl(BRAINPOOLP512t1)
  1067. def do_test_from_openssl(self, curve, hash_name="SHA1"):
  1068. curvename = curve.openssl_name
  1069. assert curvename
  1070. # OpenSSL: create sk, vk, sign.
  1071. # Python: read vk(3), checksig(5), read sk(1), sign, check
  1072. mdarg = self.get_openssl_messagedigest_arg(hash_name)
  1073. if os.path.isdir("t"): # pragma: no cover
  1074. shutil.rmtree("t")
  1075. os.mkdir("t")
  1076. run_openssl("ecparam -name %s -genkey -out t/privkey.pem" % curvename)
  1077. run_openssl("ec -in t/privkey.pem -pubout -out t/pubkey.pem")
  1078. data = b"data"
  1079. with open("t/data.txt", "wb") as e:
  1080. e.write(data)
  1081. run_openssl(
  1082. "dgst %s -sign t/privkey.pem -out t/data.sig t/data.txt" % mdarg
  1083. )
  1084. run_openssl(
  1085. "dgst %s -verify t/pubkey.pem -signature t/data.sig t/data.txt"
  1086. % mdarg
  1087. )
  1088. with open("t/pubkey.pem", "rb") as e:
  1089. pubkey_pem = e.read()
  1090. vk = VerifyingKey.from_pem(pubkey_pem) # 3
  1091. with open("t/data.sig", "rb") as e:
  1092. sig_der = e.read()
  1093. self.assertTrue(
  1094. vk.verify(
  1095. sig_der,
  1096. data, # 5
  1097. hashfunc=partial(hashlib.new, hash_name),
  1098. sigdecode=sigdecode_der,
  1099. )
  1100. )
  1101. with open("t/privkey.pem") as e:
  1102. fp = e.read()
  1103. sk = SigningKey.from_pem(fp) # 1
  1104. sig = sk.sign(data, hashfunc=partial(hashlib.new, hash_name))
  1105. self.assertTrue(
  1106. vk.verify(sig, data, hashfunc=partial(hashlib.new, hash_name))
  1107. )
  1108. run_openssl(
  1109. "pkcs8 -topk8 -nocrypt "
  1110. "-in t/privkey.pem -outform pem -out t/privkey-p8.pem"
  1111. )
  1112. with open("t/privkey-p8.pem", "rb") as e:
  1113. privkey_p8_pem = e.read()
  1114. sk_from_p8 = SigningKey.from_pem(privkey_p8_pem)
  1115. self.assertEqual(sk, sk_from_p8)
  1116. @pytest.mark.slow
  1117. @pytest.mark.skipif(
  1118. "secp112r1" not in OPENSSL_SUPPORTED_CURVES,
  1119. reason="system openssl does not support secp112r1",
  1120. )
  1121. def test_to_openssl_secp112r1(self):
  1122. self.do_test_to_openssl(SECP112r1)
  1123. @pytest.mark.slow
  1124. @pytest.mark.skipif(
  1125. "secp112r2" not in OPENSSL_SUPPORTED_CURVES,
  1126. reason="system openssl does not support secp112r2",
  1127. )
  1128. def test_to_openssl_secp112r2(self):
  1129. self.do_test_to_openssl(SECP112r2)
  1130. @pytest.mark.slow
  1131. @pytest.mark.skipif(
  1132. "secp128r1" not in OPENSSL_SUPPORTED_CURVES,
  1133. reason="system openssl does not support secp128r1",
  1134. )
  1135. def test_to_openssl_secp128r1(self):
  1136. self.do_test_to_openssl(SECP128r1)
  1137. @pytest.mark.slow
  1138. @pytest.mark.skipif(
  1139. "secp160r1" not in OPENSSL_SUPPORTED_CURVES,
  1140. reason="system openssl does not support secp160r1",
  1141. )
  1142. def test_to_openssl_secp160r1(self):
  1143. self.do_test_to_openssl(SECP160r1)
  1144. @pytest.mark.slow
  1145. @pytest.mark.skipif(
  1146. "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
  1147. reason="system openssl does not support prime192v1",
  1148. )
  1149. def test_to_openssl_nist192p(self):
  1150. self.do_test_to_openssl(NIST192p)
  1151. @pytest.mark.slow
  1152. @pytest.mark.skipif(
  1153. "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
  1154. reason="system openssl does not support prime192v1",
  1155. )
  1156. def test_to_openssl_nist192p_sha256(self):
  1157. self.do_test_to_openssl(NIST192p, "SHA256")
  1158. @pytest.mark.slow
  1159. @pytest.mark.skipif(
  1160. "secp224r1" not in OPENSSL_SUPPORTED_CURVES,
  1161. reason="system openssl does not support secp224r1",
  1162. )
  1163. def test_to_openssl_nist224p(self):
  1164. self.do_test_to_openssl(NIST224p)
  1165. @pytest.mark.slow
  1166. @pytest.mark.skipif(
  1167. "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
  1168. reason="system openssl does not support prime256v1",
  1169. )
  1170. def test_to_openssl_nist256p(self):
  1171. self.do_test_to_openssl(NIST256p)
  1172. @pytest.mark.slow
  1173. @pytest.mark.skipif(
  1174. "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
  1175. reason="system openssl does not support prime256v1",
  1176. )
  1177. def test_to_openssl_nist256p_sha384(self):
  1178. self.do_test_to_openssl(NIST256p, "SHA384")
  1179. @pytest.mark.slow
  1180. @pytest.mark.skipif(
  1181. "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
  1182. reason="system openssl does not support prime256v1",
  1183. )
  1184. def test_to_openssl_nist256p_sha512(self):
  1185. self.do_test_to_openssl(NIST256p, "SHA512")
  1186. @pytest.mark.slow
  1187. @pytest.mark.skipif(
  1188. "secp384r1" not in OPENSSL_SUPPORTED_CURVES,
  1189. reason="system openssl does not support secp384r1",
  1190. )
  1191. def test_to_openssl_nist384p(self):
  1192. self.do_test_to_openssl(NIST384p)
  1193. @pytest.mark.slow
  1194. @pytest.mark.skipif(
  1195. "secp521r1" not in OPENSSL_SUPPORTED_CURVES,
  1196. reason="system openssl does not support secp521r1",
  1197. )
  1198. def test_to_openssl_nist521p(self):
  1199. self.do_test_to_openssl(NIST521p)
  1200. @pytest.mark.slow
  1201. @pytest.mark.skipif(
  1202. "secp256k1" not in OPENSSL_SUPPORTED_CURVES,
  1203. reason="system openssl does not support secp256k1",
  1204. )
  1205. def test_to_openssl_secp256k1(self):
  1206. self.do_test_to_openssl(SECP256k1)
  1207. @pytest.mark.slow
  1208. @pytest.mark.skipif(
  1209. "brainpoolP160r1" not in OPENSSL_SUPPORTED_CURVES,
  1210. reason="system openssl does not support brainpoolP160r1",
  1211. )
  1212. def test_to_openssl_brainpoolp160r1(self):
  1213. self.do_test_to_openssl(BRAINPOOLP160r1)
  1214. @pytest.mark.slow
  1215. @pytest.mark.skipif(
  1216. "brainpoolP192r1" not in OPENSSL_SUPPORTED_CURVES,
  1217. reason="system openssl does not support brainpoolP192r1",
  1218. )
  1219. def test_to_openssl_brainpoolp192r1(self):
  1220. self.do_test_to_openssl(BRAINPOOLP192r1)
  1221. @pytest.mark.slow
  1222. @pytest.mark.skipif(
  1223. "brainpoolP224r1" not in OPENSSL_SUPPORTED_CURVES,
  1224. reason="system openssl does not support brainpoolP224r1",
  1225. )
  1226. def test_to_openssl_brainpoolp224r1(self):
  1227. self.do_test_to_openssl(BRAINPOOLP224r1)
  1228. @pytest.mark.slow
  1229. @pytest.mark.skipif(
  1230. "brainpoolP256r1" not in OPENSSL_SUPPORTED_CURVES,
  1231. reason="system openssl does not support brainpoolP256r1",
  1232. )
  1233. def test_to_openssl_brainpoolp256r1(self):
  1234. self.do_test_to_openssl(BRAINPOOLP256r1)
  1235. @pytest.mark.slow
  1236. @pytest.mark.skipif(
  1237. "brainpoolP320r1" not in OPENSSL_SUPPORTED_CURVES,
  1238. reason="system openssl does not support brainpoolP320r1",
  1239. )
  1240. def test_to_openssl_brainpoolp320r1(self):
  1241. self.do_test_to_openssl(BRAINPOOLP320r1)
  1242. @pytest.mark.slow
  1243. @pytest.mark.skipif(
  1244. "brainpoolP384r1" not in OPENSSL_SUPPORTED_CURVES,
  1245. reason="system openssl does not support brainpoolP384r1",
  1246. )
  1247. def test_to_openssl_brainpoolp384r1(self):
  1248. self.do_test_to_openssl(BRAINPOOLP384r1)
  1249. @pytest.mark.slow
  1250. @pytest.mark.skipif(
  1251. "brainpoolP512r1" not in OPENSSL_SUPPORTED_CURVES,
  1252. reason="system openssl does not support brainpoolP512r1",
  1253. )
  1254. def test_to_openssl_brainpoolp512r1(self):
  1255. self.do_test_to_openssl(BRAINPOOLP512r1)
  1256. @pytest.mark.slow
  1257. @pytest.mark.skipif(
  1258. "brainpoolP160t1" not in OPENSSL_SUPPORTED_CURVES,
  1259. reason="system openssl does not support brainpoolP160t1",
  1260. )
  1261. def test_to_openssl_brainpoolp160t1(self):
  1262. self.do_test_to_openssl(BRAINPOOLP160t1)
  1263. @pytest.mark.slow
  1264. @pytest.mark.skipif(
  1265. "brainpoolP192t1" not in OPENSSL_SUPPORTED_CURVES,
  1266. reason="system openssl does not support brainpoolP192t1",
  1267. )
  1268. def test_to_openssl_brainpoolp192t1(self):
  1269. self.do_test_to_openssl(BRAINPOOLP192t1)
  1270. @pytest.mark.slow
  1271. @pytest.mark.skipif(
  1272. "brainpoolP224t1" not in OPENSSL_SUPPORTED_CURVES,
  1273. reason="system openssl does not support brainpoolP224t1",
  1274. )
  1275. def test_to_openssl_brainpoolp224t1(self):
  1276. self.do_test_to_openssl(BRAINPOOLP224t1)
  1277. @pytest.mark.slow
  1278. @pytest.mark.skipif(
  1279. "brainpoolP256t1" not in OPENSSL_SUPPORTED_CURVES,
  1280. reason="system openssl does not support brainpoolP256t1",
  1281. )
  1282. def test_to_openssl_brainpoolp256t1(self):
  1283. self.do_test_to_openssl(BRAINPOOLP256t1)
  1284. @pytest.mark.slow
  1285. @pytest.mark.skipif(
  1286. "brainpoolP320t1" not in OPENSSL_SUPPORTED_CURVES,
  1287. reason="system openssl does not support brainpoolP320t1",
  1288. )
  1289. def test_to_openssl_brainpoolp320t1(self):
  1290. self.do_test_to_openssl(BRAINPOOLP320t1)
  1291. @pytest.mark.slow
  1292. @pytest.mark.skipif(
  1293. "brainpoolP384t1" not in OPENSSL_SUPPORTED_CURVES,
  1294. reason="system openssl does not support brainpoolP384t1",
  1295. )
  1296. def test_to_openssl_brainpoolp384t1(self):
  1297. self.do_test_to_openssl(BRAINPOOLP384t1)
  1298. @pytest.mark.slow
  1299. @pytest.mark.skipif(
  1300. "brainpoolP512t1" not in OPENSSL_SUPPORTED_CURVES,
  1301. reason="system openssl does not support brainpoolP512t1",
  1302. )
  1303. def test_to_openssl_brainpoolp512t1(self):
  1304. self.do_test_to_openssl(BRAINPOOLP512t1)
  1305. def do_test_to_openssl(self, curve, hash_name="SHA1"):
  1306. curvename = curve.openssl_name
  1307. assert curvename
  1308. # Python: create sk, vk, sign.
  1309. # OpenSSL: read vk(4), checksig(6), read sk(2), sign, check
  1310. mdarg = self.get_openssl_messagedigest_arg(hash_name)
  1311. if os.path.isdir("t"): # pragma: no cover
  1312. shutil.rmtree("t")
  1313. os.mkdir("t")
  1314. sk = SigningKey.generate(curve=curve)
  1315. vk = sk.get_verifying_key()
  1316. data = b"data"
  1317. with open("t/pubkey.der", "wb") as e:
  1318. e.write(vk.to_der()) # 4
  1319. with open("t/pubkey.pem", "wb") as e:
  1320. e.write(vk.to_pem()) # 4
  1321. sig_der = sk.sign(
  1322. data,
  1323. hashfunc=partial(hashlib.new, hash_name),
  1324. sigencode=sigencode_der,
  1325. )
  1326. with open("t/data.sig", "wb") as e:
  1327. e.write(sig_der) # 6
  1328. with open("t/data.txt", "wb") as e:
  1329. e.write(data)
  1330. with open("t/baddata.txt", "wb") as e:
  1331. e.write(data + b"corrupt")
  1332. self.assertRaises(
  1333. SubprocessError,
  1334. run_openssl,
  1335. "dgst %s -verify t/pubkey.der -keyform DER -signature t/data.sig t/baddata.txt"
  1336. % mdarg,
  1337. )
  1338. run_openssl(
  1339. "dgst %s -verify t/pubkey.der -keyform DER -signature t/data.sig t/data.txt"
  1340. % mdarg
  1341. )
  1342. with open("t/privkey.pem", "wb") as e:
  1343. e.write(sk.to_pem()) # 2
  1344. run_openssl(
  1345. "dgst %s -sign t/privkey.pem -out t/data.sig2 t/data.txt" % mdarg
  1346. )
  1347. run_openssl(
  1348. "dgst %s -verify t/pubkey.pem -signature t/data.sig2 t/data.txt"
  1349. % mdarg
  1350. )
  1351. with open("t/privkey-explicit.pem", "wb") as e:
  1352. e.write(sk.to_pem(curve_parameters_encoding="explicit"))
  1353. run_openssl(
  1354. "dgst %s -sign t/privkey-explicit.pem -out t/data.sig2 t/data.txt"
  1355. % mdarg
  1356. )
  1357. run_openssl(
  1358. "dgst %s -verify t/pubkey.pem -signature t/data.sig2 t/data.txt"
  1359. % mdarg
  1360. )
  1361. with open("t/privkey-p8.pem", "wb") as e:
  1362. e.write(sk.to_pem(format="pkcs8"))
  1363. run_openssl(
  1364. "dgst %s -sign t/privkey-p8.pem -out t/data.sig3 t/data.txt"
  1365. % mdarg
  1366. )
  1367. run_openssl(
  1368. "dgst %s -verify t/pubkey.pem -signature t/data.sig3 t/data.txt"
  1369. % mdarg
  1370. )
  1371. with open("t/privkey-p8-explicit.pem", "wb") as e:
  1372. e.write(
  1373. sk.to_pem(format="pkcs8", curve_parameters_encoding="explicit")
  1374. )
  1375. run_openssl(
  1376. "dgst %s -sign t/privkey-p8-explicit.pem -out t/data.sig3 t/data.txt"
  1377. % mdarg
  1378. )
  1379. run_openssl(
  1380. "dgst %s -verify t/pubkey.pem -signature t/data.sig3 t/data.txt"
  1381. % mdarg
  1382. )
  1383. OPENSSL_SUPPORTED_TYPES = set()
  1384. try:
  1385. if "-rawin" in run_openssl("pkeyutl -help"):
  1386. OPENSSL_SUPPORTED_TYPES = set( # pragma: no branch
  1387. c.lower()
  1388. for c in ("ED25519", "ED448")
  1389. if c in run_openssl("list -public-key-methods")
  1390. )
  1391. except SubprocessError: # pragma: no cover
  1392. pass
  1393. def do_eddsa_test_to_openssl(self, curve):
  1394. if os.path.isdir("t"):
  1395. shutil.rmtree("t")
  1396. os.mkdir("t")
  1397. sk = SigningKey.generate(curve=curve)
  1398. vk = sk.get_verifying_key()
  1399. data = b"data"
  1400. with open("t/pubkey.der", "wb") as e:
  1401. e.write(vk.to_der())
  1402. with open("t/pubkey.pem", "wb") as e:
  1403. e.write(vk.to_pem())
  1404. sig = sk.sign(data)
  1405. with open("t/data.sig", "wb") as e:
  1406. e.write(sig)
  1407. with open("t/data.txt", "wb") as e:
  1408. e.write(data)
  1409. with open("t/baddata.txt", "wb") as e:
  1410. e.write(data + b"corrupt")
  1411. with self.assertRaises(SubprocessError):
  1412. run_openssl(
  1413. "pkeyutl -verify -pubin -inkey t/pubkey.pem -rawin "
  1414. "-in t/baddata.txt -sigfile t/data.sig"
  1415. )
  1416. run_openssl(
  1417. "pkeyutl -verify -pubin -inkey t/pubkey.pem -rawin "
  1418. "-in t/data.txt -sigfile t/data.sig"
  1419. )
  1420. shutil.rmtree("t")
  1421. # in practice at least OpenSSL 3.0.0 is needed to make EdDSA signatures
  1422. # earlier versions support EdDSA only in X.509 certificates
  1423. @pytest.mark.slow
  1424. @pytest.mark.skipif(
  1425. "ed25519" not in OPENSSL_SUPPORTED_TYPES,
  1426. reason="system openssl does not support signing with Ed25519",
  1427. )
  1428. def test_to_openssl_ed25519(self):
  1429. return self.do_eddsa_test_to_openssl(Ed25519)
  1430. @pytest.mark.slow
  1431. @pytest.mark.skipif(
  1432. "ed448" not in OPENSSL_SUPPORTED_TYPES,
  1433. reason="system openssl does not support signing with Ed448",
  1434. )
  1435. def test_to_openssl_ed448(self):
  1436. return self.do_eddsa_test_to_openssl(Ed448)
  1437. def do_eddsa_test_from_openssl(self, curve):
  1438. curvename = curve.name
  1439. if os.path.isdir("t"):
  1440. shutil.rmtree("t")
  1441. os.mkdir("t")
  1442. data = b"data"
  1443. run_openssl(
  1444. "genpkey -algorithm {0} -outform PEM -out t/privkey.pem".format(
  1445. curvename
  1446. )
  1447. )
  1448. run_openssl(
  1449. "pkey -outform PEM -pubout -in t/privkey.pem -out t/pubkey.pem"
  1450. )
  1451. with open("t/data.txt", "wb") as e:
  1452. e.write(data)
  1453. run_openssl(
  1454. "pkeyutl -sign -inkey t/privkey.pem "
  1455. "-rawin -in t/data.txt -out t/data.sig"
  1456. )
  1457. with open("t/data.sig", "rb") as e:
  1458. sig = e.read()
  1459. with open("t/pubkey.pem", "rb") as e:
  1460. vk = VerifyingKey.from_pem(e.read())
  1461. self.assertIs(vk.curve, curve)
  1462. vk.verify(sig, data)
  1463. shutil.rmtree("t")
  1464. @pytest.mark.slow
  1465. @pytest.mark.skipif(
  1466. "ed25519" not in OPENSSL_SUPPORTED_TYPES,
  1467. reason="system openssl does not support signing with Ed25519",
  1468. )
  1469. def test_from_openssl_ed25519(self):
  1470. return self.do_eddsa_test_from_openssl(Ed25519)
  1471. @pytest.mark.slow
  1472. @pytest.mark.skipif(
  1473. "ed448" not in OPENSSL_SUPPORTED_TYPES,
  1474. reason="system openssl does not support signing with Ed448",
  1475. )
  1476. def test_from_openssl_ed448(self):
  1477. return self.do_eddsa_test_from_openssl(Ed448)
  1478. class TooSmallCurve(unittest.TestCase):
  1479. OPENSSL_SUPPORTED_CURVES = set(
  1480. c.split(":")[0].strip()
  1481. for c in run_openssl("ecparam -list_curves").split("\n")
  1482. )
  1483. @pytest.mark.skipif(
  1484. "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
  1485. reason="system openssl does not support prime192v1",
  1486. )
  1487. def test_sign_too_small_curve_dont_allow_truncate_raises(self):
  1488. sk = SigningKey.generate(curve=NIST192p)
  1489. data = b"data"
  1490. with self.assertRaises(BadDigestError):
  1491. sk.sign(
  1492. data,
  1493. hashfunc=partial(hashlib.new, "SHA256"),
  1494. sigencode=sigencode_der,
  1495. allow_truncate=False,
  1496. )
  1497. @pytest.mark.skipif(
  1498. "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
  1499. reason="system openssl does not support prime192v1",
  1500. )
  1501. def test_verify_too_small_curve_dont_allow_truncate_raises(self):
  1502. sk = SigningKey.generate(curve=NIST192p)
  1503. vk = sk.get_verifying_key()
  1504. data = b"data"
  1505. sig_der = sk.sign(
  1506. data,
  1507. hashfunc=partial(hashlib.new, "SHA256"),
  1508. sigencode=sigencode_der,
  1509. allow_truncate=True,
  1510. )
  1511. with self.assertRaises(BadDigestError):
  1512. vk.verify(
  1513. sig_der,
  1514. data,
  1515. hashfunc=partial(hashlib.new, "SHA256"),
  1516. sigdecode=sigdecode_der,
  1517. allow_truncate=False,
  1518. )
  1519. class DER(unittest.TestCase):
  1520. def test_integer(self):
  1521. self.assertEqual(der.encode_integer(0), b"\x02\x01\x00")
  1522. self.assertEqual(der.encode_integer(1), b"\x02\x01\x01")
  1523. self.assertEqual(der.encode_integer(127), b"\x02\x01\x7f")
  1524. self.assertEqual(der.encode_integer(128), b"\x02\x02\x00\x80")
  1525. self.assertEqual(der.encode_integer(256), b"\x02\x02\x01\x00")
  1526. # self.assertEqual(der.encode_integer(-1), b"\x02\x01\xff")
  1527. def s(n):
  1528. return der.remove_integer(der.encode_integer(n) + b"junk")
  1529. self.assertEqual(s(0), (0, b"junk"))
  1530. self.assertEqual(s(1), (1, b"junk"))
  1531. self.assertEqual(s(127), (127, b"junk"))
  1532. self.assertEqual(s(128), (128, b"junk"))
  1533. self.assertEqual(s(256), (256, b"junk"))
  1534. self.assertEqual(
  1535. s(1234567890123456789012345678901234567890),
  1536. (1234567890123456789012345678901234567890, b"junk"),
  1537. )
  1538. def test_number(self):
  1539. self.assertEqual(der.encode_number(0), b"\x00")
  1540. self.assertEqual(der.encode_number(127), b"\x7f")
  1541. self.assertEqual(der.encode_number(128), b"\x81\x00")
  1542. self.assertEqual(der.encode_number(3 * 128 + 7), b"\x83\x07")
  1543. # self.assertEqual(der.read_number("\x81\x9b" + "more"), (155, 2))
  1544. # self.assertEqual(der.encode_number(155), b"\x81\x9b")
  1545. for n in (0, 1, 2, 127, 128, 3 * 128 + 7, 840, 10045): # , 155):
  1546. x = der.encode_number(n) + b"more"
  1547. n1, llen = der.read_number(x)
  1548. self.assertEqual(n1, n)
  1549. self.assertEqual(x[llen:], b"more")
  1550. def test_length(self):
  1551. self.assertEqual(der.encode_length(0), b"\x00")
  1552. self.assertEqual(der.encode_length(127), b"\x7f")
  1553. self.assertEqual(der.encode_length(128), b"\x81\x80")
  1554. self.assertEqual(der.encode_length(255), b"\x81\xff")
  1555. self.assertEqual(der.encode_length(256), b"\x82\x01\x00")
  1556. self.assertEqual(der.encode_length(3 * 256 + 7), b"\x82\x03\x07")
  1557. self.assertEqual(der.read_length(b"\x81\x9b" + b"more"), (155, 2))
  1558. self.assertEqual(der.encode_length(155), b"\x81\x9b")
  1559. for n in (0, 1, 2, 127, 128, 255, 256, 3 * 256 + 7, 155):
  1560. x = der.encode_length(n) + b"more"
  1561. n1, llen = der.read_length(x)
  1562. self.assertEqual(n1, n)
  1563. self.assertEqual(x[llen:], b"more")
  1564. def test_sequence(self):
  1565. x = der.encode_sequence(b"ABC", b"DEF") + b"GHI"
  1566. self.assertEqual(x, b"\x30\x06ABCDEFGHI")
  1567. x1, rest = der.remove_sequence(x)
  1568. self.assertEqual(x1, b"ABCDEF")
  1569. self.assertEqual(rest, b"GHI")
  1570. def test_constructed(self):
  1571. x = der.encode_constructed(0, NIST224p.encoded_oid)
  1572. self.assertEqual(hexlify(x), b"a007" + b"06052b81040021")
  1573. x = der.encode_constructed(1, unhexlify(b"0102030a0b0c"))
  1574. self.assertEqual(hexlify(x), b"a106" + b"0102030a0b0c")
  1575. class Util(unittest.TestCase):
  1576. @pytest.mark.slow
  1577. def test_trytryagain(self):
  1578. tta = util.randrange_from_seed__trytryagain
  1579. for i in range(1000):
  1580. seed = "seed-%d" % i
  1581. for order in (
  1582. 2**8 - 2,
  1583. 2**8 - 1,
  1584. 2**8,
  1585. 2**8 + 1,
  1586. 2**8 + 2,
  1587. 2**16 - 1,
  1588. 2**16 + 1,
  1589. ):
  1590. n = tta(seed, order)
  1591. self.assertTrue(1 <= n < order, (1, n, order))
  1592. # this trytryagain *does* provide long-term stability
  1593. self.assertEqual(
  1594. ("%x" % (tta("seed", NIST224p.order))).encode(),
  1595. b"6fa59d73bf0446ae8743cf748fc5ac11d5585a90356417e97155c3bc",
  1596. )
  1597. def test_trytryagain_single(self):
  1598. tta = util.randrange_from_seed__trytryagain
  1599. order = 2**8 - 2
  1600. seed = b"text"
  1601. n = tta(seed, order)
  1602. # known issue: https://github.com/warner/python-ecdsa/issues/221
  1603. if sys.version_info < (3, 0): # pragma: no branch
  1604. self.assertEqual(n, 228)
  1605. else: # pragma: no branch
  1606. self.assertEqual(n, 18)
  1607. @settings(**HYP_SETTINGS)
  1608. @given(st.integers(min_value=0, max_value=10**200))
  1609. def test_randrange(self, i):
  1610. # util.randrange does not provide long-term stability: we might
  1611. # change the algorithm in the future.
  1612. entropy = util.PRNG("seed-%d" % i)
  1613. for order in (
  1614. 2**8 - 2,
  1615. 2**8 - 1,
  1616. 2**8,
  1617. 2**16 - 1,
  1618. 2**16 + 1,
  1619. ):
  1620. # that oddball 2**16+1 takes half our runtime
  1621. n = util.randrange(order, entropy=entropy)
  1622. self.assertTrue(1 <= n < order, (1, n, order))
  1623. def OFF_test_prove_uniformity(self): # pragma: no cover
  1624. order = 2**8 - 2
  1625. counts = dict([(i, 0) for i in range(1, order)])
  1626. assert 0 not in counts
  1627. assert order not in counts
  1628. for i in range(1000000):
  1629. seed = "seed-%d" % i
  1630. n = util.randrange_from_seed__trytryagain(seed, order)
  1631. counts[n] += 1
  1632. # this technique should use the full range
  1633. self.assertTrue(counts[order - 1])
  1634. for i in range(1, order):
  1635. print("%3d: %s" % (i, "*" * (counts[i] // 100)))
  1636. class RFC6979(unittest.TestCase):
  1637. # https://tools.ietf.org/html/rfc6979#appendix-A.1
  1638. def _do(self, generator, secexp, hsh, hash_func, expected):
  1639. actual = rfc6979.generate_k(generator.order(), secexp, hash_func, hsh)
  1640. self.assertEqual(expected, actual)
  1641. def test_SECP256k1(self):
  1642. """RFC doesn't contain test vectors for SECP256k1 used in bitcoin.
  1643. This vector has been computed by Golang reference implementation instead."""
  1644. self._do(
  1645. generator=SECP256k1.generator,
  1646. secexp=int("9d0219792467d7d37b4d43298a7d0c05", 16),
  1647. hsh=hashlib.sha256(b"sample").digest(),
  1648. hash_func=hashlib.sha256,
  1649. expected=int(
  1650. "8fa1f95d514760e498f28957b824ee6ec39ed64826ff4fecc2b5739ec45b91cd",
  1651. 16,
  1652. ),
  1653. )
  1654. def test_SECP256k1_2(self):
  1655. self._do(
  1656. generator=SECP256k1.generator,
  1657. secexp=int(
  1658. "cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50",
  1659. 16,
  1660. ),
  1661. hsh=hashlib.sha256(b"sample").digest(),
  1662. hash_func=hashlib.sha256,
  1663. expected=int(
  1664. "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3",
  1665. 16,
  1666. ),
  1667. )
  1668. def test_SECP256k1_3(self):
  1669. self._do(
  1670. generator=SECP256k1.generator,
  1671. secexp=0x1,
  1672. hsh=hashlib.sha256(b"Satoshi Nakamoto").digest(),
  1673. hash_func=hashlib.sha256,
  1674. expected=0x8F8A276C19F4149656B280621E358CCE24F5F52542772691EE69063B74F15D15,
  1675. )
  1676. def test_SECP256k1_4(self):
  1677. self._do(
  1678. generator=SECP256k1.generator,
  1679. secexp=0x1,
  1680. hsh=hashlib.sha256(
  1681. b"All those moments will be lost in time, like tears in rain. Time to die..."
  1682. ).digest(),
  1683. hash_func=hashlib.sha256,
  1684. expected=0x38AA22D72376B4DBC472E06C3BA403EE0A394DA63FC58D88686C611ABA98D6B3,
  1685. )
  1686. def test_SECP256k1_5(self):
  1687. self._do(
  1688. generator=SECP256k1.generator,
  1689. secexp=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140,
  1690. hsh=hashlib.sha256(b"Satoshi Nakamoto").digest(),
  1691. hash_func=hashlib.sha256,
  1692. expected=0x33A19B60E25FB6F4435AF53A3D42D493644827367E6453928554F43E49AA6F90,
  1693. )
  1694. def test_SECP256k1_6(self):
  1695. self._do(
  1696. generator=SECP256k1.generator,
  1697. secexp=0xF8B8AF8CE3C7CCA5E300D33939540C10D45CE001B8F252BFBC57BA0342904181,
  1698. hsh=hashlib.sha256(b"Alan Turing").digest(),
  1699. hash_func=hashlib.sha256,
  1700. expected=0x525A82B70E67874398067543FD84C83D30C175FDC45FDEEE082FE13B1D7CFDF1,
  1701. )
  1702. def test_1(self):
  1703. # Basic example of the RFC, it also tests 'try-try-again' from Step H of rfc6979
  1704. self._do(
  1705. generator=Point(
  1706. None,
  1707. 0,
  1708. 0,
  1709. int("4000000000000000000020108A2E0CC0D99F8A5EF", 16),
  1710. ),
  1711. secexp=int("09A4D6792295A7F730FC3F2B49CBC0F62E862272F", 16),
  1712. hsh=unhexlify(
  1713. b"AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF"
  1714. ),
  1715. hash_func=hashlib.sha256,
  1716. expected=int("23AF4074C90A02B3FE61D286D5C87F425E6BDD81B", 16),
  1717. )
  1718. def test_2(self):
  1719. self._do(
  1720. generator=NIST192p.generator,
  1721. secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  1722. hsh=hashlib.sha1(b"sample").digest(),
  1723. hash_func=hashlib.sha1,
  1724. expected=int(
  1725. "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", 16
  1726. ),
  1727. )
  1728. def test_3(self):
  1729. self._do(
  1730. generator=NIST192p.generator,
  1731. secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  1732. hsh=hashlib.sha256(b"sample").digest(),
  1733. hash_func=hashlib.sha256,
  1734. expected=int(
  1735. "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", 16
  1736. ),
  1737. )
  1738. def test_4(self):
  1739. self._do(
  1740. generator=NIST192p.generator,
  1741. secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  1742. hsh=hashlib.sha512(b"sample").digest(),
  1743. hash_func=hashlib.sha512,
  1744. expected=int(
  1745. "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", 16
  1746. ),
  1747. )
  1748. def test_5(self):
  1749. self._do(
  1750. generator=NIST192p.generator,
  1751. secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  1752. hsh=hashlib.sha1(b"test").digest(),
  1753. hash_func=hashlib.sha1,
  1754. expected=int(
  1755. "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", 16
  1756. ),
  1757. )
  1758. def test_6(self):
  1759. self._do(
  1760. generator=NIST192p.generator,
  1761. secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  1762. hsh=hashlib.sha256(b"test").digest(),
  1763. hash_func=hashlib.sha256,
  1764. expected=int(
  1765. "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", 16
  1766. ),
  1767. )
  1768. def test_7(self):
  1769. self._do(
  1770. generator=NIST192p.generator,
  1771. secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  1772. hsh=hashlib.sha512(b"test").digest(),
  1773. hash_func=hashlib.sha512,
  1774. expected=int(
  1775. "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", 16
  1776. ),
  1777. )
  1778. def test_8(self):
  1779. self._do(
  1780. generator=NIST521p.generator,
  1781. secexp=int(
  1782. "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
  1783. 16,
  1784. ),
  1785. hsh=hashlib.sha1(b"sample").digest(),
  1786. hash_func=hashlib.sha1,
  1787. expected=int(
  1788. "089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9",
  1789. 16,
  1790. ),
  1791. )
  1792. def test_9(self):
  1793. self._do(
  1794. generator=NIST521p.generator,
  1795. secexp=int(
  1796. "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
  1797. 16,
  1798. ),
  1799. hsh=hashlib.sha256(b"sample").digest(),
  1800. hash_func=hashlib.sha256,
  1801. expected=int(
  1802. "0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0",
  1803. 16,
  1804. ),
  1805. )
  1806. def test_10(self):
  1807. self._do(
  1808. generator=NIST521p.generator,
  1809. secexp=int(
  1810. "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
  1811. 16,
  1812. ),
  1813. hsh=hashlib.sha512(b"test").digest(),
  1814. hash_func=hashlib.sha512,
  1815. expected=int(
  1816. "16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D",
  1817. 16,
  1818. ),
  1819. )
  1820. class ECDH(unittest.TestCase):
  1821. def _do(self, curve, generator, dA, x_qA, y_qA, dB, x_qB, y_qB, x_Z, y_Z):
  1822. qA = dA * generator
  1823. qB = dB * generator
  1824. Z = dA * qB
  1825. self.assertEqual(Point(curve, x_qA, y_qA), qA)
  1826. self.assertEqual(Point(curve, x_qB, y_qB), qB)
  1827. self.assertTrue(
  1828. (dA * qB)
  1829. == (dA * dB * generator)
  1830. == (dB * dA * generator)
  1831. == (dB * qA)
  1832. )
  1833. self.assertEqual(Point(curve, x_Z, y_Z), Z)
  1834. class RFC6932(ECDH):
  1835. # https://tools.ietf.org/html/rfc6932#appendix-A.1
  1836. def test_brainpoolP224r1(self):
  1837. self._do(
  1838. curve=curve_brainpoolp224r1,
  1839. generator=BRAINPOOLP224r1.generator,
  1840. dA=int(
  1841. "7C4B7A2C8A4BAD1FBB7D79CC0955DB7C6A4660CA64CC4778159B495E", 16
  1842. ),
  1843. x_qA=int(
  1844. "B104A67A6F6E85E14EC1825E1539E8ECDBBF584922367DD88C6BDCF2", 16
  1845. ),
  1846. y_qA=int(
  1847. "46D782E7FDB5F60CD8404301AC5949C58EDB26BC68BA07695B750A94", 16
  1848. ),
  1849. dB=int(
  1850. "63976D4AAE6CD0F6DD18DEFEF55D96569D0507C03E74D6486FFA28FB", 16
  1851. ),
  1852. x_qB=int(
  1853. "2A97089A9296147B71B21A4B574E1278245B536F14D8C2B9D07A874E", 16
  1854. ),
  1855. y_qB=int(
  1856. "9B900D7C77A709A797276B8CA1BA61BB95B546FC29F862E44D59D25B", 16
  1857. ),
  1858. x_Z=int(
  1859. "312DFD98783F9FB77B9704945A73BEB6DCCBE3B65D0F967DCAB574EB", 16
  1860. ),
  1861. y_Z=int(
  1862. "6F800811D64114B1C48C621AB3357CF93F496E4238696A2A012B3C98", 16
  1863. ),
  1864. )
  1865. def test_brainpoolP256r1(self):
  1866. self._do(
  1867. curve=curve_brainpoolp256r1,
  1868. generator=BRAINPOOLP256r1.generator,
  1869. dA=int(
  1870. "041EB8B1E2BC681BCE8E39963B2E9FC415B05283313DD1A8BCC055F11AE"
  1871. "49699",
  1872. 16,
  1873. ),
  1874. x_qA=int(
  1875. "78028496B5ECAAB3C8B6C12E45DB1E02C9E4D26B4113BC4F015F60C5C"
  1876. "CC0D206",
  1877. 16,
  1878. ),
  1879. y_qA=int(
  1880. "A2AE1762A3831C1D20F03F8D1E3C0C39AFE6F09B4D44BBE80CD100987"
  1881. "B05F92B",
  1882. 16,
  1883. ),
  1884. dB=int(
  1885. "06F5240EACDB9837BC96D48274C8AA834B6C87BA9CC3EEDD81F99A16B8D"
  1886. "804D3",
  1887. 16,
  1888. ),
  1889. x_qB=int(
  1890. "8E07E219BA588916C5B06AA30A2F464C2F2ACFC1610A3BE2FB240B635"
  1891. "341F0DB",
  1892. 16,
  1893. ),
  1894. y_qB=int(
  1895. "148EA1D7D1E7E54B9555B6C9AC90629C18B63BEE5D7AA6949EBBF47B2"
  1896. "4FDE40D",
  1897. 16,
  1898. ),
  1899. x_Z=int(
  1900. "05E940915549E9F6A4A75693716E37466ABA79B4BF2919877A16DD2CC2"
  1901. "E23708",
  1902. 16,
  1903. ),
  1904. y_Z=int(
  1905. "6BC23B6702BC5A019438CEEA107DAAD8B94232FFBBC350F3B137628FE6"
  1906. "FD134C",
  1907. 16,
  1908. ),
  1909. )
  1910. @pytest.mark.slow
  1911. def test_brainpoolP384r1(self):
  1912. self._do(
  1913. curve=curve_brainpoolp384r1,
  1914. generator=BRAINPOOLP384r1.generator,
  1915. dA=int(
  1916. "014EC0755B78594BA47FB0A56F6173045B4331E74BA1A6F47322E70D79D"
  1917. "828D97E095884CA72B73FDABD5910DF0FA76A",
  1918. 16,
  1919. ),
  1920. x_qA=int(
  1921. "45CB26E4384DAF6FB776885307B9A38B7AD1B5C692E0C32F012533277"
  1922. "8F3B8D3F50CA358099B30DEB5EE69A95C058B4E",
  1923. 16,
  1924. ),
  1925. y_qA=int(
  1926. "8173A1C54AFFA7E781D0E1E1D12C0DC2B74F4DF58E4A4E3AF7026C5D3"
  1927. "2DC530A2CD89C859BB4B4B768497F49AB8CC859",
  1928. 16,
  1929. ),
  1930. dB=int(
  1931. "6B461CB79BD0EA519A87D6828815D8CE7CD9B3CAA0B5A8262CBCD550A01"
  1932. "5C90095B976F3529957506E1224A861711D54",
  1933. 16,
  1934. ),
  1935. x_qB=int(
  1936. "01BF92A92EE4BE8DED1A911125C209B03F99E3161CFCC986DC7711383"
  1937. "FC30AF9CE28CA3386D59E2C8D72CE1E7B4666E8",
  1938. 16,
  1939. ),
  1940. y_qB=int(
  1941. "3289C4A3A4FEE035E39BDB885D509D224A142FF9FBCC5CFE5CCBB3026"
  1942. "8EE47487ED8044858D31D848F7A95C635A347AC",
  1943. 16,
  1944. ),
  1945. x_Z=int(
  1946. "04CC4FF3DCCCB07AF24E0ACC529955B36D7C807772B92FCBE48F3AFE9A"
  1947. "2F370A1F98D3FA73FD0C0747C632E12F1423EC",
  1948. 16,
  1949. ),
  1950. y_Z=int(
  1951. "7F465F90BD69AFB8F828A214EB9716D66ABC59F17AF7C75EE7F1DE22AB"
  1952. "5D05085F5A01A9382D05BF72D96698FE3FF64E",
  1953. 16,
  1954. ),
  1955. )
  1956. @pytest.mark.slow
  1957. def test_brainpoolP512r1(self):
  1958. self._do(
  1959. curve=curve_brainpoolp512r1,
  1960. generator=BRAINPOOLP512r1.generator,
  1961. dA=int(
  1962. "636B6BE0482A6C1C41AA7AE7B245E983392DB94CECEA2660A379CFE1595"
  1963. "59E357581825391175FC195D28BAC0CF03A7841A383B95C262B98378287"
  1964. "4CCE6FE333",
  1965. 16,
  1966. ),
  1967. x_qA=int(
  1968. "0562E68B9AF7CBFD5565C6B16883B777FF11C199161ECC427A39D17EC"
  1969. "2166499389571D6A994977C56AD8252658BA8A1B72AE42F4FB7532151"
  1970. "AFC3EF0971CCDA",
  1971. 16,
  1972. ),
  1973. y_qA=int(
  1974. "A7CA2D8191E21776A89860AFBC1F582FAA308D551C1DC6133AF9F9C3C"
  1975. "AD59998D70079548140B90B1F311AFB378AA81F51B275B2BE6B7DEE97"
  1976. "8EFC7343EA642E",
  1977. 16,
  1978. ),
  1979. dB=int(
  1980. "0AF4E7F6D52EDD52907BB8DBAB3992A0BB696EC10DF11892FF205B66D38"
  1981. "1ECE72314E6A6EA079CEA06961DBA5AE6422EF2E9EE803A1F236FB96A17"
  1982. "99B86E5C8B",
  1983. 16,
  1984. ),
  1985. x_qB=int(
  1986. "5A7954E32663DFF11AE24712D87419F26B708AC2B92877D6BFEE2BFC4"
  1987. "3714D89BBDB6D24D807BBD3AEB7F0C325F862E8BADE4F74636B97EAAC"
  1988. "E739E11720D323",
  1989. 16,
  1990. ),
  1991. y_qB=int(
  1992. "96D14621A9283A1BED84DE8DD64836B2C0758B11441179DC0C54C0D49"
  1993. "A47C03807D171DD544B72CAAEF7B7CE01C7753E2CAD1A861ECA55A719"
  1994. "54EE1BA35E04BE",
  1995. 16,
  1996. ),
  1997. x_Z=int(
  1998. "1EE8321A4BBF93B9CF8921AB209850EC9B7066D1984EF08C2BB7232362"
  1999. "08AC8F1A483E79461A00E0D5F6921CE9D360502F85C812BEDEE23AC5B2"
  2000. "10E5811B191E",
  2001. 16,
  2002. ),
  2003. y_Z=int(
  2004. "2632095B7B936174B41FD2FAF369B1D18DCADEED7E410A7E251F083109"
  2005. "7C50D02CFED02607B6A2D5ADB4C0006008562208631875B58B54ECDA5A"
  2006. "4F9FE9EAABA6",
  2007. 16,
  2008. ),
  2009. )
  2010. class RFC7027(ECDH):
  2011. # https://tools.ietf.org/html/rfc7027#appendix-A
  2012. def test_brainpoolP256r1(self):
  2013. self._do(
  2014. curve=curve_brainpoolp256r1,
  2015. generator=BRAINPOOLP256r1.generator,
  2016. dA=int(
  2017. "81DB1EE100150FF2EA338D708271BE38300CB54241D79950F77B0630398"
  2018. "04F1D",
  2019. 16,
  2020. ),
  2021. x_qA=int(
  2022. "44106E913F92BC02A1705D9953A8414DB95E1AAA49E81D9E85F929A8E"
  2023. "3100BE5",
  2024. 16,
  2025. ),
  2026. y_qA=int(
  2027. "8AB4846F11CACCB73CE49CBDD120F5A900A69FD32C272223F789EF10E"
  2028. "B089BDC",
  2029. 16,
  2030. ),
  2031. dB=int(
  2032. "55E40BC41E37E3E2AD25C3C6654511FFA8474A91A0032087593852D3E7D"
  2033. "76BD3",
  2034. 16,
  2035. ),
  2036. x_qB=int(
  2037. "8D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F"
  2038. "1B39F7B",
  2039. 16,
  2040. ),
  2041. y_qB=int(
  2042. "990C57520812BE512641E47034832106BC7D3E8DD0E4C7F1136D70065"
  2043. "47CEC6A",
  2044. 16,
  2045. ),
  2046. x_Z=int(
  2047. "89AFC39D41D3B327814B80940B042590F96556EC91E6AE7939BCE31F3A"
  2048. "18BF2B",
  2049. 16,
  2050. ),
  2051. y_Z=int(
  2052. "49C27868F4ECA2179BFD7D59B1E3BF34C1DBDE61AE12931648F43E5963"
  2053. "2504DE",
  2054. 16,
  2055. ),
  2056. )
  2057. @pytest.mark.slow
  2058. def test_brainpoolP384r1(self):
  2059. self._do(
  2060. curve=curve_brainpoolp384r1,
  2061. generator=BRAINPOOLP384r1.generator,
  2062. dA=int(
  2063. "1E20F5E048A5886F1F157C74E91BDE2B98C8B52D58E5003D57053FC4B0B"
  2064. "D65D6F15EB5D1EE1610DF870795143627D042",
  2065. 16,
  2066. ),
  2067. x_qA=int(
  2068. "68B665DD91C195800650CDD363C625F4E742E8134667B767B1B476793"
  2069. "588F885AB698C852D4A6E77A252D6380FCAF068",
  2070. 16,
  2071. ),
  2072. y_qA=int(
  2073. "55BC91A39C9EC01DEE36017B7D673A931236D2F1F5C83942D049E3FA2"
  2074. "0607493E0D038FF2FD30C2AB67D15C85F7FAA59",
  2075. 16,
  2076. ),
  2077. dB=int(
  2078. "032640BC6003C59260F7250C3DB58CE647F98E1260ACCE4ACDA3DD869F7"
  2079. "4E01F8BA5E0324309DB6A9831497ABAC96670",
  2080. 16,
  2081. ),
  2082. x_qB=int(
  2083. "4D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D"
  2084. "19DC8CE6AD18E404B15738B2086DF37E71D1EB4",
  2085. 16,
  2086. ),
  2087. y_qB=int(
  2088. "62D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A42E"
  2089. "9185329B5B275903D192F8D4E1F32FE9CC78C48",
  2090. 16,
  2091. ),
  2092. x_Z=int(
  2093. "0BD9D3A7EA0B3D519D09D8E48D0785FB744A6B355E6304BC51C229FBBC"
  2094. "E239BBADF6403715C35D4FB2A5444F575D4F42",
  2095. 16,
  2096. ),
  2097. y_Z=int(
  2098. "0DF213417EBE4D8E40A5F76F66C56470C489A3478D146DECF6DF0D94BA"
  2099. "E9E598157290F8756066975F1DB34B2324B7BD",
  2100. 16,
  2101. ),
  2102. )
  2103. @pytest.mark.slow
  2104. def test_brainpoolP512r1(self):
  2105. self._do(
  2106. curve=curve_brainpoolp512r1,
  2107. generator=BRAINPOOLP512r1.generator,
  2108. dA=int(
  2109. "16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD8"
  2110. "7BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764C"
  2111. "AD57665422",
  2112. 16,
  2113. ),
  2114. x_qA=int(
  2115. "0A420517E406AAC0ACDCE90FCD71487718D3B953EFD7FBEC5F7F27E28"
  2116. "C6149999397E91E029E06457DB2D3E640668B392C2A7E737A7F0BF044"
  2117. "36D11640FD09FD",
  2118. 16,
  2119. ),
  2120. y_qA=int(
  2121. "72E6882E8DB28AAD36237CD25D580DB23783961C8DC52DFA2EC138AD4"
  2122. "72A0FCEF3887CF62B623B2A87DE5C588301EA3E5FC269B373B60724F5"
  2123. "E82A6AD147FDE7",
  2124. 16,
  2125. ),
  2126. dB=int(
  2127. "230E18E1BCC88A362FA54E4EA3902009292F7F8033624FD471B5D8ACE49"
  2128. "D12CFABBC19963DAB8E2F1EBA00BFFB29E4D72D13F2224562F405CB8050"
  2129. "3666B25429",
  2130. 16,
  2131. ),
  2132. x_qB=int(
  2133. "9D45F66DE5D67E2E6DB6E93A59CE0BB48106097FF78A081DE781CDB31"
  2134. "FCE8CCBAAEA8DD4320C4119F1E9CD437A2EAB3731FA9668AB268D871D"
  2135. "EDA55A5473199F",
  2136. 16,
  2137. ),
  2138. y_qB=int(
  2139. "2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB"
  2140. "481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194"
  2141. "512B71876285FA",
  2142. 16,
  2143. ),
  2144. x_Z=int(
  2145. "A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226"
  2146. "244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1"
  2147. "454B21C4CD1F",
  2148. 16,
  2149. ),
  2150. y_Z=int(
  2151. "7DB71C3DEF63212841C463E881BDCF055523BD368240E6C3143BD8DEF8"
  2152. "B3B3223B95E0F53082FF5E412F4222537A43DF1C6D25729DDB51620A83"
  2153. "2BE6A26680A2",
  2154. 16,
  2155. ),
  2156. )
  2157. # https://tools.ietf.org/html/rfc4754#page-5
  2158. @pytest.mark.parametrize(
  2159. "w, gwx, gwy, k, msg, md, r, s, curve",
  2160. [
  2161. pytest.param(
  2162. "DC51D3866A15BACDE33D96F992FCA99DA7E6EF0934E7097559C27F1614C88A7F",
  2163. "2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970",
  2164. "6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D",
  2165. "9E56F509196784D963D1C0A401510EE7ADA3DCC5DEE04B154BF61AF1D5A6DECE",
  2166. b"abc",
  2167. hashlib.sha256,
  2168. "CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C",
  2169. "86FA3BB4E26CAD5BF90B7F81899256CE7594BB1EA0C89212748BFF3B3D5B0315",
  2170. NIST256p,
  2171. id="ECDSA-256",
  2172. ),
  2173. pytest.param(
  2174. "0BEB646634BA87735D77AE4809A0EBEA865535DE4C1E1DCB692E84708E81A5AF"
  2175. "62E528C38B2A81B35309668D73524D9F",
  2176. "96281BF8DD5E0525CA049C048D345D3082968D10FEDF5C5ACA0C64E6465A97EA"
  2177. "5CE10C9DFEC21797415710721F437922",
  2178. "447688BA94708EB6E2E4D59F6AB6D7EDFF9301D249FE49C33096655F5D502FAD"
  2179. "3D383B91C5E7EDAA2B714CC99D5743CA",
  2180. "B4B74E44D71A13D568003D7489908D564C7761E229C58CBFA18950096EB7463B"
  2181. "854D7FA992F934D927376285E63414FA",
  2182. b"abc",
  2183. hashlib.sha384,
  2184. "FB017B914E29149432D8BAC29A514640B46F53DDAB2C69948084E2930F1C8F7E"
  2185. "08E07C9C63F2D21A07DCB56A6AF56EB3",
  2186. "B263A1305E057F984D38726A1B46874109F417BCA112674C528262A40A629AF1"
  2187. "CBB9F516CE0FA7D2FF630863A00E8B9F",
  2188. NIST384p,
  2189. id="ECDSA-384",
  2190. ),
  2191. pytest.param(
  2192. "0065FDA3409451DCAB0A0EAD45495112A3D813C17BFD34BDF8C1209D7DF58491"
  2193. "20597779060A7FF9D704ADF78B570FFAD6F062E95C7E0C5D5481C5B153B48B37"
  2194. "5FA1",
  2195. "0151518F1AF0F563517EDD5485190DF95A4BF57B5CBA4CF2A9A3F6474725A35F"
  2196. "7AFE0A6DDEB8BEDBCD6A197E592D40188901CECD650699C9B5E456AEA5ADD190"
  2197. "52A8",
  2198. "006F3B142EA1BFFF7E2837AD44C9E4FF6D2D34C73184BBAD90026DD5E6E85317"
  2199. "D9DF45CAD7803C6C20035B2F3FF63AFF4E1BA64D1C077577DA3F4286C58F0AEA"
  2200. "E643",
  2201. "00C1C2B305419F5A41344D7E4359933D734096F556197A9B244342B8B62F46F9"
  2202. "373778F9DE6B6497B1EF825FF24F42F9B4A4BD7382CFC3378A540B1B7F0C1B95"
  2203. "6C2F",
  2204. b"abc",
  2205. hashlib.sha512,
  2206. "0154FD3836AF92D0DCA57DD5341D3053988534FDE8318FC6AAAAB68E2E6F4339"
  2207. "B19F2F281A7E0B22C269D93CF8794A9278880ED7DBB8D9362CAEACEE54432055"
  2208. "2251",
  2209. "017705A7030290D1CEB605A9A1BB03FF9CDD521E87A696EC926C8C10C8362DF4"
  2210. "975367101F67D1CF9BCCBF2F3D239534FA509E70AAC851AE01AAC68D62F86647"
  2211. "2660",
  2212. NIST521p,
  2213. id="ECDSA-521",
  2214. ),
  2215. ],
  2216. )
  2217. def test_RFC4754_vectors(w, gwx, gwy, k, msg, md, r, s, curve):
  2218. sk = SigningKey.from_string(unhexlify(w), curve)
  2219. vk = VerifyingKey.from_string(unhexlify(gwx + gwy), curve)
  2220. assert sk.verifying_key == vk
  2221. sig = sk.sign(msg, hashfunc=md, sigencode=sigencode_strings, k=int(k, 16))
  2222. assert sig == (unhexlify(r), unhexlify(s))
  2223. assert vk.verify(sig, msg, md, sigdecode_strings)