test_pyecdsa.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. from __future__ import with_statement, division
  2. import unittest
  3. import os
  4. import time
  5. import shutil
  6. import subprocess
  7. from binascii import hexlify, unhexlify
  8. from hashlib import sha1, sha256, sha512
  9. from .six import b, print_, binary_type
  10. from .keys import SigningKey, VerifyingKey
  11. from .keys import BadSignatureError
  12. from . import util
  13. from .util import sigencode_der, sigencode_strings
  14. from .util import sigdecode_der, sigdecode_strings
  15. from .curves import Curve, UnknownCurveError
  16. from .curves import NIST192p, NIST224p, NIST256p, NIST384p, NIST521p, SECP256k1
  17. from .ellipticcurve import Point
  18. from . import der
  19. from . import rfc6979
  20. class SubprocessError(Exception):
  21. pass
  22. def run_openssl(cmd):
  23. OPENSSL = "openssl"
  24. p = subprocess.Popen([OPENSSL] + cmd.split(),
  25. stdout=subprocess.PIPE,
  26. stderr=subprocess.STDOUT)
  27. stdout, ignored = p.communicate()
  28. if p.returncode != 0:
  29. raise SubprocessError("cmd '%s %s' failed: rc=%s, stdout/err was %s" %
  30. (OPENSSL, cmd, p.returncode, stdout))
  31. return stdout.decode()
  32. BENCH = False
  33. class ECDSA(unittest.TestCase):
  34. def test_basic(self):
  35. priv = SigningKey.generate()
  36. pub = priv.get_verifying_key()
  37. data = b("blahblah")
  38. sig = priv.sign(data)
  39. self.assertTrue(pub.verify(sig, data))
  40. self.assertRaises(BadSignatureError, pub.verify, sig, data+b("bad"))
  41. pub2 = VerifyingKey.from_string(pub.to_string())
  42. self.assertTrue(pub2.verify(sig, data))
  43. def test_deterministic(self):
  44. data = b("blahblah")
  45. secexp = int("9d0219792467d7d37b4d43298a7d0c05", 16)
  46. priv = SigningKey.from_secret_exponent(secexp, SECP256k1, sha256)
  47. pub = priv.get_verifying_key()
  48. k = rfc6979.generate_k(SECP256k1.generator, secexp, sha256, sha256(data).digest())
  49. sig1 = priv.sign(data, k=k)
  50. self.assertTrue(pub.verify(sig1, data))
  51. sig2 = priv.sign(data, k=k)
  52. self.assertTrue(pub.verify(sig2, data))
  53. sig3 = priv.sign_deterministic(data, sha256)
  54. self.assertTrue(pub.verify(sig3, data))
  55. self.assertEqual(sig1, sig2)
  56. self.assertEqual(sig1, sig3)
  57. def test_bad_usage(self):
  58. # sk=SigningKey() is wrong
  59. self.assertRaises(TypeError, SigningKey)
  60. self.assertRaises(TypeError, VerifyingKey)
  61. def test_lengths(self):
  62. default = NIST192p
  63. priv = SigningKey.generate()
  64. pub = priv.get_verifying_key()
  65. self.assertEqual(len(pub.to_string()), default.verifying_key_length)
  66. sig = priv.sign(b("data"))
  67. self.assertEqual(len(sig), default.signature_length)
  68. if BENCH:
  69. print_()
  70. for curve in (NIST192p, NIST224p, NIST256p, NIST384p, NIST521p):
  71. start = time.time()
  72. priv = SigningKey.generate(curve=curve)
  73. pub1 = priv.get_verifying_key()
  74. keygen_time = time.time() - start
  75. pub2 = VerifyingKey.from_string(pub1.to_string(), curve)
  76. self.assertEqual(pub1.to_string(), pub2.to_string())
  77. self.assertEqual(len(pub1.to_string()),
  78. curve.verifying_key_length)
  79. start = time.time()
  80. sig = priv.sign(b("data"))
  81. sign_time = time.time() - start
  82. self.assertEqual(len(sig), curve.signature_length)
  83. if BENCH:
  84. start = time.time()
  85. pub1.verify(sig, b("data"))
  86. verify_time = time.time() - start
  87. print_("%s: siglen=%d, keygen=%0.3fs, sign=%0.3f, verify=%0.3f" \
  88. % (curve.name, curve.signature_length,
  89. keygen_time, sign_time, verify_time))
  90. def test_serialize(self):
  91. seed = b("secret")
  92. curve = NIST192p
  93. secexp1 = util.randrange_from_seed__trytryagain(seed, curve.order)
  94. secexp2 = util.randrange_from_seed__trytryagain(seed, curve.order)
  95. self.assertEqual(secexp1, secexp2)
  96. priv1 = SigningKey.from_secret_exponent(secexp1, curve)
  97. priv2 = SigningKey.from_secret_exponent(secexp2, curve)
  98. self.assertEqual(hexlify(priv1.to_string()),
  99. hexlify(priv2.to_string()))
  100. self.assertEqual(priv1.to_pem(), priv2.to_pem())
  101. pub1 = priv1.get_verifying_key()
  102. pub2 = priv2.get_verifying_key()
  103. data = b("data")
  104. sig1 = priv1.sign(data)
  105. sig2 = priv2.sign(data)
  106. self.assertTrue(pub1.verify(sig1, data))
  107. self.assertTrue(pub2.verify(sig1, data))
  108. self.assertTrue(pub1.verify(sig2, data))
  109. self.assertTrue(pub2.verify(sig2, data))
  110. self.assertEqual(hexlify(pub1.to_string()),
  111. hexlify(pub2.to_string()))
  112. def test_nonrandom(self):
  113. s = b("all the entropy in the entire world, compressed into one line")
  114. def not_much_entropy(numbytes):
  115. return s[:numbytes]
  116. # we control the entropy source, these two keys should be identical:
  117. priv1 = SigningKey.generate(entropy=not_much_entropy)
  118. priv2 = SigningKey.generate(entropy=not_much_entropy)
  119. self.assertEqual(hexlify(priv1.get_verifying_key().to_string()),
  120. hexlify(priv2.get_verifying_key().to_string()))
  121. # likewise, signatures should be identical. Obviously you'd never
  122. # want to do this with keys you care about, because the secrecy of
  123. # the private key depends upon using different random numbers for
  124. # each signature
  125. sig1 = priv1.sign(b("data"), entropy=not_much_entropy)
  126. sig2 = priv2.sign(b("data"), entropy=not_much_entropy)
  127. self.assertEqual(hexlify(sig1), hexlify(sig2))
  128. def assertTruePrivkeysEqual(self, priv1, priv2):
  129. self.assertEqual(priv1.privkey.secret_multiplier,
  130. priv2.privkey.secret_multiplier)
  131. self.assertEqual(priv1.privkey.public_key.generator,
  132. priv2.privkey.public_key.generator)
  133. def failIfPrivkeysEqual(self, priv1, priv2):
  134. self.failIfEqual(priv1.privkey.secret_multiplier,
  135. priv2.privkey.secret_multiplier)
  136. def test_privkey_creation(self):
  137. s = b("all the entropy in the entire world, compressed into one line")
  138. def not_much_entropy(numbytes):
  139. return s[:numbytes]
  140. priv1 = SigningKey.generate()
  141. self.assertEqual(priv1.baselen, NIST192p.baselen)
  142. priv1 = SigningKey.generate(curve=NIST224p)
  143. self.assertEqual(priv1.baselen, NIST224p.baselen)
  144. priv1 = SigningKey.generate(entropy=not_much_entropy)
  145. self.assertEqual(priv1.baselen, NIST192p.baselen)
  146. priv2 = SigningKey.generate(entropy=not_much_entropy)
  147. self.assertEqual(priv2.baselen, NIST192p.baselen)
  148. self.assertTruePrivkeysEqual(priv1, priv2)
  149. priv1 = SigningKey.from_secret_exponent(secexp=3)
  150. self.assertEqual(priv1.baselen, NIST192p.baselen)
  151. priv2 = SigningKey.from_secret_exponent(secexp=3)
  152. self.assertTruePrivkeysEqual(priv1, priv2)
  153. priv1 = SigningKey.from_secret_exponent(secexp=4, curve=NIST224p)
  154. self.assertEqual(priv1.baselen, NIST224p.baselen)
  155. def test_privkey_strings(self):
  156. priv1 = SigningKey.generate()
  157. s1 = priv1.to_string()
  158. self.assertEqual(type(s1), binary_type)
  159. self.assertEqual(len(s1), NIST192p.baselen)
  160. priv2 = SigningKey.from_string(s1)
  161. self.assertTruePrivkeysEqual(priv1, priv2)
  162. s1 = priv1.to_pem()
  163. self.assertEqual(type(s1), binary_type)
  164. self.assertTrue(s1.startswith(b("-----BEGIN EC PRIVATE KEY-----")))
  165. self.assertTrue(s1.strip().endswith(b("-----END EC PRIVATE KEY-----")))
  166. priv2 = SigningKey.from_pem(s1)
  167. self.assertTruePrivkeysEqual(priv1, priv2)
  168. s1 = priv1.to_der()
  169. self.assertEqual(type(s1), binary_type)
  170. priv2 = SigningKey.from_der(s1)
  171. self.assertTruePrivkeysEqual(priv1, priv2)
  172. priv1 = SigningKey.generate(curve=NIST256p)
  173. s1 = priv1.to_pem()
  174. self.assertEqual(type(s1), binary_type)
  175. self.assertTrue(s1.startswith(b("-----BEGIN EC PRIVATE KEY-----")))
  176. self.assertTrue(s1.strip().endswith(b("-----END EC PRIVATE KEY-----")))
  177. priv2 = SigningKey.from_pem(s1)
  178. self.assertTruePrivkeysEqual(priv1, priv2)
  179. s1 = priv1.to_der()
  180. self.assertEqual(type(s1), binary_type)
  181. priv2 = SigningKey.from_der(s1)
  182. self.assertTruePrivkeysEqual(priv1, priv2)
  183. def assertTruePubkeysEqual(self, pub1, pub2):
  184. self.assertEqual(pub1.pubkey.point, pub2.pubkey.point)
  185. self.assertEqual(pub1.pubkey.generator, pub2.pubkey.generator)
  186. self.assertEqual(pub1.curve, pub2.curve)
  187. def test_pubkey_strings(self):
  188. priv1 = SigningKey.generate()
  189. pub1 = priv1.get_verifying_key()
  190. s1 = pub1.to_string()
  191. self.assertEqual(type(s1), binary_type)
  192. self.assertEqual(len(s1), NIST192p.verifying_key_length)
  193. pub2 = VerifyingKey.from_string(s1)
  194. self.assertTruePubkeysEqual(pub1, pub2)
  195. priv1 = SigningKey.generate(curve=NIST256p)
  196. pub1 = priv1.get_verifying_key()
  197. s1 = pub1.to_string()
  198. self.assertEqual(type(s1), binary_type)
  199. self.assertEqual(len(s1), NIST256p.verifying_key_length)
  200. pub2 = VerifyingKey.from_string(s1, curve=NIST256p)
  201. self.assertTruePubkeysEqual(pub1, pub2)
  202. pub1_der = pub1.to_der()
  203. self.assertEqual(type(pub1_der), binary_type)
  204. pub2 = VerifyingKey.from_der(pub1_der)
  205. self.assertTruePubkeysEqual(pub1, pub2)
  206. self.assertRaises(der.UnexpectedDER,
  207. VerifyingKey.from_der, pub1_der+b("junk"))
  208. badpub = VerifyingKey.from_der(pub1_der)
  209. class FakeGenerator:
  210. def order(self): return 123456789
  211. badcurve = Curve("unknown", None, FakeGenerator(), (1,2,3,4,5,6))
  212. badpub.curve = badcurve
  213. badder = badpub.to_der()
  214. self.assertRaises(UnknownCurveError, VerifyingKey.from_der, badder)
  215. pem = pub1.to_pem()
  216. self.assertEqual(type(pem), binary_type)
  217. self.assertTrue(pem.startswith(b("-----BEGIN PUBLIC KEY-----")), pem)
  218. self.assertTrue(pem.strip().endswith(b("-----END PUBLIC KEY-----")), pem)
  219. pub2 = VerifyingKey.from_pem(pem)
  220. self.assertTruePubkeysEqual(pub1, pub2)
  221. def test_signature_strings(self):
  222. priv1 = SigningKey.generate()
  223. pub1 = priv1.get_verifying_key()
  224. data = b("data")
  225. sig = priv1.sign(data)
  226. self.assertEqual(type(sig), binary_type)
  227. self.assertEqual(len(sig), NIST192p.signature_length)
  228. self.assertTrue(pub1.verify(sig, data))
  229. sig = priv1.sign(data, sigencode=sigencode_strings)
  230. self.assertEqual(type(sig), tuple)
  231. self.assertEqual(len(sig), 2)
  232. self.assertEqual(type(sig[0]), binary_type)
  233. self.assertEqual(type(sig[1]), binary_type)
  234. self.assertEqual(len(sig[0]), NIST192p.baselen)
  235. self.assertEqual(len(sig[1]), NIST192p.baselen)
  236. self.assertTrue(pub1.verify(sig, data, sigdecode=sigdecode_strings))
  237. sig_der = priv1.sign(data, sigencode=sigencode_der)
  238. self.assertEqual(type(sig_der), binary_type)
  239. self.assertTrue(pub1.verify(sig_der, data, sigdecode=sigdecode_der))
  240. def test_hashfunc(self):
  241. sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
  242. data = b("security level is 128 bits")
  243. sig = sk.sign(data)
  244. vk = VerifyingKey.from_string(sk.get_verifying_key().to_string(),
  245. curve=NIST256p, hashfunc=sha256)
  246. self.assertTrue(vk.verify(sig, data))
  247. sk2 = SigningKey.generate(curve=NIST256p)
  248. sig2 = sk2.sign(data, hashfunc=sha256)
  249. vk2 = VerifyingKey.from_string(sk2.get_verifying_key().to_string(),
  250. curve=NIST256p, hashfunc=sha256)
  251. self.assertTrue(vk2.verify(sig2, data))
  252. vk3 = VerifyingKey.from_string(sk.get_verifying_key().to_string(),
  253. curve=NIST256p)
  254. self.assertTrue(vk3.verify(sig, data, hashfunc=sha256))
  255. class OpenSSL(unittest.TestCase):
  256. # test interoperability with OpenSSL tools. Note that openssl's ECDSA
  257. # sign/verify arguments changed between 0.9.8 and 1.0.0: the early
  258. # versions require "-ecdsa-with-SHA1", the later versions want just
  259. # "-SHA1" (or to leave out that argument entirely, which means the
  260. # signature will use some default digest algorithm, probably determined
  261. # by the key, probably always SHA1).
  262. #
  263. # openssl ecparam -name secp224r1 -genkey -out privkey.pem
  264. # openssl ec -in privkey.pem -text -noout # get the priv/pub keys
  265. # openssl dgst -ecdsa-with-SHA1 -sign privkey.pem -out data.sig data.txt
  266. # openssl asn1parse -in data.sig -inform DER
  267. # data.sig is 64 bytes, probably 56b plus ASN1 overhead
  268. # openssl dgst -ecdsa-with-SHA1 -prverify privkey.pem -signature data.sig data.txt ; echo $?
  269. # openssl ec -in privkey.pem -pubout -out pubkey.pem
  270. # openssl ec -in privkey.pem -pubout -outform DER -out pubkey.der
  271. def get_openssl_messagedigest_arg(self):
  272. v = run_openssl("version")
  273. # e.g. "OpenSSL 1.0.0 29 Mar 2010", or "OpenSSL 1.0.0a 1 Jun 2010",
  274. # or "OpenSSL 0.9.8o 01 Jun 2010"
  275. vs = v.split()[1].split(".")
  276. if vs >= ["1","0","0"]:
  277. return "-SHA1"
  278. else:
  279. return "-ecdsa-with-SHA1"
  280. # sk: 1:OpenSSL->python 2:python->OpenSSL
  281. # vk: 3:OpenSSL->python 4:python->OpenSSL
  282. # sig: 5:OpenSSL->python 6:python->OpenSSL
  283. def test_from_openssl_nist192p(self):
  284. return self.do_test_from_openssl(NIST192p, "prime192v1")
  285. def test_from_openssl_nist224p(self):
  286. return self.do_test_from_openssl(NIST224p, "secp224r1")
  287. def test_from_openssl_nist384p(self):
  288. return self.do_test_from_openssl(NIST384p, "secp384r1")
  289. def test_from_openssl_nist521p(self):
  290. return self.do_test_from_openssl(NIST521p, "secp521r1")
  291. def do_test_from_openssl(self, curve, curvename):
  292. # OpenSSL: create sk, vk, sign.
  293. # Python: read vk(3), checksig(5), read sk(1), sign, check
  294. mdarg = self.get_openssl_messagedigest_arg()
  295. if os.path.isdir("t"):
  296. shutil.rmtree("t")
  297. os.mkdir("t")
  298. run_openssl("ecparam -name %s -genkey -out t/privkey.pem" % curvename)
  299. run_openssl("ec -in t/privkey.pem -pubout -out t/pubkey.pem")
  300. data = b("data")
  301. with open("t/data.txt","wb") as e: e.write(data)
  302. run_openssl("dgst %s -sign t/privkey.pem -out t/data.sig t/data.txt" % mdarg)
  303. run_openssl("dgst %s -verify t/pubkey.pem -signature t/data.sig t/data.txt" % mdarg)
  304. with open("t/pubkey.pem","rb") as e: pubkey_pem = e.read()
  305. vk = VerifyingKey.from_pem(pubkey_pem) # 3
  306. with open("t/data.sig","rb") as e: sig_der = e.read()
  307. self.assertTrue(vk.verify(sig_der, data, # 5
  308. hashfunc=sha1, sigdecode=sigdecode_der))
  309. with open("t/privkey.pem") as e: fp = e.read()
  310. sk = SigningKey.from_pem(fp) # 1
  311. sig = sk.sign(data)
  312. self.assertTrue(vk.verify(sig, data))
  313. def test_to_openssl_nist192p(self):
  314. self.do_test_to_openssl(NIST192p, "prime192v1")
  315. def test_to_openssl_nist224p(self):
  316. self.do_test_to_openssl(NIST224p, "secp224r1")
  317. def test_to_openssl_nist384p(self):
  318. self.do_test_to_openssl(NIST384p, "secp384r1")
  319. def test_to_openssl_nist521p(self):
  320. self.do_test_to_openssl(NIST521p, "secp521r1")
  321. def do_test_to_openssl(self, curve, curvename):
  322. # Python: create sk, vk, sign.
  323. # OpenSSL: read vk(4), checksig(6), read sk(2), sign, check
  324. mdarg = self.get_openssl_messagedigest_arg()
  325. if os.path.isdir("t"):
  326. shutil.rmtree("t")
  327. os.mkdir("t")
  328. sk = SigningKey.generate(curve=curve)
  329. vk = sk.get_verifying_key()
  330. data = b("data")
  331. with open("t/pubkey.der","wb") as e: e.write(vk.to_der()) # 4
  332. with open("t/pubkey.pem","wb") as e: e.write(vk.to_pem()) # 4
  333. sig_der = sk.sign(data, hashfunc=sha1, sigencode=sigencode_der)
  334. with open("t/data.sig","wb") as e: e.write(sig_der) # 6
  335. with open("t/data.txt","wb") as e: e.write(data)
  336. with open("t/baddata.txt","wb") as e: e.write(data+b("corrupt"))
  337. self.assertRaises(SubprocessError, run_openssl,
  338. "dgst %s -verify t/pubkey.der -keyform DER -signature t/data.sig t/baddata.txt" % mdarg)
  339. run_openssl("dgst %s -verify t/pubkey.der -keyform DER -signature t/data.sig t/data.txt" % mdarg)
  340. with open("t/privkey.pem","wb") as e: e.write(sk.to_pem()) # 2
  341. run_openssl("dgst %s -sign t/privkey.pem -out t/data.sig2 t/data.txt" % mdarg)
  342. run_openssl("dgst %s -verify t/pubkey.pem -signature t/data.sig2 t/data.txt" % mdarg)
  343. class DER(unittest.TestCase):
  344. def test_oids(self):
  345. oid_ecPublicKey = der.encode_oid(1, 2, 840, 10045, 2, 1)
  346. self.assertEqual(hexlify(oid_ecPublicKey), b("06072a8648ce3d0201"))
  347. self.assertEqual(hexlify(NIST224p.encoded_oid), b("06052b81040021"))
  348. self.assertEqual(hexlify(NIST256p.encoded_oid),
  349. b("06082a8648ce3d030107"))
  350. x = oid_ecPublicKey + b("more")
  351. x1, rest = der.remove_object(x)
  352. self.assertEqual(x1, (1, 2, 840, 10045, 2, 1))
  353. self.assertEqual(rest, b("more"))
  354. def test_integer(self):
  355. self.assertEqual(der.encode_integer(0), b("\x02\x01\x00"))
  356. self.assertEqual(der.encode_integer(1), b("\x02\x01\x01"))
  357. self.assertEqual(der.encode_integer(127), b("\x02\x01\x7f"))
  358. self.assertEqual(der.encode_integer(128), b("\x02\x02\x00\x80"))
  359. self.assertEqual(der.encode_integer(256), b("\x02\x02\x01\x00"))
  360. #self.assertEqual(der.encode_integer(-1), b("\x02\x01\xff"))
  361. def s(n): return der.remove_integer(der.encode_integer(n) + b("junk"))
  362. self.assertEqual(s(0), (0, b("junk")))
  363. self.assertEqual(s(1), (1, b("junk")))
  364. self.assertEqual(s(127), (127, b("junk")))
  365. self.assertEqual(s(128), (128, b("junk")))
  366. self.assertEqual(s(256), (256, b("junk")))
  367. self.assertEqual(s(1234567890123456789012345678901234567890),
  368. (1234567890123456789012345678901234567890,b("junk")))
  369. def test_number(self):
  370. self.assertEqual(der.encode_number(0), b("\x00"))
  371. self.assertEqual(der.encode_number(127), b("\x7f"))
  372. self.assertEqual(der.encode_number(128), b("\x81\x00"))
  373. self.assertEqual(der.encode_number(3*128+7), b("\x83\x07"))
  374. #self.assertEqual(der.read_number("\x81\x9b"+"more"), (155, 2))
  375. #self.assertEqual(der.encode_number(155), b("\x81\x9b"))
  376. for n in (0, 1, 2, 127, 128, 3*128+7, 840, 10045): #, 155):
  377. x = der.encode_number(n) + b("more")
  378. n1, llen = der.read_number(x)
  379. self.assertEqual(n1, n)
  380. self.assertEqual(x[llen:], b("more"))
  381. def test_length(self):
  382. self.assertEqual(der.encode_length(0), b("\x00"))
  383. self.assertEqual(der.encode_length(127), b("\x7f"))
  384. self.assertEqual(der.encode_length(128), b("\x81\x80"))
  385. self.assertEqual(der.encode_length(255), b("\x81\xff"))
  386. self.assertEqual(der.encode_length(256), b("\x82\x01\x00"))
  387. self.assertEqual(der.encode_length(3*256+7), b("\x82\x03\x07"))
  388. self.assertEqual(der.read_length(b("\x81\x9b")+b("more")), (155, 2))
  389. self.assertEqual(der.encode_length(155), b("\x81\x9b"))
  390. for n in (0, 1, 2, 127, 128, 255, 256, 3*256+7, 155):
  391. x = der.encode_length(n) + b("more")
  392. n1, llen = der.read_length(x)
  393. self.assertEqual(n1, n)
  394. self.assertEqual(x[llen:], b("more"))
  395. def test_sequence(self):
  396. x = der.encode_sequence(b("ABC"), b("DEF")) + b("GHI")
  397. self.assertEqual(x, b("\x30\x06ABCDEFGHI"))
  398. x1, rest = der.remove_sequence(x)
  399. self.assertEqual(x1, b("ABCDEF"))
  400. self.assertEqual(rest, b("GHI"))
  401. def test_constructed(self):
  402. x = der.encode_constructed(0, NIST224p.encoded_oid)
  403. self.assertEqual(hexlify(x), b("a007") + b("06052b81040021"))
  404. x = der.encode_constructed(1, unhexlify(b("0102030a0b0c")))
  405. self.assertEqual(hexlify(x), b("a106") + b("0102030a0b0c"))
  406. class Util(unittest.TestCase):
  407. def test_trytryagain(self):
  408. tta = util.randrange_from_seed__trytryagain
  409. for i in range(1000):
  410. seed = "seed-%d" % i
  411. for order in (2**8-2, 2**8-1, 2**8, 2**8+1, 2**8+2,
  412. 2**16-1, 2**16+1):
  413. n = tta(seed, order)
  414. self.assertTrue(1 <= n < order, (1, n, order))
  415. # this trytryagain *does* provide long-term stability
  416. self.assertEqual(("%x"%(tta("seed", NIST224p.order))).encode(),
  417. b("6fa59d73bf0446ae8743cf748fc5ac11d5585a90356417e97155c3bc"))
  418. def test_randrange(self):
  419. # util.randrange does not provide long-term stability: we might
  420. # change the algorithm in the future.
  421. for i in range(1000):
  422. entropy = util.PRNG("seed-%d" % i)
  423. for order in (2**8-2, 2**8-1, 2**8,
  424. 2**16-1, 2**16+1,
  425. ):
  426. # that oddball 2**16+1 takes half our runtime
  427. n = util.randrange(order, entropy=entropy)
  428. self.assertTrue(1 <= n < order, (1, n, order))
  429. def OFF_test_prove_uniformity(self):
  430. order = 2**8-2
  431. counts = dict([(i, 0) for i in range(1, order)])
  432. assert 0 not in counts
  433. assert order not in counts
  434. for i in range(1000000):
  435. seed = "seed-%d" % i
  436. n = util.randrange_from_seed__trytryagain(seed, order)
  437. counts[n] += 1
  438. # this technique should use the full range
  439. self.assertTrue(counts[order-1])
  440. for i in range(1, order):
  441. print_("%3d: %s" % (i, "*"*(counts[i]//100)))
  442. class RFC6979(unittest.TestCase):
  443. # https://tools.ietf.org/html/rfc6979#appendix-A.1
  444. def _do(self, generator, secexp, hsh, hash_func, expected):
  445. actual = rfc6979.generate_k(generator, secexp, hash_func, hsh)
  446. self.assertEqual(expected, actual)
  447. def test_SECP256k1(self):
  448. '''RFC doesn't contain test vectors for SECP256k1 used in bitcoin.
  449. This vector has been computed by Golang reference implementation instead.'''
  450. self._do(
  451. generator = SECP256k1.generator,
  452. secexp = int("9d0219792467d7d37b4d43298a7d0c05", 16),
  453. hsh = sha256(b("sample")).digest(),
  454. hash_func = sha256,
  455. expected = int("8fa1f95d514760e498f28957b824ee6ec39ed64826ff4fecc2b5739ec45b91cd", 16))
  456. def test_SECP256k1_2(self):
  457. self._do(
  458. generator=SECP256k1.generator,
  459. secexp=int("cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50", 16),
  460. hsh=sha256(b("sample")).digest(),
  461. hash_func=sha256,
  462. expected=int("2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3", 16))
  463. def test_SECP256k1_3(self):
  464. self._do(
  465. generator=SECP256k1.generator,
  466. secexp=0x1,
  467. hsh=sha256(b("Satoshi Nakamoto")).digest(),
  468. hash_func=sha256,
  469. expected=0x8F8A276C19F4149656B280621E358CCE24F5F52542772691EE69063B74F15D15)
  470. def test_SECP256k1_4(self):
  471. self._do(
  472. generator=SECP256k1.generator,
  473. secexp=0x1,
  474. hsh=sha256(b("All those moments will be lost in time, like tears in rain. Time to die...")).digest(),
  475. hash_func=sha256,
  476. expected=0x38AA22D72376B4DBC472E06C3BA403EE0A394DA63FC58D88686C611ABA98D6B3)
  477. def test_SECP256k1_5(self):
  478. self._do(
  479. generator=SECP256k1.generator,
  480. secexp=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140,
  481. hsh=sha256(b("Satoshi Nakamoto")).digest(),
  482. hash_func=sha256,
  483. expected=0x33A19B60E25FB6F4435AF53A3D42D493644827367E6453928554F43E49AA6F90)
  484. def test_SECP256k1_6(self):
  485. self._do(
  486. generator=SECP256k1.generator,
  487. secexp=0xf8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181,
  488. hsh=sha256(b("Alan Turing")).digest(),
  489. hash_func=sha256,
  490. expected=0x525A82B70E67874398067543FD84C83D30C175FDC45FDEEE082FE13B1D7CFDF1)
  491. def test_1(self):
  492. # Basic example of the RFC, it also tests 'try-try-again' from Step H of rfc6979
  493. self._do(
  494. generator = Point(None, 0, 0, int("4000000000000000000020108A2E0CC0D99F8A5EF", 16)),
  495. secexp = int("09A4D6792295A7F730FC3F2B49CBC0F62E862272F", 16),
  496. hsh = unhexlify(b("AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF")),
  497. hash_func = sha256,
  498. expected = int("23AF4074C90A02B3FE61D286D5C87F425E6BDD81B", 16))
  499. def test_2(self):
  500. self._do(
  501. generator=NIST192p.generator,
  502. secexp = int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  503. hsh = sha1(b("sample")).digest(),
  504. hash_func = sha1,
  505. expected = int("37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", 16))
  506. def test_3(self):
  507. self._do(
  508. generator=NIST192p.generator,
  509. secexp = int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  510. hsh = sha256(b("sample")).digest(),
  511. hash_func = sha256,
  512. expected = int("32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", 16))
  513. def test_4(self):
  514. self._do(
  515. generator=NIST192p.generator,
  516. secexp = int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  517. hsh = sha512(b("sample")).digest(),
  518. hash_func = sha512,
  519. expected = int("A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", 16))
  520. def test_5(self):
  521. self._do(
  522. generator=NIST192p.generator,
  523. secexp = int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  524. hsh = sha1(b("test")).digest(),
  525. hash_func = sha1,
  526. expected = int("D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", 16))
  527. def test_6(self):
  528. self._do(
  529. generator=NIST192p.generator,
  530. secexp = int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  531. hsh = sha256(b("test")).digest(),
  532. hash_func = sha256,
  533. expected = int("5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", 16))
  534. def test_7(self):
  535. self._do(
  536. generator=NIST192p.generator,
  537. secexp = int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
  538. hsh = sha512(b("test")).digest(),
  539. hash_func = sha512,
  540. expected = int("0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", 16))
  541. def test_8(self):
  542. self._do(
  543. generator=NIST521p.generator,
  544. secexp = int("0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538", 16),
  545. hsh = sha1(b("sample")).digest(),
  546. hash_func = sha1,
  547. expected = int("089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9", 16))
  548. def test_9(self):
  549. self._do(
  550. generator=NIST521p.generator,
  551. secexp = int("0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538", 16),
  552. hsh = sha256(b("sample")).digest(),
  553. hash_func = sha256,
  554. expected = int("0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0", 16))
  555. def test_10(self):
  556. self._do(
  557. generator=NIST521p.generator,
  558. secexp = int("0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538", 16),
  559. hsh = sha512(b("test")).digest(),
  560. hash_func = sha512,
  561. expected = int("16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D", 16))
  562. def __main__():
  563. unittest.main()
  564. if __name__ == "__main__":
  565. __main__()