test_import_ECC.py 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. # ===================================================================
  2. #
  3. # Copyright (c) 2015, Legrandin <helderijs@gmail.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions
  8. # are met:
  9. #
  10. # 1. Redistributions of source code must retain the above copyright
  11. # notice, this list of conditions and the following disclaimer.
  12. # 2. Redistributions in binary form must reproduce the above copyright
  13. # notice, this list of conditions and the following disclaimer in
  14. # the documentation and/or other materials provided with the
  15. # distribution.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. # POSSIBILITY OF SUCH DAMAGE.
  29. # ===================================================================
  30. import sys
  31. import unittest
  32. from binascii import unhexlify
  33. from tls.Crypto.SelfTest.st_common import list_test_cases
  34. from tls.Crypto.Util._file_system import pycryptodome_filename
  35. from tls.Crypto.Util.py3compat import bord, tostr
  36. from tls.Crypto.Util.number import bytes_to_long
  37. from tls.Crypto.Hash import SHAKE128
  38. from tls.Crypto.PublicKey import ECC
  39. def load_file(filename, mode="rb"):
  40. comps = [ "Crypto", "SelfTest", "PublicKey", "test_vectors", "ECC" ]
  41. with open(pycryptodome_filename(comps, filename), mode) as fd:
  42. return fd.read()
  43. def compact(lines):
  44. ext = b"".join(lines)
  45. return unhexlify(tostr(ext).replace(" ", "").replace(":", ""))
  46. def create_ref_keys_p256():
  47. key_len = 32
  48. key_lines = load_file("ecc_p256.txt").splitlines()
  49. private_key_d = bytes_to_long(compact(key_lines[2:5]))
  50. public_key_xy = compact(key_lines[6:11])
  51. assert bord(public_key_xy[0]) == 4 # Uncompressed
  52. public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
  53. public_key_y = bytes_to_long(public_key_xy[key_len+1:])
  54. return (ECC.construct(curve="P-256", d=private_key_d),
  55. ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y))
  56. def create_ref_keys_p384():
  57. key_len = 48
  58. key_lines = load_file("ecc_p384.txt").splitlines()
  59. private_key_d = bytes_to_long(compact(key_lines[2:6]))
  60. public_key_xy = compact(key_lines[7:14])
  61. assert bord(public_key_xy[0]) == 4 # Uncompressed
  62. public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
  63. public_key_y = bytes_to_long(public_key_xy[key_len+1:])
  64. return (ECC.construct(curve="P-384", d=private_key_d),
  65. ECC.construct(curve="P-384", point_x=public_key_x, point_y=public_key_y))
  66. def create_ref_keys_p521():
  67. key_len = 66
  68. key_lines = load_file("ecc_p521.txt").splitlines()
  69. private_key_d = bytes_to_long(compact(key_lines[2:7]))
  70. public_key_xy = compact(key_lines[8:17])
  71. assert bord(public_key_xy[0]) == 4 # Uncompressed
  72. public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
  73. public_key_y = bytes_to_long(public_key_xy[key_len+1:])
  74. return (ECC.construct(curve="P-521", d=private_key_d),
  75. ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y))
  76. # Create reference key pair
  77. # ref_private, ref_public = create_ref_keys_p521()
  78. def get_fixed_prng():
  79. return SHAKE128.new().update(b"SEED").read
  80. class TestImport(unittest.TestCase):
  81. def test_empty(self):
  82. self.assertRaises(ValueError, ECC.import_key, b"")
  83. class TestImport_P256(unittest.TestCase):
  84. ref_private, ref_public = create_ref_keys_p256()
  85. def test_import_public_der(self):
  86. key_file = load_file("ecc_p256_public.der")
  87. key = ECC._import_subjectPublicKeyInfo(key_file)
  88. self.assertEqual(self.ref_public, key)
  89. key = ECC._import_der(key_file, None)
  90. self.assertEqual(self.ref_public, key)
  91. key = ECC.import_key(key_file)
  92. self.assertEqual(self.ref_public, key)
  93. def test_import_private_der(self):
  94. key_file = load_file("ecc_p256_private.der")
  95. key = ECC._import_private_der(key_file, None)
  96. self.assertEqual(self.ref_private, key)
  97. key = ECC._import_der(key_file, None)
  98. self.assertEqual(self.ref_private, key)
  99. key = ECC.import_key(key_file)
  100. self.assertEqual(self.ref_private, key)
  101. def test_import_private_pkcs8_clear(self):
  102. key_file = load_file("ecc_p256_private_p8_clear.der")
  103. key = ECC._import_der(key_file, None)
  104. self.assertEqual(self.ref_private, key)
  105. key = ECC.import_key(key_file)
  106. self.assertEqual(self.ref_private, key)
  107. def test_import_private_pkcs8_in_pem_clear(self):
  108. key_file = load_file("ecc_p256_private_p8_clear.pem")
  109. key = ECC.import_key(key_file)
  110. self.assertEqual(self.ref_private, key)
  111. def test_import_private_pkcs8_encrypted_1(self):
  112. key_file = load_file("ecc_p256_private_p8.der")
  113. key = ECC._import_der(key_file, "secret")
  114. self.assertEqual(self.ref_private, key)
  115. key = ECC.import_key(key_file, "secret")
  116. self.assertEqual(self.ref_private, key)
  117. def test_import_private_pkcs8_encrypted_2(self):
  118. key_file = load_file("ecc_p256_private_p8.pem")
  119. key = ECC.import_key(key_file, "secret")
  120. self.assertEqual(self.ref_private, key)
  121. def test_import_x509_der(self):
  122. key_file = load_file("ecc_p256_x509.der")
  123. key = ECC._import_der(key_file, None)
  124. self.assertEqual(self.ref_public, key)
  125. key = ECC.import_key(key_file)
  126. self.assertEqual(self.ref_public, key)
  127. def test_import_public_pem(self):
  128. key_file = load_file("ecc_p256_public.pem")
  129. key = ECC.import_key(key_file)
  130. self.assertEqual(self.ref_public, key)
  131. def test_import_private_pem(self):
  132. key_file = load_file("ecc_p256_private.pem")
  133. key = ECC.import_key(key_file)
  134. self.assertEqual(self.ref_private, key)
  135. def test_import_private_pem_with_ecparams(self):
  136. if sys.version_info[:2] == (2, 6):
  137. return
  138. key_file = load_file("ecc_p256_private_ecparams.pem")
  139. key = ECC.import_key(key_file)
  140. # We just check if the import succeeds
  141. def test_import_private_pem_encrypted(self):
  142. for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm":
  143. key_file = load_file("ecc_p256_private_enc_%s.pem" % algo)
  144. key = ECC.import_key(key_file, "secret")
  145. self.assertEqual(self.ref_private, key)
  146. key = ECC.import_key(tostr(key_file), b"secret")
  147. self.assertEqual(self.ref_private, key)
  148. def test_import_x509_pem(self):
  149. key_file = load_file("ecc_p256_x509.pem")
  150. key = ECC.import_key(key_file)
  151. self.assertEqual(self.ref_public, key)
  152. def test_import_openssh_public(self):
  153. key_file = load_file("ecc_p256_public_openssh.txt")
  154. key = ECC._import_openssh_public(key_file)
  155. self.assertEqual(self.ref_public, key)
  156. key = ECC.import_key(key_file)
  157. self.assertEqual(self.ref_public, key)
  158. def test_import_openssh_private_clear(self):
  159. key_file = load_file("ecc_p256_private_openssh.pem")
  160. key_file_old = load_file("ecc_p256_private_openssh_old.pem")
  161. key = ECC.import_key(key_file)
  162. key_old = ECC.import_key(key_file_old)
  163. self.assertEqual(key, key_old)
  164. def test_import_openssh_private_password(self):
  165. key_file = load_file("ecc_p256_private_openssh_pwd.pem")
  166. key_file_old = load_file("ecc_p256_private_openssh_pwd_old.pem")
  167. key = ECC.import_key(key_file, b"password")
  168. key_old = ECC.import_key(key_file_old)
  169. self.assertEqual(key, key_old)
  170. class TestImport_P384(unittest.TestCase):
  171. ref_private, ref_public = create_ref_keys_p384()
  172. def test_import_public_der(self):
  173. key_file = load_file("ecc_p384_public.der")
  174. key = ECC._import_subjectPublicKeyInfo(key_file)
  175. self.assertEqual(self.ref_public, key)
  176. key = ECC._import_der(key_file, None)
  177. self.assertEqual(self.ref_public, key)
  178. key = ECC.import_key(key_file)
  179. self.assertEqual(self.ref_public, key)
  180. def test_import_private_der(self):
  181. key_file = load_file("ecc_p384_private.der")
  182. key = ECC._import_private_der(key_file, None)
  183. self.assertEqual(self.ref_private, key)
  184. key = ECC._import_der(key_file, None)
  185. self.assertEqual(self.ref_private, key)
  186. key = ECC.import_key(key_file)
  187. self.assertEqual(self.ref_private, key)
  188. def test_import_private_pkcs8_clear(self):
  189. key_file = load_file("ecc_p384_private_p8_clear.der")
  190. key = ECC._import_der(key_file, None)
  191. self.assertEqual(self.ref_private, key)
  192. key = ECC.import_key(key_file)
  193. self.assertEqual(self.ref_private, key)
  194. def test_import_private_pkcs8_in_pem_clear(self):
  195. key_file = load_file("ecc_p384_private_p8_clear.pem")
  196. key = ECC.import_key(key_file)
  197. self.assertEqual(self.ref_private, key)
  198. def test_import_private_pkcs8_encrypted_1(self):
  199. key_file = load_file("ecc_p384_private_p8.der")
  200. key = ECC._import_der(key_file, "secret")
  201. self.assertEqual(self.ref_private, key)
  202. key = ECC.import_key(key_file, "secret")
  203. self.assertEqual(self.ref_private, key)
  204. def test_import_private_pkcs8_encrypted_2(self):
  205. key_file = load_file("ecc_p384_private_p8.pem")
  206. key = ECC.import_key(key_file, "secret")
  207. self.assertEqual(self.ref_private, key)
  208. def test_import_x509_der(self):
  209. key_file = load_file("ecc_p384_x509.der")
  210. key = ECC._import_der(key_file, None)
  211. self.assertEqual(self.ref_public, key)
  212. key = ECC.import_key(key_file)
  213. self.assertEqual(self.ref_public, key)
  214. def test_import_public_pem(self):
  215. key_file = load_file("ecc_p384_public.pem")
  216. key = ECC.import_key(key_file)
  217. self.assertEqual(self.ref_public, key)
  218. def test_import_private_pem(self):
  219. key_file = load_file("ecc_p384_private.pem")
  220. key = ECC.import_key(key_file)
  221. self.assertEqual(self.ref_private, key)
  222. def test_import_private_pem_encrypted(self):
  223. for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm":
  224. key_file = load_file("ecc_p384_private_enc_%s.pem" % algo)
  225. key = ECC.import_key(key_file, "secret")
  226. self.assertEqual(self.ref_private, key)
  227. key = ECC.import_key(tostr(key_file), b"secret")
  228. self.assertEqual(self.ref_private, key)
  229. def test_import_x509_pem(self):
  230. key_file = load_file("ecc_p384_x509.pem")
  231. key = ECC.import_key(key_file)
  232. self.assertEqual(self.ref_public, key)
  233. def test_import_openssh_public(self):
  234. key_file = load_file("ecc_p384_public_openssh.txt")
  235. key = ECC._import_openssh_public(key_file)
  236. self.assertEqual(self.ref_public, key)
  237. key = ECC.import_key(key_file)
  238. self.assertEqual(self.ref_public, key)
  239. def test_import_openssh_private_clear(self):
  240. key_file = load_file("ecc_p384_private_openssh.pem")
  241. key_file_old = load_file("ecc_p384_private_openssh_old.pem")
  242. key = ECC.import_key(key_file)
  243. key_old = ECC.import_key(key_file_old)
  244. self.assertEqual(key, key_old)
  245. def test_import_openssh_private_password(self):
  246. key_file = load_file("ecc_p384_private_openssh_pwd.pem")
  247. key_file_old = load_file("ecc_p384_private_openssh_pwd_old.pem")
  248. key = ECC.import_key(key_file, b"password")
  249. key_old = ECC.import_key(key_file_old)
  250. self.assertEqual(key, key_old)
  251. class TestImport_P521(unittest.TestCase):
  252. ref_private, ref_public = create_ref_keys_p521()
  253. def test_import_public_der(self):
  254. key_file = load_file("ecc_p521_public.der")
  255. key = ECC._import_subjectPublicKeyInfo(key_file)
  256. self.assertEqual(self.ref_public, key)
  257. key = ECC._import_der(key_file, None)
  258. self.assertEqual(self.ref_public, key)
  259. key = ECC.import_key(key_file)
  260. self.assertEqual(self.ref_public, key)
  261. def test_import_private_der(self):
  262. key_file = load_file("ecc_p521_private.der")
  263. key = ECC._import_private_der(key_file, None)
  264. self.assertEqual(self.ref_private, key)
  265. key = ECC._import_der(key_file, None)
  266. self.assertEqual(self.ref_private, key)
  267. key = ECC.import_key(key_file)
  268. self.assertEqual(self.ref_private, key)
  269. def test_import_private_pkcs8_clear(self):
  270. key_file = load_file("ecc_p521_private_p8_clear.der")
  271. key = ECC._import_der(key_file, None)
  272. self.assertEqual(self.ref_private, key)
  273. key = ECC.import_key(key_file)
  274. self.assertEqual(self.ref_private, key)
  275. def test_import_private_pkcs8_in_pem_clear(self):
  276. key_file = load_file("ecc_p521_private_p8_clear.pem")
  277. key = ECC.import_key(key_file)
  278. self.assertEqual(self.ref_private, key)
  279. def test_import_private_pkcs8_encrypted_1(self):
  280. key_file = load_file("ecc_p521_private_p8.der")
  281. key = ECC._import_der(key_file, "secret")
  282. self.assertEqual(self.ref_private, key)
  283. key = ECC.import_key(key_file, "secret")
  284. self.assertEqual(self.ref_private, key)
  285. def test_import_private_pkcs8_encrypted_2(self):
  286. key_file = load_file("ecc_p521_private_p8.pem")
  287. key = ECC.import_key(key_file, "secret")
  288. self.assertEqual(self.ref_private, key)
  289. def test_import_x509_der(self):
  290. key_file = load_file("ecc_p521_x509.der")
  291. key = ECC._import_der(key_file, None)
  292. self.assertEqual(self.ref_public, key)
  293. key = ECC.import_key(key_file)
  294. self.assertEqual(self.ref_public, key)
  295. def test_import_public_pem(self):
  296. key_file = load_file("ecc_p521_public.pem")
  297. key = ECC.import_key(key_file)
  298. self.assertEqual(self.ref_public, key)
  299. def test_import_private_pem(self):
  300. key_file = load_file("ecc_p521_private.pem")
  301. key = ECC.import_key(key_file)
  302. self.assertEqual(self.ref_private, key)
  303. def test_import_private_pem_encrypted(self):
  304. for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm":
  305. key_file = load_file("ecc_p521_private_enc_%s.pem" % algo)
  306. key = ECC.import_key(key_file, "secret")
  307. self.assertEqual(self.ref_private, key)
  308. key = ECC.import_key(tostr(key_file), b"secret")
  309. self.assertEqual(self.ref_private, key)
  310. def test_import_x509_pem(self):
  311. key_file = load_file("ecc_p521_x509.pem")
  312. key = ECC.import_key(key_file)
  313. self.assertEqual(self.ref_public, key)
  314. def test_import_openssh_public(self):
  315. key_file = load_file("ecc_p521_public_openssh.txt")
  316. key = ECC._import_openssh_public(key_file)
  317. self.assertEqual(self.ref_public, key)
  318. key = ECC.import_key(key_file)
  319. self.assertEqual(self.ref_public, key)
  320. def test_import_openssh_private_clear(self):
  321. key_file = load_file("ecc_p521_private_openssh.pem")
  322. key_file_old = load_file("ecc_p521_private_openssh_old.pem")
  323. key = ECC.import_key(key_file)
  324. key_old = ECC.import_key(key_file_old)
  325. self.assertEqual(key, key_old)
  326. def test_import_openssh_private_password(self):
  327. key_file = load_file("ecc_p521_private_openssh_pwd.pem")
  328. key_file_old = load_file("ecc_p521_private_openssh_pwd_old.pem")
  329. key = ECC.import_key(key_file, b"password")
  330. key_old = ECC.import_key(key_file_old)
  331. self.assertEqual(key, key_old)
  332. class TestExport_P256(unittest.TestCase):
  333. ref_private, ref_public = create_ref_keys_p256()
  334. def test_export_public_der_uncompressed(self):
  335. key_file = load_file("ecc_p256_public.der")
  336. encoded = self.ref_public._export_subjectPublicKeyInfo(False)
  337. self.assertEqual(key_file, encoded)
  338. encoded = self.ref_public.export_key(format="DER")
  339. self.assertEqual(key_file, encoded)
  340. encoded = self.ref_public.export_key(format="DER", compress=False)
  341. self.assertEqual(key_file, encoded)
  342. def test_export_public_der_compressed(self):
  343. key_file = load_file("ecc_p256_public.der")
  344. pub_key = ECC.import_key(key_file)
  345. key_file_compressed = pub_key.export_key(format="DER", compress=True)
  346. key_file_compressed_ref = load_file("ecc_p256_public_compressed.der")
  347. self.assertEqual(key_file_compressed, key_file_compressed_ref)
  348. def test_export_private_der(self):
  349. key_file = load_file("ecc_p256_private.der")
  350. encoded = self.ref_private._export_private_der()
  351. self.assertEqual(key_file, encoded)
  352. # ---
  353. encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
  354. self.assertEqual(key_file, encoded)
  355. def test_export_private_pkcs8_clear(self):
  356. key_file = load_file("ecc_p256_private_p8_clear.der")
  357. encoded = self.ref_private._export_pkcs8()
  358. self.assertEqual(key_file, encoded)
  359. # ---
  360. encoded = self.ref_private.export_key(format="DER")
  361. self.assertEqual(key_file, encoded)
  362. def test_export_private_pkcs8_encrypted(self):
  363. encoded = self.ref_private._export_pkcs8(passphrase="secret",
  364. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  365. # This should prove that the output is password-protected
  366. self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None)
  367. decoded = ECC._import_pkcs8(encoded, "secret")
  368. self.assertEqual(self.ref_private, decoded)
  369. # ---
  370. encoded = self.ref_private.export_key(format="DER",
  371. passphrase="secret",
  372. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  373. decoded = ECC.import_key(encoded, "secret")
  374. self.assertEqual(self.ref_private, decoded)
  375. def test_export_public_pem_uncompressed(self):
  376. key_file = load_file("ecc_p256_public.pem", "rt").strip()
  377. encoded = self.ref_private._export_public_pem(False)
  378. self.assertEqual(key_file, encoded)
  379. # ---
  380. encoded = self.ref_public.export_key(format="PEM")
  381. self.assertEqual(key_file, encoded)
  382. encoded = self.ref_public.export_key(format="PEM", compress=False)
  383. self.assertEqual(key_file, encoded)
  384. def test_export_public_pem_compressed(self):
  385. key_file = load_file("ecc_p256_public.pem", "rt").strip()
  386. pub_key = ECC.import_key(key_file)
  387. key_file_compressed = pub_key.export_key(format="PEM", compress=True)
  388. key_file_compressed_ref = load_file("ecc_p256_public_compressed.pem", "rt").strip()
  389. self.assertEqual(key_file_compressed, key_file_compressed_ref)
  390. def test_export_private_pem_clear(self):
  391. key_file = load_file("ecc_p256_private.pem", "rt").strip()
  392. encoded = self.ref_private._export_private_pem(None)
  393. self.assertEqual(key_file, encoded)
  394. # ---
  395. encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
  396. self.assertEqual(key_file, encoded)
  397. def test_export_private_pem_encrypted(self):
  398. encoded = self.ref_private._export_private_pem(passphrase=b"secret")
  399. # This should prove that the output is password-protected
  400. self.assertRaises(ValueError, ECC.import_key, encoded)
  401. assert "EC PRIVATE KEY" in encoded
  402. decoded = ECC.import_key(encoded, "secret")
  403. self.assertEqual(self.ref_private, decoded)
  404. # ---
  405. encoded = self.ref_private.export_key(format="PEM",
  406. passphrase="secret",
  407. use_pkcs8=False)
  408. decoded = ECC.import_key(encoded, "secret")
  409. self.assertEqual(self.ref_private, decoded)
  410. def test_export_private_pkcs8_and_pem_1(self):
  411. # PKCS8 inside PEM with both unencrypted
  412. key_file = load_file("ecc_p256_private_p8_clear.pem", "rt").strip()
  413. encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
  414. self.assertEqual(key_file, encoded)
  415. # ---
  416. encoded = self.ref_private.export_key(format="PEM")
  417. self.assertEqual(key_file, encoded)
  418. def test_export_private_pkcs8_and_pem_2(self):
  419. # PKCS8 inside PEM with PKCS8 encryption
  420. encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret",
  421. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  422. # This should prove that the output is password-protected
  423. self.assertRaises(ValueError, ECC.import_key, encoded)
  424. assert "ENCRYPTED PRIVATE KEY" in encoded
  425. decoded = ECC.import_key(encoded, "secret")
  426. self.assertEqual(self.ref_private, decoded)
  427. # ---
  428. encoded = self.ref_private.export_key(format="PEM",
  429. passphrase="secret",
  430. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  431. decoded = ECC.import_key(encoded, "secret")
  432. self.assertEqual(self.ref_private, decoded)
  433. def test_export_openssh_uncompressed(self):
  434. key_file = load_file("ecc_p256_public_openssh.txt", "rt")
  435. encoded = self.ref_public._export_openssh(False)
  436. self.assertEquals(key_file, encoded)
  437. # ---
  438. encoded = self.ref_public.export_key(format="OpenSSH")
  439. self.assertEquals(key_file, encoded)
  440. encoded = self.ref_public.export_key(format="OpenSSH", compress=False)
  441. self.assertEquals(key_file, encoded)
  442. def test_export_openssh_compressed(self):
  443. key_file = load_file("ecc_p256_public_openssh.txt", "rt")
  444. pub_key = ECC.import_key(key_file)
  445. key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True)
  446. assert len(key_file) > len(key_file_compressed)
  447. self.assertEquals(pub_key, ECC.import_key(key_file_compressed))
  448. def test_prng(self):
  449. # Test that password-protected containers use the provided PRNG
  450. encoded1 = self.ref_private.export_key(format="PEM",
  451. passphrase="secret",
  452. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
  453. randfunc=get_fixed_prng())
  454. encoded2 = self.ref_private.export_key(format="PEM",
  455. passphrase="secret",
  456. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
  457. randfunc=get_fixed_prng())
  458. self.assertEquals(encoded1, encoded2)
  459. # ---
  460. encoded1 = self.ref_private.export_key(format="PEM",
  461. use_pkcs8=False,
  462. passphrase="secret",
  463. randfunc=get_fixed_prng())
  464. encoded2 = self.ref_private.export_key(format="PEM",
  465. use_pkcs8=False,
  466. passphrase="secret",
  467. randfunc=get_fixed_prng())
  468. self.assertEquals(encoded1, encoded2)
  469. def test_byte_or_string_passphrase(self):
  470. encoded1 = self.ref_private.export_key(format="PEM",
  471. use_pkcs8=False,
  472. passphrase="secret",
  473. randfunc=get_fixed_prng())
  474. encoded2 = self.ref_private.export_key(format="PEM",
  475. use_pkcs8=False,
  476. passphrase=b"secret",
  477. randfunc=get_fixed_prng())
  478. self.assertEquals(encoded1, encoded2)
  479. def test_error_params1(self):
  480. # Unknown format
  481. self.assertRaises(ValueError, self.ref_private.export_key, format="XXX")
  482. # Missing 'protection' parameter when PKCS#8 is used
  483. self.ref_private.export_key(format="PEM", passphrase="secret",
  484. use_pkcs8=False)
  485. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  486. passphrase="secret")
  487. # DER format but no PKCS#8
  488. self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
  489. passphrase="secret",
  490. use_pkcs8=False,
  491. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  492. # Incorrect parameters for public keys
  493. self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
  494. use_pkcs8=False)
  495. # Empty password
  496. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  497. passphrase="", use_pkcs8=False)
  498. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  499. passphrase="",
  500. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  501. # No private keys with OpenSSH
  502. self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH",
  503. passphrase="secret")
  504. def test_unsupported_curve(self):
  505. # openssl ecparam -name secp224r1 -genkey -noout -out strange-curve.pem -conv_form uncompressed
  506. curve = """-----BEGIN EC PRIVATE KEY-----
  507. MGgCAQEEHEi7xTHW+5oT8wgpjoEKV7uwMuY8rt2YUZe4j1SgBwYFK4EEACGhPAM6
  508. AATJgfOG+Bnki8robpNM8MtArji43GU9up4B0x9sVhqB+fZP+hXgV9ITN7YX4E/k
  509. gVnJp9EBND/tHQ==
  510. -----END EC PRIVATE KEY-----"""
  511. from tls.Crypto.PublicKey.ECC import UnsupportedEccFeature
  512. try:
  513. ECC.import_key(curve)
  514. except UnsupportedEccFeature as uef:
  515. assert("1.3.132.0.33" in str(uef))
  516. else:
  517. assert(False)
  518. def test_compressed_curve(self):
  519. # Compressed P-256 curve (Y-point is even)
  520. pem1 = """-----BEGIN EC PRIVATE KEY-----
  521. MFcCAQEEIHTuc09jC51xXomV6MVCDN+DpAAvSmaJWZPTEHM6D5H1oAoGCCqGSM49
  522. AwEHoSQDIgACWFuGbHe8yJ43rir7PMTE9w8vHz0BSpXHq90Xi7/s+a0=
  523. -----END EC PRIVATE KEY-----"""
  524. # Compressed P-256 curve (Y-point is odd)
  525. pem2 = """-----BEGIN EC PRIVATE KEY-----
  526. MFcCAQEEIFggiPN9SQP+FAPTCPp08fRUz7rHp2qNBRcBJ1DXhb3ZoAoGCCqGSM49
  527. AwEHoSQDIgADLpph1trTIlVfa8NJvlMUPyWvL+wP+pW3BJITUL/wj9A=
  528. -----END EC PRIVATE KEY-----"""
  529. key1 = ECC.import_key(pem1)
  530. low16 = int(key1.pointQ.y % 65536)
  531. self.assertEqual(low16, 0xA6FC)
  532. key2 = ECC.import_key(pem2)
  533. low16 = int(key2.pointQ.y % 65536)
  534. self.assertEqual(low16, 0x6E57)
  535. class TestExport_P384(unittest.TestCase):
  536. ref_private, ref_public = create_ref_keys_p384()
  537. def test_export_public_der_uncompressed(self):
  538. key_file = load_file("ecc_p384_public.der")
  539. encoded = self.ref_public._export_subjectPublicKeyInfo(False)
  540. self.assertEqual(key_file, encoded)
  541. encoded = self.ref_public.export_key(format="DER")
  542. self.assertEqual(key_file, encoded)
  543. encoded = self.ref_public.export_key(format="DER", compress=False)
  544. self.assertEqual(key_file, encoded)
  545. def test_export_public_der_compressed(self):
  546. key_file = load_file("ecc_p384_public.der")
  547. pub_key = ECC.import_key(key_file)
  548. key_file_compressed = pub_key.export_key(format="DER", compress=True)
  549. key_file_compressed_ref = load_file("ecc_p384_public_compressed.der")
  550. self.assertEqual(key_file_compressed, key_file_compressed_ref)
  551. def test_export_private_der(self):
  552. key_file = load_file("ecc_p384_private.der")
  553. encoded = self.ref_private._export_private_der()
  554. self.assertEqual(key_file, encoded)
  555. # ---
  556. encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
  557. self.assertEqual(key_file, encoded)
  558. def test_export_private_pkcs8_clear(self):
  559. key_file = load_file("ecc_p384_private_p8_clear.der")
  560. encoded = self.ref_private._export_pkcs8()
  561. self.assertEqual(key_file, encoded)
  562. # ---
  563. encoded = self.ref_private.export_key(format="DER")
  564. self.assertEqual(key_file, encoded)
  565. def test_export_private_pkcs8_encrypted(self):
  566. encoded = self.ref_private._export_pkcs8(passphrase="secret",
  567. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  568. # This should prove that the output is password-protected
  569. self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None)
  570. decoded = ECC._import_pkcs8(encoded, "secret")
  571. self.assertEqual(self.ref_private, decoded)
  572. # ---
  573. encoded = self.ref_private.export_key(format="DER",
  574. passphrase="secret",
  575. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  576. decoded = ECC.import_key(encoded, "secret")
  577. self.assertEqual(self.ref_private, decoded)
  578. def test_export_public_pem_uncompressed(self):
  579. key_file = load_file("ecc_p384_public.pem", "rt").strip()
  580. encoded = self.ref_private._export_public_pem(False)
  581. self.assertEqual(key_file, encoded)
  582. # ---
  583. encoded = self.ref_public.export_key(format="PEM")
  584. self.assertEqual(key_file, encoded)
  585. encoded = self.ref_public.export_key(format="PEM", compress=False)
  586. self.assertEqual(key_file, encoded)
  587. def test_export_public_pem_compressed(self):
  588. key_file = load_file("ecc_p384_public.pem", "rt").strip()
  589. pub_key = ECC.import_key(key_file)
  590. key_file_compressed = pub_key.export_key(format="PEM", compress=True)
  591. key_file_compressed_ref = load_file("ecc_p384_public_compressed.pem", "rt").strip()
  592. self.assertEqual(key_file_compressed, key_file_compressed_ref)
  593. def test_export_private_pem_clear(self):
  594. key_file = load_file("ecc_p384_private.pem", "rt").strip()
  595. encoded = self.ref_private._export_private_pem(None)
  596. self.assertEqual(key_file, encoded)
  597. # ---
  598. encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
  599. self.assertEqual(key_file, encoded)
  600. def test_export_private_pem_encrypted(self):
  601. encoded = self.ref_private._export_private_pem(passphrase=b"secret")
  602. # This should prove that the output is password-protected
  603. self.assertRaises(ValueError, ECC.import_key, encoded)
  604. assert "EC PRIVATE KEY" in encoded
  605. decoded = ECC.import_key(encoded, "secret")
  606. self.assertEqual(self.ref_private, decoded)
  607. # ---
  608. encoded = self.ref_private.export_key(format="PEM",
  609. passphrase="secret",
  610. use_pkcs8=False)
  611. decoded = ECC.import_key(encoded, "secret")
  612. self.assertEqual(self.ref_private, decoded)
  613. def test_export_private_pkcs8_and_pem_1(self):
  614. # PKCS8 inside PEM with both unencrypted
  615. key_file = load_file("ecc_p384_private_p8_clear.pem", "rt").strip()
  616. encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
  617. self.assertEqual(key_file, encoded)
  618. # ---
  619. encoded = self.ref_private.export_key(format="PEM")
  620. self.assertEqual(key_file, encoded)
  621. def test_export_private_pkcs8_and_pem_2(self):
  622. # PKCS8 inside PEM with PKCS8 encryption
  623. encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret",
  624. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  625. # This should prove that the output is password-protected
  626. self.assertRaises(ValueError, ECC.import_key, encoded)
  627. assert "ENCRYPTED PRIVATE KEY" in encoded
  628. decoded = ECC.import_key(encoded, "secret")
  629. self.assertEqual(self.ref_private, decoded)
  630. # ---
  631. encoded = self.ref_private.export_key(format="PEM",
  632. passphrase="secret",
  633. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  634. decoded = ECC.import_key(encoded, "secret")
  635. self.assertEqual(self.ref_private, decoded)
  636. def test_export_openssh_uncompressed(self):
  637. key_file = load_file("ecc_p384_public_openssh.txt", "rt")
  638. encoded = self.ref_public._export_openssh(False)
  639. self.assertEquals(key_file, encoded)
  640. # ---
  641. encoded = self.ref_public.export_key(format="OpenSSH")
  642. self.assertEquals(key_file, encoded)
  643. encoded = self.ref_public.export_key(format="OpenSSH", compress=False)
  644. self.assertEquals(key_file, encoded)
  645. def test_export_openssh_compressed(self):
  646. key_file = load_file("ecc_p384_public_openssh.txt", "rt")
  647. pub_key = ECC.import_key(key_file)
  648. key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True)
  649. assert len(key_file) > len(key_file_compressed)
  650. self.assertEquals(pub_key, ECC.import_key(key_file_compressed))
  651. def test_prng(self):
  652. # Test that password-protected containers use the provided PRNG
  653. encoded1 = self.ref_private.export_key(format="PEM",
  654. passphrase="secret",
  655. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
  656. randfunc=get_fixed_prng())
  657. encoded2 = self.ref_private.export_key(format="PEM",
  658. passphrase="secret",
  659. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
  660. randfunc=get_fixed_prng())
  661. self.assertEquals(encoded1, encoded2)
  662. # ---
  663. encoded1 = self.ref_private.export_key(format="PEM",
  664. use_pkcs8=False,
  665. passphrase="secret",
  666. randfunc=get_fixed_prng())
  667. encoded2 = self.ref_private.export_key(format="PEM",
  668. use_pkcs8=False,
  669. passphrase="secret",
  670. randfunc=get_fixed_prng())
  671. self.assertEquals(encoded1, encoded2)
  672. def test_byte_or_string_passphrase(self):
  673. encoded1 = self.ref_private.export_key(format="PEM",
  674. use_pkcs8=False,
  675. passphrase="secret",
  676. randfunc=get_fixed_prng())
  677. encoded2 = self.ref_private.export_key(format="PEM",
  678. use_pkcs8=False,
  679. passphrase=b"secret",
  680. randfunc=get_fixed_prng())
  681. self.assertEquals(encoded1, encoded2)
  682. def test_error_params1(self):
  683. # Unknown format
  684. self.assertRaises(ValueError, self.ref_private.export_key, format="XXX")
  685. # Missing 'protection' parameter when PKCS#8 is used
  686. self.ref_private.export_key(format="PEM", passphrase="secret",
  687. use_pkcs8=False)
  688. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  689. passphrase="secret")
  690. # DER format but no PKCS#8
  691. self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
  692. passphrase="secret",
  693. use_pkcs8=False,
  694. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  695. # Incorrect parameters for public keys
  696. self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
  697. use_pkcs8=False)
  698. # Empty password
  699. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  700. passphrase="", use_pkcs8=False)
  701. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  702. passphrase="",
  703. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  704. # No private keys with OpenSSH
  705. self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH",
  706. passphrase="secret")
  707. def test_compressed_curve(self):
  708. # Compressed P-384 curve (Y-point is even)
  709. # openssl ecparam -name secp384p1 -genkey -noout -conv_form compressed -out /tmp/a.pem
  710. # openssl ec -in /tmp/a.pem -text -noout
  711. pem1 = """-----BEGIN EC PRIVATE KEY-----
  712. MIGkAgEBBDAM0lEIhvXuekK2SWtdbgOcZtBaxa9TxfpO/GcDFZLCJ3JVXaTgwken
  713. QT+C+XLtD6WgBwYFK4EEACKhZANiAATs0kZMhFDu8DoBC21jrSDPyAUn4aXZ/DM4
  714. ylhDfWmb4LEbeszXceIzfhIUaaGs5y1xXaqf5KXTiAAYx2pKUzAAM9lcGUHCGKJG
  715. k4AgUmVJON29XoUilcFrzjDmuye3B6Q=
  716. -----END EC PRIVATE KEY-----"""
  717. # Compressed P-384 curve (Y-point is odd)
  718. pem2 = """-----BEGIN EC PRIVATE KEY-----
  719. MIGkAgEBBDDHPFTslYLltE16fHdSDTtE/2HTmd3M8mqy5MttAm4wZ833KXiGS9oe
  720. kFdx9sNV0KygBwYFK4EEACKhZANiAASLIE5RqVMtNhtBH/u/p/ifqOAlKnK/+RrQ
  721. YC46ZRsnKNayw3wATdPjgja7L/DSII3nZK0G6KOOVwJBznT/e+zudUJYhZKaBLRx
  722. /bgXyxUtYClOXxb1Y/5N7txLstYRyP0=
  723. -----END EC PRIVATE KEY-----"""
  724. key1 = ECC.import_key(pem1)
  725. low16 = int(key1.pointQ.y % 65536)
  726. self.assertEqual(low16, 0x07a4)
  727. key2 = ECC.import_key(pem2)
  728. low16 = int(key2.pointQ.y % 65536)
  729. self.assertEqual(low16, 0xc8fd)
  730. class TestExport_P521(unittest.TestCase):
  731. ref_private, ref_public = create_ref_keys_p521()
  732. def test_export_public_der_uncompressed(self):
  733. key_file = load_file("ecc_p521_public.der")
  734. encoded = self.ref_public._export_subjectPublicKeyInfo(False)
  735. self.assertEqual(key_file, encoded)
  736. encoded = self.ref_public.export_key(format="DER")
  737. self.assertEqual(key_file, encoded)
  738. encoded = self.ref_public.export_key(format="DER", compress=False)
  739. self.assertEqual(key_file, encoded)
  740. def test_export_public_der_compressed(self):
  741. key_file = load_file("ecc_p521_public.der")
  742. pub_key = ECC.import_key(key_file)
  743. key_file_compressed = pub_key.export_key(format="DER", compress=True)
  744. key_file_compressed_ref = load_file("ecc_p521_public_compressed.der")
  745. self.assertEqual(key_file_compressed, key_file_compressed_ref)
  746. def test_export_private_der(self):
  747. key_file = load_file("ecc_p521_private.der")
  748. encoded = self.ref_private._export_private_der()
  749. self.assertEqual(key_file, encoded)
  750. # ---
  751. encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
  752. self.assertEqual(key_file, encoded)
  753. def test_export_private_pkcs8_clear(self):
  754. key_file = load_file("ecc_p521_private_p8_clear.der")
  755. encoded = self.ref_private._export_pkcs8()
  756. self.assertEqual(key_file, encoded)
  757. # ---
  758. encoded = self.ref_private.export_key(format="DER")
  759. self.assertEqual(key_file, encoded)
  760. def test_export_private_pkcs8_encrypted(self):
  761. encoded = self.ref_private._export_pkcs8(passphrase="secret",
  762. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  763. # This should prove that the output is password-protected
  764. self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None)
  765. decoded = ECC._import_pkcs8(encoded, "secret")
  766. self.assertEqual(self.ref_private, decoded)
  767. # ---
  768. encoded = self.ref_private.export_key(format="DER",
  769. passphrase="secret",
  770. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  771. decoded = ECC.import_key(encoded, "secret")
  772. self.assertEqual(self.ref_private, decoded)
  773. def test_export_public_pem_uncompressed(self):
  774. key_file = load_file("ecc_p521_public.pem", "rt").strip()
  775. encoded = self.ref_private._export_public_pem(False)
  776. self.assertEqual(key_file, encoded)
  777. # ---
  778. encoded = self.ref_public.export_key(format="PEM")
  779. self.assertEqual(key_file, encoded)
  780. encoded = self.ref_public.export_key(format="PEM", compress=False)
  781. self.assertEqual(key_file, encoded)
  782. def test_export_public_pem_compressed(self):
  783. key_file = load_file("ecc_p521_public.pem", "rt").strip()
  784. pub_key = ECC.import_key(key_file)
  785. key_file_compressed = pub_key.export_key(format="PEM", compress=True)
  786. key_file_compressed_ref = load_file("ecc_p521_public_compressed.pem", "rt").strip()
  787. self.assertEqual(key_file_compressed, key_file_compressed_ref)
  788. def test_export_private_pem_clear(self):
  789. key_file = load_file("ecc_p521_private.pem", "rt").strip()
  790. encoded = self.ref_private._export_private_pem(None)
  791. self.assertEqual(key_file, encoded)
  792. # ---
  793. encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
  794. self.assertEqual(key_file, encoded)
  795. def test_export_private_pem_encrypted(self):
  796. encoded = self.ref_private._export_private_pem(passphrase=b"secret")
  797. # This should prove that the output is password-protected
  798. self.assertRaises(ValueError, ECC.import_key, encoded)
  799. assert "EC PRIVATE KEY" in encoded
  800. decoded = ECC.import_key(encoded, "secret")
  801. self.assertEqual(self.ref_private, decoded)
  802. # ---
  803. encoded = self.ref_private.export_key(format="PEM",
  804. passphrase="secret",
  805. use_pkcs8=False)
  806. decoded = ECC.import_key(encoded, "secret")
  807. self.assertEqual(self.ref_private, decoded)
  808. def test_export_private_pkcs8_and_pem_1(self):
  809. # PKCS8 inside PEM with both unencrypted
  810. key_file = load_file("ecc_p521_private_p8_clear.pem", "rt").strip()
  811. encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
  812. self.assertEqual(key_file, encoded)
  813. # ---
  814. encoded = self.ref_private.export_key(format="PEM")
  815. self.assertEqual(key_file, encoded)
  816. def test_export_private_pkcs8_and_pem_2(self):
  817. # PKCS8 inside PEM with PKCS8 encryption
  818. encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret",
  819. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  820. # This should prove that the output is password-protected
  821. self.assertRaises(ValueError, ECC.import_key, encoded)
  822. assert "ENCRYPTED PRIVATE KEY" in encoded
  823. decoded = ECC.import_key(encoded, "secret")
  824. self.assertEqual(self.ref_private, decoded)
  825. # ---
  826. encoded = self.ref_private.export_key(format="PEM",
  827. passphrase="secret",
  828. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  829. decoded = ECC.import_key(encoded, "secret")
  830. self.assertEqual(self.ref_private, decoded)
  831. def test_export_openssh_uncompressed(self):
  832. key_file = load_file("ecc_p521_public_openssh.txt", "rt")
  833. encoded = self.ref_public._export_openssh(False)
  834. self.assertEquals(key_file, encoded)
  835. # ---
  836. encoded = self.ref_public.export_key(format="OpenSSH")
  837. self.assertEquals(key_file, encoded)
  838. encoded = self.ref_public.export_key(format="OpenSSH", compress=False)
  839. self.assertEquals(key_file, encoded)
  840. def test_export_openssh_compressed(self):
  841. key_file = load_file("ecc_p521_public_openssh.txt", "rt")
  842. pub_key = ECC.import_key(key_file)
  843. key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True)
  844. assert len(key_file) > len(key_file_compressed)
  845. self.assertEquals(pub_key, ECC.import_key(key_file_compressed))
  846. def test_prng(self):
  847. # Test that password-protected containers use the provided PRNG
  848. encoded1 = self.ref_private.export_key(format="PEM",
  849. passphrase="secret",
  850. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
  851. randfunc=get_fixed_prng())
  852. encoded2 = self.ref_private.export_key(format="PEM",
  853. passphrase="secret",
  854. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
  855. randfunc=get_fixed_prng())
  856. self.assertEquals(encoded1, encoded2)
  857. # ---
  858. encoded1 = self.ref_private.export_key(format="PEM",
  859. use_pkcs8=False,
  860. passphrase="secret",
  861. randfunc=get_fixed_prng())
  862. encoded2 = self.ref_private.export_key(format="PEM",
  863. use_pkcs8=False,
  864. passphrase="secret",
  865. randfunc=get_fixed_prng())
  866. self.assertEquals(encoded1, encoded2)
  867. def test_byte_or_string_passphrase(self):
  868. encoded1 = self.ref_private.export_key(format="PEM",
  869. use_pkcs8=False,
  870. passphrase="secret",
  871. randfunc=get_fixed_prng())
  872. encoded2 = self.ref_private.export_key(format="PEM",
  873. use_pkcs8=False,
  874. passphrase=b"secret",
  875. randfunc=get_fixed_prng())
  876. self.assertEquals(encoded1, encoded2)
  877. def test_error_params1(self):
  878. # Unknown format
  879. self.assertRaises(ValueError, self.ref_private.export_key, format="XXX")
  880. # Missing 'protection' parameter when PKCS#8 is used
  881. self.ref_private.export_key(format="PEM", passphrase="secret",
  882. use_pkcs8=False)
  883. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  884. passphrase="secret")
  885. # DER format but no PKCS#8
  886. self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
  887. passphrase="secret",
  888. use_pkcs8=False,
  889. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  890. # Incorrect parameters for public keys
  891. self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
  892. use_pkcs8=False)
  893. # Empty password
  894. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  895. passphrase="", use_pkcs8=False)
  896. self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
  897. passphrase="",
  898. protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
  899. # No private keys with OpenSSH
  900. self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH",
  901. passphrase="secret")
  902. def test_compressed_curve(self):
  903. # Compressed P-521 curve (Y-point is even)
  904. # openssl ecparam -name secp521r1 -genkey -noout -conv_form compressed -out /tmp/a.pem
  905. # openssl ec -in /tmp/a.pem -text -noout
  906. pem1 = """-----BEGIN EC PRIVATE KEY-----
  907. MIHcAgEBBEIAnm1CEjVjvNfXEN730p+D6su5l+mOztdc5XmTEoti+s2R4GQ4mAv3
  908. 0zYLvyklvOHw0+yy8d0cyGEJGb8T3ZVKmg2gBwYFK4EEACOhgYkDgYYABAHzjTI1
  909. ckxQ3Togi0LAxiG0PucdBBBs5oIy3df95xv6SInp70z+4qQ2EltEmdNMssH8eOrl
  910. M5CYdZ6nbcHMVaJUvQEzTrYxvFjOgJiOd+E9eBWbLkbMNqsh1UKVO6HbMbW0ohCI
  911. uGxO8tM6r3w89/qzpG2SvFM/fvv3mIR30wSZDD84qA==
  912. -----END EC PRIVATE KEY-----"""
  913. # Compressed P-521 curve (Y-point is odd)
  914. pem2 = """-----BEGIN EC PRIVATE KEY-----
  915. MIHcAgEBBEIB84OfhJluLBRLn3+cC/RQ37C2SfQVP/t0gQK2tCsTf5avRcWYRrOJ
  916. PmX9lNnkC0Hobd75QFRmdxrB0Wd1/M4jZOWgBwYFK4EEACOhgYkDgYYABAAMZcdJ
  917. 1YLCGHt3bHCEzdidVy6+brlJIbv1aQ9fPQLF7WKNv4c8w3H8d5a2+SDZilBOsk5c
  918. 6cNJDMz2ExWQvxl4CwDJtJGt1+LHVKFGy73NANqVxMbRu+2F8lOxkNp/ziFTbVyV
  919. vv6oYkMIIi7r5oQWAiQDrR2mlrrFDL9V7GH/r8SWQw==
  920. -----END EC PRIVATE KEY-----"""
  921. key1 = ECC.import_key(pem1)
  922. low16 = int(key1.pointQ.y % 65536)
  923. self.assertEqual(low16, 0x38a8)
  924. key2 = ECC.import_key(pem2)
  925. low16 = int(key2.pointQ.y % 65536)
  926. self.assertEqual(low16, 0x9643)
  927. def get_tests(config={}):
  928. tests = []
  929. tests += list_test_cases(TestImport)
  930. tests += list_test_cases(TestImport_P256)
  931. tests += list_test_cases(TestImport_P384)
  932. tests += list_test_cases(TestImport_P521)
  933. tests += list_test_cases(TestExport_P256)
  934. tests += list_test_cases(TestExport_P384)
  935. tests += list_test_cases(TestExport_P521)
  936. return tests
  937. if __name__ == '__main__':
  938. suite = lambda: unittest.TestSuite(get_tests())
  939. unittest.main(defaultTest='suite')