test_keys.py 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for L{twisted.conch.ssh.keys}.
  5. """
  6. from __future__ import absolute_import, division
  7. try:
  8. import cryptography
  9. except ImportError:
  10. cryptography = None
  11. skipCryptography = 'Cannot run without cryptography.'
  12. try:
  13. import Crypto.Cipher.DES3
  14. import Crypto.PublicKey.RSA
  15. import Crypto.PublicKey.DSA
  16. except ImportError:
  17. # we'll have to skip some tests without PyCypto
  18. Crypto = None
  19. skipPyCrypto = 'Cannot run without PyCrypto.'
  20. try:
  21. import pyasn1
  22. except ImportError:
  23. pyasn1 = None
  24. if cryptography and pyasn1:
  25. from twisted.conch.ssh import keys, common, sexpy
  26. import base64
  27. import os
  28. from twisted.conch.test import keydata
  29. from twisted.python import randbytes
  30. from twisted.trial import unittest
  31. from twisted.python.compat import long, _PY3
  32. from incremental import Version
  33. from twisted.python.filepath import FilePath
  34. class ObjectTypeTests(unittest.TestCase):
  35. """
  36. Unit tests for the objectType method.
  37. """
  38. if cryptography is None:
  39. skip = skipCryptography
  40. if Crypto is None:
  41. skip = "Cannot run without PyCrypto."
  42. if _PY3:
  43. skip = "objectType is deprecated and is not being ported to Python 3."
  44. def getRSAKey(self):
  45. """
  46. Return a PyCrypto RSA key to support the tests.
  47. @return: The RSA key to support the tests.
  48. @rtype: C{Crypto.PublicKey.RSA}
  49. """
  50. # Use lazy import as PyCrypto will be deprecated.
  51. from Crypto.PublicKey import RSA
  52. return RSA.construct((
  53. keydata.RSAData['n'],
  54. keydata.RSAData['e'],
  55. keydata.RSAData['d'],
  56. ))
  57. def getDSAKey(self):
  58. """
  59. Return a PyCrypto DSA key to support the tests.
  60. @return: The DSA key to support the tests.
  61. @rtype: C{Crypto.PublicKey.DSA}
  62. """
  63. # Use lazy import as PyCrypto will be deprecated.
  64. from Crypto.PublicKey import DSA
  65. return DSA.construct((
  66. keydata.DSAData['y'],
  67. keydata.DSAData['g'],
  68. keydata.DSAData['p'],
  69. keydata.DSAData['q'],
  70. keydata.DSAData['x'],
  71. ))
  72. def checkDeprecation(self):
  73. """
  74. Check that we have a deprecation warning for C{objectType}.
  75. """
  76. warnings = self.flushWarnings()
  77. self.assertEqual(1, len(warnings))
  78. self.assertIs(DeprecationWarning, warnings[0]['category'])
  79. self.assertEqual(
  80. 'twisted.conch.ssh.keys.objectType was deprecated in '
  81. 'Twisted 15.5.0',
  82. warnings[0]['message'])
  83. def test_objectType_rsa(self):
  84. """
  85. C{ssh-rsa} is the type of the RSA keys.
  86. """
  87. key = self.getRSAKey()
  88. self.assertEqual(keys.objectType(key), b'ssh-rsa')
  89. self.checkDeprecation()
  90. def test_objectType_dsa(self):
  91. """
  92. C{ssh-dss} is the type of the DSA keys.
  93. """
  94. key = self.getDSAKey()
  95. self.assertEqual(keys.objectType(key), b'ssh-dss')
  96. self.checkDeprecation()
  97. def test_objectKey_none(self):
  98. """
  99. A BadKeyError is raised when getting the type of L{None}.
  100. """
  101. self.assertRaises(keys.BadKeyError, keys.objectType, None)
  102. self.checkDeprecation()
  103. def test_deprecation(self):
  104. """
  105. It is deprecated.
  106. """
  107. key = self.getRSAKey()
  108. keys.objectType(key)
  109. self.checkDeprecation()
  110. class KeyTests(unittest.TestCase):
  111. if cryptography is None:
  112. skip = skipCryptography
  113. if pyasn1 is None:
  114. skip = "Cannot run without PyASN1"
  115. def setUp(self):
  116. self.rsaObj = keys.Key._fromRSAComponents(
  117. n=keydata.RSAData['n'],
  118. e=keydata.RSAData['e'],
  119. d=keydata.RSAData['d'],
  120. p=keydata.RSAData['p'],
  121. q=keydata.RSAData['q'],
  122. u=keydata.RSAData['u'],
  123. )._keyObject
  124. self.dsaObj = keys.Key._fromDSAComponents(
  125. y=keydata.DSAData['y'],
  126. p=keydata.DSAData['p'],
  127. q=keydata.DSAData['q'],
  128. g=keydata.DSAData['g'],
  129. x=keydata.DSAData['x'],
  130. )._keyObject
  131. self.ecObj = keys.Key._fromECComponents(
  132. x=keydata.ECDatanistp256['x'],
  133. y=keydata.ECDatanistp256['y'],
  134. privateValue=keydata.ECDatanistp256['privateValue'],
  135. curve=keydata.ECDatanistp256['curve']
  136. )._keyObject
  137. self.ecObj384 = keys.Key._fromECComponents(
  138. x=keydata.ECDatanistp384['x'],
  139. y=keydata.ECDatanistp384['y'],
  140. privateValue=keydata.ECDatanistp384['privateValue'],
  141. curve=keydata.ECDatanistp384['curve']
  142. )._keyObject
  143. self.ecObj521 = keys.Key._fromECComponents(
  144. x=keydata.ECDatanistp521['x'],
  145. y=keydata.ECDatanistp521['y'],
  146. privateValue=keydata.ECDatanistp521['privateValue'],
  147. curve=keydata.ECDatanistp521['curve']
  148. )._keyObject
  149. self.rsaSignature = (b'\x00\x00\x00\x07ssh-rsa\x00'
  150. b'\x00\x00`N\xac\xb4@qK\xa0(\xc3\xf2h \xd3\xdd\xee6Np\x9d_'
  151. b'\xb0>\xe3\x0c(L\x9d{\txUd|!\xf6m\x9c\xd3\x93\x842\x7fU'
  152. b'\x05\xf4\xf7\xfaD\xda\xce\x81\x8ea\x7f=Y\xed*\xb7\xba\x81'
  153. b'\xf2\xad\xda\xeb(\x97\x03S\x08\x81\xc7\xb1\xb7\xe6\xe3'
  154. b'\xcd*\xd4\xbd\xc0wt\xf7y\xcd\xf0\xb7\x7f\xfb\x1e>\xf9r'
  155. b'\x8c\xba')
  156. self.dsaSignature = (
  157. b'\x00\x00\x00\x07ssh-dss\x00\x00\x00(?\xc7\xeb\x86;\xd5TFA\xb4'
  158. b'\xdf\x0c\xc4E@4,d\xbc\t\xd9\xae\xdd[\xed-\x82nQ\x8cf\x9b\xe8\xe1'
  159. b'jrg\x84p<'
  160. )
  161. self.patch(randbytes, 'secureRandom', lambda x: b'\xff' * x)
  162. self.keyFile = self.mktemp()
  163. with open(self.keyFile, 'wb') as f:
  164. f.write(keydata.privateRSA_lsh)
  165. def tearDown(self):
  166. os.unlink(self.keyFile)
  167. def test_size(self):
  168. """
  169. The L{keys.Key.size} method returns the size of key object in bits.
  170. """
  171. self.assertEqual(keys.Key(self.rsaObj).size(), 768)
  172. self.assertEqual(keys.Key(self.dsaObj).size(), 1024)
  173. self.assertEqual(keys.Key(self.ecObj).size(), 256)
  174. self.assertEqual(keys.Key(self.ecObj384).size(), 384)
  175. self.assertEqual(keys.Key(self.ecObj521).size(), 521)
  176. def test__guessStringType(self):
  177. """
  178. Test that the _guessStringType method guesses string types
  179. correctly.
  180. """
  181. self.assertEqual(keys.Key._guessStringType(keydata.publicRSA_openssh),
  182. 'public_openssh')
  183. self.assertEqual(keys.Key._guessStringType(keydata.publicDSA_openssh),
  184. 'public_openssh')
  185. self.assertEqual(keys.Key._guessStringType(keydata.publicECDSA_openssh),
  186. 'public_openssh')
  187. self.assertEqual(keys.Key._guessStringType(
  188. keydata.privateRSA_openssh), 'private_openssh')
  189. self.assertEqual(keys.Key._guessStringType(
  190. keydata.privateDSA_openssh), 'private_openssh')
  191. self.assertEqual(keys.Key._guessStringType(
  192. keydata.privateECDSA_openssh), 'private_openssh')
  193. self.assertEqual(keys.Key._guessStringType(keydata.publicRSA_lsh),
  194. 'public_lsh')
  195. self.assertEqual(keys.Key._guessStringType(keydata.publicDSA_lsh),
  196. 'public_lsh')
  197. self.assertEqual(keys.Key._guessStringType(keydata.privateRSA_lsh),
  198. 'private_lsh')
  199. self.assertEqual(keys.Key._guessStringType(keydata.privateDSA_lsh),
  200. 'private_lsh')
  201. self.assertEqual(keys.Key._guessStringType(
  202. keydata.privateRSA_agentv3), 'agentv3')
  203. self.assertEqual(keys.Key._guessStringType(
  204. keydata.privateDSA_agentv3), 'agentv3')
  205. self.assertEqual(keys.Key._guessStringType(
  206. b'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x01\x01'),
  207. 'blob')
  208. self.assertEqual(keys.Key._guessStringType(
  209. b'\x00\x00\x00\x07ssh-dss\x00\x00\x00\x01\x01'),
  210. 'blob')
  211. self.assertEqual(keys.Key._guessStringType(b'not a key'),
  212. None)
  213. def test_isPublic(self):
  214. """
  215. The L{keys.Key.isPublic} method returns True for public keys
  216. otherwise False.
  217. """
  218. rsaKey = keys.Key.fromString(keydata.privateRSA_openssh)
  219. dsaKey = keys.Key.fromString(keydata.privateDSA_openssh)
  220. ecdsaKey = keys.Key.fromString(keydata.privateECDSA_openssh)
  221. self.assertTrue(rsaKey.public().isPublic())
  222. self.assertFalse(rsaKey.isPublic())
  223. self.assertTrue(dsaKey.public().isPublic())
  224. self.assertFalse(dsaKey.isPublic())
  225. self.assertTrue(ecdsaKey.public().isPublic())
  226. self.assertFalse(ecdsaKey.isPublic())
  227. def _testPublicPrivateFromString(self, public, private, type, data):
  228. self._testPublicFromString(public, type, data)
  229. self._testPrivateFromString(private, type, data)
  230. def _testPublicFromString(self, public, type, data):
  231. publicKey = keys.Key.fromString(public)
  232. self.assertTrue(publicKey.isPublic())
  233. self.assertEqual(publicKey.type(), type)
  234. for k, v in publicKey.data().items():
  235. self.assertEqual(data[k], v)
  236. def _testPrivateFromString(self, private, type, data):
  237. privateKey = keys.Key.fromString(private)
  238. self.assertFalse(privateKey.isPublic())
  239. self.assertEqual(privateKey.type(), type)
  240. for k, v in data.items():
  241. self.assertEqual(privateKey.data()[k], v)
  242. def test_fromOpenSSH(self):
  243. """
  244. Test that keys are correctly generated from OpenSSH strings.
  245. """
  246. self._testPublicPrivateFromString(keydata.publicECDSA_openssh,
  247. keydata.privateECDSA_openssh, 'EC', keydata.ECDatanistp256)
  248. self._testPublicPrivateFromString(keydata.publicRSA_openssh,
  249. keydata.privateRSA_openssh, 'RSA', keydata.RSAData)
  250. self.assertEqual(keys.Key.fromString(
  251. keydata.privateRSA_openssh_encrypted,
  252. passphrase=b'encrypted'),
  253. keys.Key.fromString(keydata.privateRSA_openssh))
  254. self.assertEqual(keys.Key.fromString(
  255. keydata.privateRSA_openssh_alternate),
  256. keys.Key.fromString(keydata.privateRSA_openssh))
  257. self._testPublicPrivateFromString(keydata.publicDSA_openssh,
  258. keydata.privateDSA_openssh, 'DSA', keydata.DSAData)
  259. def test_fromOpenSSHErrors(self):
  260. """
  261. Tests for invalid key types.
  262. """
  263. badKey = b"""-----BEGIN FOO PRIVATE KEY-----
  264. MIGkAgEBBDAtAi7I8j73WCX20qUM5hhHwHuFzYWYYILs2Sh8UZ+awNkARZ/Fu2LU
  265. LLl5RtOQpbWgBwYFK4EEACKhZANiAATU17sA9P5FRwSknKcFsjjsk0+E3CeXPYX0
  266. Tk/M0HK3PpWQWgrO8JdRHP9eFE9O/23P8BumwFt7F/AvPlCzVd35VfraFT0o4cCW
  267. G0RqpQ+np31aKmeJshkcYALEchnU+tQ=
  268. -----END EC PRIVATE KEY-----"""
  269. self.assertRaises(keys.BadKeyError,
  270. keys.Key._fromString_PRIVATE_OPENSSH, badKey, None)
  271. def test_fromOpenSSH_with_whitespace(self):
  272. """
  273. If key strings have trailing whitespace, it should be ignored.
  274. """
  275. # from bug #3391, since our test key data doesn't have
  276. # an issue with appended newlines
  277. privateDSAData = b"""-----BEGIN DSA PRIVATE KEY-----
  278. MIIBuwIBAAKBgQDylESNuc61jq2yatCzZbenlr9llG+p9LhIpOLUbXhhHcwC6hrh
  279. EZIdCKqTO0USLrGoP5uS9UHAUoeN62Z0KXXWTwOWGEQn/syyPzNJtnBorHpNUT9D
  280. Qzwl1yUa53NNgEctpo4NoEFOx8PuU6iFLyvgHCjNn2MsuGuzkZm7sI9ZpQIVAJiR
  281. 9dPc08KLdpJyRxz8T74b4FQRAoGAGBc4Z5Y6R/HZi7AYM/iNOM8su6hrk8ypkBwR
  282. a3Dbhzk97fuV3SF1SDrcQu4zF7c4CtH609N5nfZs2SUjLLGPWln83Ysb8qhh55Em
  283. AcHXuROrHS/sDsnqu8FQp86MaudrqMExCOYyVPE7jaBWW+/JWFbKCxmgOCSdViUJ
  284. esJpBFsCgYEA7+jtVvSt9yrwsS/YU1QGP5wRAiDYB+T5cK4HytzAqJKRdC5qS4zf
  285. C7R0eKcDHHLMYO39aPnCwXjscisnInEhYGNblTDyPyiyNxAOXuC8x7luTmwzMbNJ
  286. /ow0IqSj0VF72VJN9uSoPpFd4lLT0zN8v42RWja0M8ohWNf+YNJluPgCFE0PT4Vm
  287. SUrCyZXsNh6VXwjs3gKQ
  288. -----END DSA PRIVATE KEY-----"""
  289. self.assertEqual(keys.Key.fromString(privateDSAData),
  290. keys.Key.fromString(privateDSAData + b'\n'))
  291. def test_fromNewerOpenSSH(self):
  292. """
  293. Newer versions of OpenSSH generate encrypted keys which have a longer
  294. IV than the older versions. These newer keys are also loaded.
  295. """
  296. key = keys.Key.fromString(keydata.privateRSA_openssh_encrypted_aes,
  297. passphrase=b'testxp')
  298. self.assertEqual(key.type(), 'RSA')
  299. key2 = keys.Key.fromString(
  300. keydata.privateRSA_openssh_encrypted_aes + b'\n',
  301. passphrase=b'testxp')
  302. self.assertEqual(key, key2)
  303. def test_fromOpenSSH_windows_line_endings(self):
  304. """
  305. Test that keys are correctly generated from OpenSSH strings with Windows
  306. line endings.
  307. """
  308. privateDSAData = b"""-----BEGIN DSA PRIVATE KEY-----
  309. MIIBuwIBAAKBgQDylESNuc61jq2yatCzZbenlr9llG+p9LhIpOLUbXhhHcwC6hrh
  310. EZIdCKqTO0USLrGoP5uS9UHAUoeN62Z0KXXWTwOWGEQn/syyPzNJtnBorHpNUT9D
  311. Qzwl1yUa53NNgEctpo4NoEFOx8PuU6iFLyvgHCjNn2MsuGuzkZm7sI9ZpQIVAJiR
  312. 9dPc08KLdpJyRxz8T74b4FQRAoGAGBc4Z5Y6R/HZi7AYM/iNOM8su6hrk8ypkBwR
  313. a3Dbhzk97fuV3SF1SDrcQu4zF7c4CtH609N5nfZs2SUjLLGPWln83Ysb8qhh55Em
  314. AcHXuROrHS/sDsnqu8FQp86MaudrqMExCOYyVPE7jaBWW+/JWFbKCxmgOCSdViUJ
  315. esJpBFsCgYEA7+jtVvSt9yrwsS/YU1QGP5wRAiDYB+T5cK4HytzAqJKRdC5qS4zf
  316. C7R0eKcDHHLMYO39aPnCwXjscisnInEhYGNblTDyPyiyNxAOXuC8x7luTmwzMbNJ
  317. /ow0IqSj0VF72VJN9uSoPpFd4lLT0zN8v42RWja0M8ohWNf+YNJluPgCFE0PT4Vm
  318. SUrCyZXsNh6VXwjs3gKQ
  319. -----END DSA PRIVATE KEY-----"""
  320. self.assertEqual(
  321. keys.Key.fromString(privateDSAData),
  322. keys.Key.fromString(privateDSAData.replace(b'\n', b'\r\n')))
  323. def test_fromLSHPublicUnsupportedType(self):
  324. """
  325. C{BadKeyError} exception is raised when public key has an unknown
  326. type.
  327. """
  328. sexp = sexpy.pack([[b'public-key', [b'bad-key', [b'p', b'2']]]])
  329. self.assertRaises(
  330. keys.BadKeyError,
  331. keys.Key.fromString, data=b'{' + base64.encodestring(sexp) + b'}',
  332. )
  333. def test_fromLSHPrivateUnsupportedType(self):
  334. """
  335. C{BadKeyError} exception is raised when private key has an unknown
  336. type.
  337. """
  338. sexp = sexpy.pack([[b'private-key', [b'bad-key', [b'p', b'2']]]])
  339. self.assertRaises(
  340. keys.BadKeyError,
  341. keys.Key.fromString, sexp,
  342. )
  343. def test_fromLSHRSA(self):
  344. """
  345. RSA public and private keys can be generated from a LSH strings.
  346. """
  347. self._testPublicPrivateFromString(
  348. keydata.publicRSA_lsh,
  349. keydata.privateRSA_lsh,
  350. 'RSA',
  351. keydata.RSAData,
  352. )
  353. def test_fromLSHDSA(self):
  354. """
  355. DSA public and private key can be generated from LSHs.
  356. """
  357. self._testPublicPrivateFromString(
  358. keydata.publicDSA_lsh,
  359. keydata.privateDSA_lsh,
  360. 'DSA',
  361. keydata.DSAData,
  362. )
  363. def test_fromAgentv3(self):
  364. """
  365. Test that keys are correctly generated from Agent v3 strings.
  366. """
  367. self._testPrivateFromString(keydata.privateRSA_agentv3, 'RSA',
  368. keydata.RSAData)
  369. self._testPrivateFromString(keydata.privateDSA_agentv3, 'DSA',
  370. keydata.DSAData)
  371. self.assertRaises(keys.BadKeyError, keys.Key.fromString,
  372. b'\x00\x00\x00\x07ssh-foo'+ b'\x00\x00\x00\x01\x01'*5)
  373. def test_fromStringErrors(self):
  374. """
  375. keys.Key.fromString should raise BadKeyError when the key is invalid.
  376. """
  377. self.assertRaises(keys.BadKeyError, keys.Key.fromString, b'')
  378. # no key data with a bad key type
  379. self.assertRaises(keys.BadKeyError, keys.Key.fromString, b'',
  380. 'bad_type')
  381. # trying to decrypt a key which doesn't support encryption
  382. self.assertRaises(keys.BadKeyError, keys.Key.fromString,
  383. keydata.publicRSA_lsh, passphrase = b'unencrypted')
  384. # trying to decrypt a key with the wrong passphrase
  385. self.assertRaises(keys.EncryptedKeyError, keys.Key.fromString,
  386. keys.Key(self.rsaObj).toString('openssh', b'encrypted'))
  387. # key with no key data
  388. self.assertRaises(keys.BadKeyError, keys.Key.fromString,
  389. b'-----BEGIN RSA KEY-----\nwA==\n')
  390. # key with invalid DEK Info
  391. self.assertRaises(
  392. keys.BadKeyError, keys.Key.fromString,
  393. b"""-----BEGIN ENCRYPTED RSA KEY-----
  394. Proc-Type: 4,ENCRYPTED
  395. DEK-Info: weird type
  396. 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
  397. T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
  398. g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
  399. sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
  400. 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
  401. gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
  402. 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
  403. vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
  404. hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
  405. 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
  406. qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
  407. 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
  408. EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
  409. 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
  410. fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
  411. V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
  412. 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
  413. xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
  414. dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
  415. VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
  416. gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
  417. 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
  418. SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
  419. CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
  420. xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
  421. -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
  422. # key with invalid encryption type
  423. self.assertRaises(
  424. keys.BadKeyError, keys.Key.fromString,
  425. b"""-----BEGIN ENCRYPTED RSA KEY-----
  426. Proc-Type: 4,ENCRYPTED
  427. DEK-Info: FOO-123-BAR,01234567
  428. 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
  429. T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
  430. g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
  431. sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
  432. 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
  433. gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
  434. 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
  435. vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
  436. hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
  437. 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
  438. qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
  439. 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
  440. EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
  441. 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
  442. fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
  443. V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
  444. 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
  445. xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
  446. dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
  447. VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
  448. gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
  449. 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
  450. SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
  451. CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
  452. xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
  453. -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
  454. # key with bad IV (AES)
  455. self.assertRaises(
  456. keys.BadKeyError, keys.Key.fromString,
  457. b"""-----BEGIN ENCRYPTED RSA KEY-----
  458. Proc-Type: 4,ENCRYPTED
  459. DEK-Info: AES-128-CBC,01234
  460. 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
  461. T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
  462. g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
  463. sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
  464. 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
  465. gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
  466. 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
  467. vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
  468. hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
  469. 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
  470. qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
  471. 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
  472. EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
  473. 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
  474. fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
  475. V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
  476. 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
  477. xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
  478. dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
  479. VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
  480. gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
  481. 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
  482. SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
  483. CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
  484. xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
  485. -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
  486. # key with bad IV (DES3)
  487. self.assertRaises(
  488. keys.BadKeyError, keys.Key.fromString,
  489. b"""-----BEGIN ENCRYPTED RSA KEY-----
  490. Proc-Type: 4,ENCRYPTED
  491. DEK-Info: DES-EDE3-CBC,01234
  492. 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
  493. T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
  494. g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
  495. sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
  496. 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
  497. gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
  498. 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
  499. vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
  500. hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
  501. 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
  502. qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
  503. 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
  504. EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
  505. 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
  506. fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
  507. V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
  508. 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
  509. xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
  510. dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
  511. VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
  512. gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
  513. 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
  514. SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
  515. CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
  516. xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
  517. -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
  518. def test_fromFile(self):
  519. """
  520. Test that fromFile works correctly.
  521. """
  522. self.assertEqual(keys.Key.fromFile(self.keyFile),
  523. keys.Key.fromString(keydata.privateRSA_lsh))
  524. self.assertRaises(keys.BadKeyError, keys.Key.fromFile,
  525. self.keyFile, 'bad_type')
  526. self.assertRaises(keys.BadKeyError, keys.Key.fromFile,
  527. self.keyFile, passphrase='unencrypted')
  528. def test_init(self):
  529. """
  530. Test that the PublicKey object is initialized correctly.
  531. """
  532. obj = keys.Key._fromRSAComponents(n=long(5), e=long(3))._keyObject
  533. key = keys.Key(obj)
  534. self.assertEqual(key._keyObject, obj)
  535. def test_equal(self):
  536. """
  537. Test that Key objects are compared correctly.
  538. """
  539. rsa1 = keys.Key(self.rsaObj)
  540. rsa2 = keys.Key(self.rsaObj)
  541. rsa3 = keys.Key(
  542. keys.Key._fromRSAComponents(n=long(5), e=long(3))._keyObject)
  543. dsa = keys.Key(self.dsaObj)
  544. self.assertTrue(rsa1 == rsa2)
  545. self.assertFalse(rsa1 == rsa3)
  546. self.assertFalse(rsa1 == dsa)
  547. self.assertFalse(rsa1 == object)
  548. self.assertFalse(rsa1 == None)
  549. def test_notEqual(self):
  550. """
  551. Test that Key objects are not-compared correctly.
  552. """
  553. rsa1 = keys.Key(self.rsaObj)
  554. rsa2 = keys.Key(self.rsaObj)
  555. rsa3 = keys.Key(
  556. keys.Key._fromRSAComponents(n=long(5), e=long(3))._keyObject)
  557. dsa = keys.Key(self.dsaObj)
  558. self.assertFalse(rsa1 != rsa2)
  559. self.assertTrue(rsa1 != rsa3)
  560. self.assertTrue(rsa1 != dsa)
  561. self.assertTrue(rsa1 != object)
  562. self.assertTrue(rsa1 != None)
  563. def test_dataError(self):
  564. """
  565. The L{keys.Key.data} method raises RuntimeError for bad keys.
  566. """
  567. badKey = keys.Key(b'')
  568. self.assertRaises(RuntimeError, badKey.data)
  569. def test_fingerprintdefault(self):
  570. """
  571. Test that the fingerprint method returns fingerprint in
  572. L{FingerprintFormats.MD5-HEX} format by default.
  573. """
  574. self.assertEqual(keys.Key(self.rsaObj).fingerprint(),
  575. '3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af')
  576. self.assertEqual(keys.Key(self.dsaObj).fingerprint(),
  577. '63:15:b3:0e:e6:4f:50:de:91:48:3d:01:6b:b3:13:c1')
  578. def test_fingerprint_md5_hex(self):
  579. """
  580. fingerprint method generates key fingerprint in
  581. L{FingerprintFormats.MD5-HEX} format if explicitly specified.
  582. """
  583. self.assertEqual(
  584. keys.Key(self.rsaObj).fingerprint(
  585. keys.FingerprintFormats.MD5_HEX),
  586. '3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af')
  587. self.assertEqual(
  588. keys.Key(self.dsaObj).fingerprint(
  589. keys.FingerprintFormats.MD5_HEX),
  590. '63:15:b3:0e:e6:4f:50:de:91:48:3d:01:6b:b3:13:c1')
  591. def test_fingerprintsha256(self):
  592. """
  593. fingerprint method generates key fingerprint in
  594. L{FingerprintFormats.SHA256-BASE64} format if explicitly specified.
  595. """
  596. self.assertEqual(
  597. keys.Key(self.rsaObj).fingerprint(
  598. keys.FingerprintFormats.SHA256_BASE64),
  599. 'ryaugIFT0B8ItuszldMEU7q14rG/wj9HkRosMeBWkts=')
  600. self.assertEqual(
  601. keys.Key(self.dsaObj).fingerprint(
  602. keys.FingerprintFormats.SHA256_BASE64),
  603. 'Wz5o2YbKyxOEcJn1au/UaALSVruUzfz0vaLI1xiIGyY=')
  604. def test_fingerprintBadFormat(self):
  605. """
  606. A C{BadFingerPrintFormat} error is raised when unsupported
  607. formats are requested.
  608. """
  609. with self.assertRaises(keys.BadFingerPrintFormat) as em:
  610. keys.Key(self.rsaObj).fingerprint('sha256-base')
  611. self.assertEqual('Unsupported fingerprint format: sha256-base',
  612. em.exception.args[0])
  613. def test_type(self):
  614. """
  615. Test that the type method returns the correct type for an object.
  616. """
  617. self.assertEqual(keys.Key(self.rsaObj).type(), 'RSA')
  618. self.assertEqual(keys.Key(self.rsaObj).sshType(), b'ssh-rsa')
  619. self.assertEqual(keys.Key(self.dsaObj).type(), 'DSA')
  620. self.assertEqual(keys.Key(self.dsaObj).sshType(), b'ssh-dss')
  621. self.assertEqual(keys.Key(self.ecObj).type(), 'EC')
  622. self.assertEqual(keys.Key(self.ecObj).sshType(),
  623. keydata.ECDatanistp256['curve'])
  624. self.assertRaises(RuntimeError, keys.Key(None).type)
  625. self.assertRaises(RuntimeError, keys.Key(None).sshType)
  626. self.assertRaises(RuntimeError, keys.Key(self).type)
  627. self.assertRaises(RuntimeError, keys.Key(self).sshType)
  628. def test_fromBlobUnsupportedType(self):
  629. """
  630. A C{BadKeyError} error is raised whey the blob has an unsupported
  631. key type.
  632. """
  633. badBlob = common.NS(b'ssh-bad')
  634. self.assertRaises(keys.BadKeyError,
  635. keys.Key.fromString, badBlob)
  636. def test_fromBlobRSA(self):
  637. """
  638. A public RSA key is correctly generated from a public key blob.
  639. """
  640. rsaPublicData = {
  641. 'n': keydata.RSAData['n'],
  642. 'e': keydata.RSAData['e'],
  643. }
  644. rsaBlob = (
  645. common.NS(b'ssh-rsa') +
  646. common.MP(rsaPublicData['e']) +
  647. common.MP(rsaPublicData['n'])
  648. )
  649. rsaKey = keys.Key.fromString(rsaBlob)
  650. self.assertTrue(rsaKey.isPublic())
  651. self.assertEqual(rsaPublicData, rsaKey.data())
  652. def test_fromBlobDSA(self):
  653. """
  654. A public DSA key is correctly generated from a public key blob.
  655. """
  656. dsaPublicData = {
  657. 'p': keydata.DSAData['p'],
  658. 'q': keydata.DSAData['q'],
  659. 'g': keydata.DSAData['g'],
  660. 'y': keydata.DSAData['y'],
  661. }
  662. dsaBlob = (
  663. common.NS(b'ssh-dss') +
  664. common.MP(dsaPublicData['p']) +
  665. common.MP(dsaPublicData['q']) +
  666. common.MP(dsaPublicData['g']) +
  667. common.MP(dsaPublicData['y'])
  668. )
  669. dsaKey = keys.Key.fromString(dsaBlob)
  670. self.assertTrue(dsaKey.isPublic())
  671. self.assertEqual(dsaPublicData, dsaKey.data())
  672. def test_fromBlobECDSA(self):
  673. """
  674. Key.fromString generates ECDSA keys from blobs.
  675. """
  676. from cryptography import utils
  677. ecPublicData = {
  678. 'x': keydata.ECDatanistp256['x'],
  679. 'y': keydata.ECDatanistp256['y'],
  680. 'curve': keydata.ECDatanistp256['curve']
  681. }
  682. ecblob = (common.NS(ecPublicData['curve']) +
  683. common.NS(ecPublicData['curve'][-8:]) +
  684. common.NS(b'\x04' +
  685. utils.int_to_bytes(ecPublicData['x'], 32) +
  686. utils.int_to_bytes(ecPublicData['y'], 32))
  687. )
  688. eckey = keys.Key.fromString(ecblob)
  689. self.assertTrue(eckey.isPublic())
  690. self.assertEqual(ecPublicData, eckey.data())
  691. def test_fromPrivateBlobUnsupportedType(self):
  692. """
  693. C{BadKeyError} is raised when loading a private blob with an
  694. unsupported type.
  695. """
  696. badBlob = common.NS(b'ssh-bad')
  697. self.assertRaises(
  698. keys.BadKeyError, keys.Key._fromString_PRIVATE_BLOB, badBlob)
  699. def test_fromPrivateBlobRSA(self):
  700. """
  701. A private RSA key is correctly generated from a private key blob.
  702. """
  703. rsaBlob = (
  704. common.NS(b'ssh-rsa') +
  705. common.MP(keydata.RSAData['n']) +
  706. common.MP(keydata.RSAData['e']) +
  707. common.MP(keydata.RSAData['d']) +
  708. common.MP(keydata.RSAData['u']) +
  709. common.MP(keydata.RSAData['p']) +
  710. common.MP(keydata.RSAData['q'])
  711. )
  712. rsaKey = keys.Key._fromString_PRIVATE_BLOB(rsaBlob)
  713. self.assertFalse(rsaKey.isPublic())
  714. self.assertEqual(keydata.RSAData, rsaKey.data())
  715. def test_fromPrivateBlobDSA(self):
  716. """
  717. A private DSA key is correctly generated from a private key blob.
  718. """
  719. dsaBlob = (
  720. common.NS(b'ssh-dss') +
  721. common.MP(keydata.DSAData['p']) +
  722. common.MP(keydata.DSAData['q']) +
  723. common.MP(keydata.DSAData['g']) +
  724. common.MP(keydata.DSAData['y']) +
  725. common.MP(keydata.DSAData['x'])
  726. )
  727. dsaKey = keys.Key._fromString_PRIVATE_BLOB(dsaBlob)
  728. self.assertFalse(dsaKey.isPublic())
  729. self.assertEqual(keydata.DSAData, dsaKey.data())
  730. def test_fromPrivateBlobECDSA(self):
  731. """
  732. A private EC key is correctly generated from a private key blob.
  733. """
  734. ecblob = (
  735. common.NS(keydata.ECDatanistp256['curve']) +
  736. common.MP(keydata.ECDatanistp256['x']) +
  737. common.MP(keydata.ECDatanistp256['y']) +
  738. common.MP(keydata.ECDatanistp256['privateValue'])
  739. )
  740. eckey = keys.Key._fromString_PRIVATE_BLOB(ecblob)
  741. self.assertFalse(eckey.isPublic())
  742. self.assertEqual(keydata.ECDatanistp256, eckey.data())
  743. def test_blobRSA(self):
  744. """
  745. Return the over-the-wire SSH format of the RSA public key.
  746. """
  747. self.assertEqual(
  748. keys.Key(self.rsaObj).blob(),
  749. common.NS(b'ssh-rsa') +
  750. common.MP(self.rsaObj.private_numbers().public_numbers.e) +
  751. common.MP(self.rsaObj.private_numbers().public_numbers.n)
  752. )
  753. def test_blobDSA(self):
  754. """
  755. Return the over-the-wire SSH format of the DSA public key.
  756. """
  757. publicNumbers = self.dsaObj.private_numbers().public_numbers
  758. self.assertEqual(
  759. keys.Key(self.dsaObj).blob(),
  760. common.NS(b'ssh-dss') +
  761. common.MP(publicNumbers.parameter_numbers.p) +
  762. common.MP(publicNumbers.parameter_numbers.q) +
  763. common.MP(publicNumbers.parameter_numbers.g) +
  764. common.MP(publicNumbers.y)
  765. )
  766. def test_blobEC(self):
  767. """
  768. Return the over-the-wire SSH format of the EC public key.
  769. """
  770. from cryptography import utils
  771. byteLength = (self.ecObj.curve.key_size + 7) // 8
  772. self.assertEqual(
  773. keys.Key(self.ecObj).blob(),
  774. common.NS(keydata.ECDatanistp256['curve']) +
  775. common.NS(keydata.ECDatanistp256['curve'][-8:]) +
  776. common.NS(b'\x04' +
  777. utils.int_to_bytes(
  778. self.ecObj.private_numbers().public_numbers.x, byteLength) +
  779. utils.int_to_bytes(
  780. self.ecObj.private_numbers().public_numbers.y, byteLength))
  781. )
  782. def test_blobNoKey(self):
  783. """
  784. C{RuntimeError} is raised when the blob is requested for a Key
  785. which is not wrapping anything.
  786. """
  787. badKey = keys.Key(None)
  788. self.assertRaises(RuntimeError, badKey.blob)
  789. def test_privateBlobRSA(self):
  790. """
  791. L{keys.Key.privateBlob} returns the SSH protocol-level format of an
  792. RSA private key.
  793. """
  794. from cryptography.hazmat.primitives.asymmetric import rsa
  795. numbers = self.rsaObj.private_numbers()
  796. u = rsa.rsa_crt_iqmp(numbers.q, numbers.p)
  797. self.assertEqual(
  798. keys.Key(self.rsaObj).privateBlob(),
  799. common.NS(b'ssh-rsa') +
  800. common.MP(self.rsaObj.private_numbers().public_numbers.n) +
  801. common.MP(self.rsaObj.private_numbers().public_numbers.e) +
  802. common.MP(self.rsaObj.private_numbers().d) +
  803. common.MP(u) +
  804. common.MP(self.rsaObj.private_numbers().p) +
  805. common.MP(self.rsaObj.private_numbers().q)
  806. )
  807. def test_privateBlobDSA(self):
  808. """
  809. L{keys.Key.privateBlob} returns the SSH protocol-level format of a DSA
  810. private key.
  811. """
  812. publicNumbers = self.dsaObj.private_numbers().public_numbers
  813. self.assertEqual(
  814. keys.Key(self.dsaObj).privateBlob(),
  815. common.NS(b'ssh-dss') +
  816. common.MP(publicNumbers.parameter_numbers.p) +
  817. common.MP(publicNumbers.parameter_numbers.q) +
  818. common.MP(publicNumbers.parameter_numbers.g) +
  819. common.MP(publicNumbers.y) +
  820. common.MP(self.dsaObj.private_numbers().x)
  821. )
  822. def test_privateBlobEC(self):
  823. """
  824. L{keys.Key.privateBlob} returns the SSH ptotocol-level format of EC
  825. private key.
  826. """
  827. self.assertEqual(
  828. keys.Key(self.ecObj).privateBlob(),
  829. common.NS(keydata.ECDatanistp256['curve']) +
  830. common.MP(self.ecObj.private_numbers().public_numbers.x) +
  831. common.MP(self.ecObj.private_numbers().public_numbers.y) +
  832. common.MP(self.ecObj.private_numbers().private_value)
  833. )
  834. def test_privateBlobNoKeyObject(self):
  835. """
  836. Raises L{RuntimeError} if the underlying key object does not exists.
  837. """
  838. badKey = keys.Key(None)
  839. self.assertRaises(RuntimeError, badKey.privateBlob)
  840. def test_toOpenSSHRSA(self):
  841. """
  842. L{keys.Key.toString} serializes an RSA key in OpenSSH format.
  843. """
  844. key = keys.Key.fromString(keydata.privateRSA_agentv3)
  845. self.assertEqual(key.toString('openssh'), keydata.privateRSA_openssh)
  846. self.assertEqual(key.toString('openssh', b'encrypted'),
  847. keydata.privateRSA_openssh_encrypted)
  848. self.assertEqual(key.public().toString('openssh'),
  849. keydata.publicRSA_openssh[:-8]) # no comment
  850. self.assertEqual(key.public().toString('openssh', b'comment'),
  851. keydata.publicRSA_openssh)
  852. def test_toOpenSSHDSA(self):
  853. """
  854. L{keys.Key.toString} serializes a DSA key in OpenSSH format.
  855. """
  856. key = keys.Key.fromString(keydata.privateDSA_lsh)
  857. self.assertEqual(key.toString('openssh'), keydata.privateDSA_openssh)
  858. self.assertEqual(key.public().toString('openssh', b'comment'),
  859. keydata.publicDSA_openssh)
  860. self.assertEqual(key.public().toString('openssh'),
  861. keydata.publicDSA_openssh[:-8]) # no comment
  862. def test_toOpenSSHECDSA(self):
  863. """
  864. L{keys.Key.toString} serializes a ECDSA key in OpenSSH format.
  865. """
  866. key = keys.Key.fromString(keydata.privateECDSA_openssh)
  867. self.assertEqual(key.public().toString('openssh', b'comment'),
  868. keydata.publicECDSA_openssh)
  869. self.assertEqual(key.public().toString('openssh'),
  870. keydata.publicECDSA_openssh[:-8]) # no comment
  871. def test_toLSHRSA(self):
  872. """
  873. L{keys.Key.toString} serializes an RSA key in LSH format.
  874. """
  875. key = keys.Key.fromString(keydata.privateRSA_openssh)
  876. self.assertEqual(key.toString('lsh'), keydata.privateRSA_lsh)
  877. self.assertEqual(key.public().toString('lsh'),
  878. keydata.publicRSA_lsh)
  879. def test_toLSHDSA(self):
  880. """
  881. L{keys.Key.toString} serializes a DSA key in LSH format.
  882. """
  883. key = keys.Key.fromString(keydata.privateDSA_openssh)
  884. self.assertEqual(key.toString('lsh'), keydata.privateDSA_lsh)
  885. self.assertEqual(key.public().toString('lsh'),
  886. keydata.publicDSA_lsh)
  887. def test_toAgentv3RSA(self):
  888. """
  889. L{keys.Key.toString} serializes an RSA key in Agent v3 format.
  890. """
  891. key = keys.Key.fromString(keydata.privateRSA_openssh)
  892. self.assertEqual(key.toString('agentv3'), keydata.privateRSA_agentv3)
  893. def test_toAgentv3DSA(self):
  894. """
  895. L{keys.Key.toString} serializes a DSA key in Agent v3 format.
  896. """
  897. key = keys.Key.fromString(keydata.privateDSA_openssh)
  898. self.assertEqual(key.toString('agentv3'), keydata.privateDSA_agentv3)
  899. def test_toStringErrors(self):
  900. """
  901. L{keys.Key.toString} raises L{keys.BadKeyError} when passed an invalid
  902. format type.
  903. """
  904. self.assertRaises(keys.BadKeyError, keys.Key(self.rsaObj).toString,
  905. 'bad_type')
  906. def test_signAndVerifyRSA(self):
  907. """
  908. Signed data can be verified using RSA.
  909. """
  910. data = b'some-data'
  911. key = keys.Key.fromString(keydata.privateRSA_openssh)
  912. signature = key.sign(data)
  913. self.assertTrue(key.public().verify(signature, data))
  914. self.assertTrue(key.verify(signature, data))
  915. def test_signAndVerifyDSA(self):
  916. """
  917. Signed data can be verified using DSA.
  918. """
  919. data = b'some-data'
  920. key = keys.Key.fromString(keydata.privateDSA_openssh)
  921. signature = key.sign(data)
  922. self.assertTrue(key.public().verify(signature, data))
  923. self.assertTrue(key.verify(signature, data))
  924. def test_signAndVerifyEC(self):
  925. """
  926. Signed data can be verified using EC.
  927. """
  928. data = b'some-data'
  929. key = keys.Key.fromString(keydata.privateECDSA_openssh)
  930. signature = key.sign(data)
  931. key384 = keys.Key.fromString(keydata.privateECDSA_openssh384)
  932. signature384 = key384.sign(data)
  933. key521 = keys.Key.fromString(keydata.privateECDSA_openssh521)
  934. signature521 = key521.sign(data)
  935. self.assertTrue(key.public().verify(signature, data))
  936. self.assertTrue(key.verify(signature, data))
  937. self.assertTrue(key384.public().verify(signature384, data))
  938. self.assertTrue(key384.verify(signature384, data))
  939. self.assertTrue(key521.public().verify(signature521, data))
  940. self.assertTrue(key521.verify(signature521, data))
  941. def test_verifyRSA(self):
  942. """
  943. A known-good RSA signature verifies successfully.
  944. """
  945. key = keys.Key.fromString(keydata.publicRSA_openssh)
  946. self.assertTrue(key.verify(self.rsaSignature, b''))
  947. self.assertFalse(key.verify(self.rsaSignature, b'a'))
  948. self.assertFalse(key.verify(self.dsaSignature, b''))
  949. def test_verifyDSA(self):
  950. """
  951. A known-good DSA signature verifies successfully.
  952. """
  953. key = keys.Key.fromString(keydata.publicDSA_openssh)
  954. self.assertTrue(key.verify(self.dsaSignature, b''))
  955. self.assertFalse(key.verify(self.dsaSignature, b'a'))
  956. self.assertFalse(key.verify(self.rsaSignature, b''))
  957. def test_verifyDSANoPrefix(self):
  958. """
  959. Some commercial SSH servers send DSA keys as 2 20-byte numbers;
  960. they are still verified as valid keys.
  961. """
  962. key = keys.Key.fromString(keydata.publicDSA_openssh)
  963. self.assertTrue(key.verify(self.dsaSignature[-40:], b''))
  964. def test_reprPrivateRSA(self):
  965. """
  966. The repr of a L{keys.Key} contains all of the RSA components for an RSA
  967. private key.
  968. """
  969. self.assertEqual(repr(keys.Key(self.rsaObj)),
  970. """<RSA Private Key (768 bits)
  971. attr d:
  972. \t6e:1f:b5:55:97:eb:ed:67:ed:2b:99:6e:ec:c1:ed:
  973. \ta8:4d:52:d6:f3:d6:65:06:04:df:e5:54:9f:cc:89:
  974. \t00:3c:9b:67:87:ec:65:a0:ab:cd:6f:65:90:8a:97:
  975. \t90:4d:c6:21:8f:a8:8d:d8:59:86:43:b5:81:b1:b4:
  976. \td7:5f:2c:22:0a:61:c1:25:8a:47:12:b4:9a:f8:7a:
  977. \t11:1c:4a:a8:8b:75:c4:91:09:3b:be:04:ca:45:d9:
  978. \t57:8a:0d:27:cb:23
  979. attr e:
  980. \t23
  981. attr n:
  982. \t00:af:32:71:f0:e6:0e:9c:99:b3:7f:8b:5f:04:4b:
  983. \tcb:8b:c0:d5:3e:b2:77:fd:cf:64:d8:8f:c0:cf:ae:
  984. \t1f:c6:31:df:f6:29:b2:44:96:e2:c6:d4:21:94:7f:
  985. \t65:7c:d8:d4:23:1f:b8:2e:6a:c9:1f:94:0d:46:c1:
  986. \t69:a2:b7:07:0c:a3:93:c1:34:d8:2e:1e:4a:99:1a:
  987. \t6c:96:46:07:46:2b:dc:25:29:1b:87:f0:be:05:1d:
  988. \tee:b4:34:b9:e7:99:95
  989. attr p:
  990. \t00:cb:4a:4b:d0:40:47:e8:45:52:f7:c7:af:0c:20:
  991. \t6d:43:0d:b6:39:94:f9:da:a5:e5:03:06:76:83:24:
  992. \teb:88:a1:55:a2:a8:de:12:3b:77:49:92:8a:a9:71:
  993. \td2:02:93:ff
  994. attr q:
  995. \t00:dc:9f:6b:d9:98:21:56:11:8d:e9:5f:03:9d:0a:
  996. \td3:93:6e:13:77:41:3c:85:4f:00:70:fd:05:54:ff:
  997. \tbc:3d:09:bf:83:f6:97:7f:64:10:91:04:fe:a2:67:
  998. \t47:54:42:6b
  999. attr u:
  1000. \t00:b4:73:97:4b:50:10:a3:17:b3:a8:47:f1:3a:14:
  1001. \t76:52:d1:38:2a:cf:12:14:34:c1:a8:54:4c:29:35:
  1002. \t80:a0:38:b8:f0:fa:4c:c4:c2:85:ab:db:87:82:ba:
  1003. \tdc:eb:db:2a>""")
  1004. def test_reprPublicRSA(self):
  1005. """
  1006. The repr of a L{keys.Key} contains all of the RSA components for an RSA
  1007. public key.
  1008. """
  1009. self.assertEqual(repr(keys.Key(self.rsaObj).public()),
  1010. """<RSA Public Key (768 bits)
  1011. attr e:
  1012. \t23
  1013. attr n:
  1014. \t00:af:32:71:f0:e6:0e:9c:99:b3:7f:8b:5f:04:4b:
  1015. \tcb:8b:c0:d5:3e:b2:77:fd:cf:64:d8:8f:c0:cf:ae:
  1016. \t1f:c6:31:df:f6:29:b2:44:96:e2:c6:d4:21:94:7f:
  1017. \t65:7c:d8:d4:23:1f:b8:2e:6a:c9:1f:94:0d:46:c1:
  1018. \t69:a2:b7:07:0c:a3:93:c1:34:d8:2e:1e:4a:99:1a:
  1019. \t6c:96:46:07:46:2b:dc:25:29:1b:87:f0:be:05:1d:
  1020. \tee:b4:34:b9:e7:99:95>""")
  1021. def test_reprPublicECDSA(self):
  1022. """
  1023. The repr of a L{keys.Key} contains all the OpenSSH format for an ECDSA
  1024. public key.
  1025. """
  1026. self.assertEqual(repr(keys.Key(self.ecObj).public()),
  1027. """<Elliptic Curve Public Key (256 bits)
  1028. curve:
  1029. \tecdsa-sha2-nistp256
  1030. x:
  1031. \t76282513020392096317118503144964731774299773481750550543382904345687059013883
  1032. y:""" +
  1033. "\n\t8154319786460285263226566476944164753434437589431431968106113715931064" +
  1034. "6683104>\n")
  1035. def test_reprPrivateECDSA(self):
  1036. """
  1037. The repr of a L{keys.Key} contains all the OpenSSH format for an ECDSA
  1038. private key.
  1039. """
  1040. self.assertEqual(repr(keys.Key(self.ecObj)),
  1041. """<Elliptic Curve Private Key (256 bits)
  1042. curve:
  1043. \tecdsa-sha2-nistp256
  1044. privateValue:
  1045. \t34638743477210341700964008455655698253555655678826059678074967909361042656500
  1046. x:
  1047. \t76282513020392096317118503144964731774299773481750550543382904345687059013883
  1048. y:""" +
  1049. "\n\t8154319786460285263226566476944164753434437589431431968106113715931064" +
  1050. "6683104>\n")
  1051. class KeyKeyObjectTests(unittest.TestCase):
  1052. """
  1053. The L{keys.Key.keyObject} property provides deprecated access to a PyCrypto
  1054. key instance of the corresponding type.
  1055. """
  1056. if cryptography is None:
  1057. skip = skipCryptography
  1058. if Crypto is None:
  1059. skip = skipPyCrypto
  1060. def test_deprecation(self):
  1061. """
  1062. Accessing the L{keys.Key.keyObject} property emits a deprecation
  1063. warning.
  1064. """
  1065. keys.Key.fromString(keydata.publicRSA_openssh).keyObject
  1066. [warning] = self.flushWarnings([KeyKeyObjectTests.test_deprecation])
  1067. self.assertIs(warning['category'], DeprecationWarning)
  1068. def test_keyObjectGetRSAPublic(self):
  1069. """
  1070. The PyCrypto key instance for an RSA public key has the same components
  1071. as the internal key.
  1072. """
  1073. key = keys.Key.fromString(keydata.publicRSA_openssh)
  1074. result = key.keyObject
  1075. self.assertIsInstance(result, Crypto.PublicKey.RSA._RSAobj)
  1076. self.assertEqual(keydata.RSAData['e'], result.key.e)
  1077. self.assertEqual(keydata.RSAData['n'], result.key.n)
  1078. def test_keyObjectGetRSAPrivate(self):
  1079. """
  1080. The PyCrypto key instance for an RSA private key has the same
  1081. components as the internal key.
  1082. """
  1083. key = keys.Key.fromString(keydata.privateRSA_openssh)
  1084. result = key.keyObject
  1085. self.assertIsInstance(result, Crypto.PublicKey.RSA._RSAobj)
  1086. self.assertEqual(keydata.RSAData['e'], result.key.e)
  1087. self.assertEqual(keydata.RSAData['n'], result.key.n)
  1088. self.assertEqual(keydata.RSAData['d'], result.key.d)
  1089. self.assertEqual(keydata.RSAData['p'], result.key.p)
  1090. self.assertEqual(keydata.RSAData['q'], result.key.q)
  1091. self.assertEqual(keydata.RSAData['u'], result.key.u)
  1092. def test_keyObjectGetDSAPublic(self):
  1093. """
  1094. The PyCrypto key instance for a DSA public key has the same components
  1095. as the internal key.
  1096. """
  1097. key = keys.Key.fromString(keydata.publicDSA_openssh)
  1098. result = key.keyObject
  1099. self.assertIsInstance(result, Crypto.PublicKey.DSA._DSAobj)
  1100. self.assertEqual(keydata.DSAData['y'], result.key.y)
  1101. self.assertEqual(keydata.DSAData['g'], result.key.g)
  1102. self.assertEqual(keydata.DSAData['p'], result.key.p)
  1103. self.assertEqual(keydata.DSAData['q'], result.key.q)
  1104. def test_keyObjectGetDSAPrivate(self):
  1105. """
  1106. The PyCrypto key instance for a DSA private key has the same components
  1107. as the internal key.
  1108. """
  1109. key = keys.Key.fromString(keydata.privateDSA_openssh)
  1110. result = key.keyObject
  1111. self.assertIsInstance(result, Crypto.PublicKey.DSA._DSAobj)
  1112. self.assertEqual(keydata.DSAData['y'], result.key.y)
  1113. self.assertEqual(keydata.DSAData['g'], result.key.g)
  1114. self.assertEqual(keydata.DSAData['p'], result.key.p)
  1115. self.assertEqual(keydata.DSAData['q'], result.key.q)
  1116. self.assertEqual(keydata.DSAData['x'], result.key.x)
  1117. def test_keyObjectSetRSAPublic(self):
  1118. """
  1119. Setting the L{keys.Key.keyObject} property to a PyCrypto public RSA key
  1120. instance updates the internal key.
  1121. """
  1122. key = keys.Key.fromString(keydata.publicDSA_openssh)
  1123. newPyCryptoKey = Crypto.PublicKey.RSA.construct((
  1124. keydata.RSAData['n'],
  1125. keydata.RSAData['e'],
  1126. ))
  1127. self.assertEqual('DSA', key.type())
  1128. key.keyObject = newPyCryptoKey
  1129. [warning] = self.flushWarnings([
  1130. KeyKeyObjectTests.test_keyObjectSetRSAPublic])
  1131. self.assertIs(warning['category'], DeprecationWarning)
  1132. self.assertEqual('RSA', key.type())
  1133. self.assertEqual({
  1134. 'n': keydata.RSAData['n'],
  1135. 'e': keydata.RSAData['e'],
  1136. },
  1137. key.data())
  1138. def test_keyObjectSetRSAPrivate(self):
  1139. """
  1140. Setting the L{keys.Key.keyObject} property to a PyCrypto private RSA
  1141. key instance updates the internal key.
  1142. """
  1143. key = keys.Key.fromString(keydata.publicDSA_openssh)
  1144. newPyCryptoKey = Crypto.PublicKey.RSA.construct((
  1145. keydata.RSAData['n'],
  1146. keydata.RSAData['e'],
  1147. keydata.RSAData['d'],
  1148. keydata.RSAData['p'],
  1149. keydata.RSAData['q'],
  1150. keydata.RSAData['u'],
  1151. ))
  1152. self.assertEqual('DSA', key.type())
  1153. key.keyObject = newPyCryptoKey
  1154. self.assertEqual('RSA', key.type())
  1155. self.assertEqual({
  1156. 'n': keydata.RSAData['n'],
  1157. 'e': keydata.RSAData['e'],
  1158. 'd': keydata.RSAData['d'],
  1159. 'p': keydata.RSAData['p'],
  1160. 'q': keydata.RSAData['q'],
  1161. 'u': keydata.RSAData['u'],
  1162. },
  1163. key.data())
  1164. def test_keyObjectSetDSAPublic(self):
  1165. """
  1166. Setting the L{keys.Key.keyObject} property to a PyCrypto public DSA key
  1167. instance updates the internal key.
  1168. """
  1169. key = keys.Key.fromString(keydata.publicRSA_openssh)
  1170. newPyCryptoKey = Crypto.PublicKey.DSA.construct((
  1171. keydata.DSAData['y'],
  1172. keydata.DSAData['g'],
  1173. keydata.DSAData['p'],
  1174. keydata.DSAData['q'],
  1175. ))
  1176. self.assertEqual('RSA', key.type())
  1177. key.keyObject = newPyCryptoKey
  1178. self.assertEqual('DSA', key.type())
  1179. self.assertEqual({
  1180. 'y': keydata.DSAData['y'],
  1181. 'g': keydata.DSAData['g'],
  1182. 'p': keydata.DSAData['p'],
  1183. 'q': keydata.DSAData['q'],
  1184. },
  1185. key.data())
  1186. def test_keyObjectSetDSAPrivate(self):
  1187. """
  1188. Setting the L{keys.Key.keyObject} property to a PyCrypto private DSA
  1189. key instance updates the internal key.
  1190. """
  1191. key = keys.Key.fromString(keydata.publicRSA_openssh)
  1192. newPyCryptoKey = Crypto.PublicKey.DSA.construct((
  1193. keydata.DSAData['y'],
  1194. keydata.DSAData['g'],
  1195. keydata.DSAData['p'],
  1196. keydata.DSAData['q'],
  1197. keydata.DSAData['x'],
  1198. ))
  1199. self.assertEqual('RSA', key.type())
  1200. key.keyObject = newPyCryptoKey
  1201. self.assertEqual('DSA', key.type())
  1202. self.assertEqual({
  1203. 'y': keydata.DSAData['y'],
  1204. 'g': keydata.DSAData['g'],
  1205. 'p': keydata.DSAData['p'],
  1206. 'q': keydata.DSAData['q'],
  1207. 'x': keydata.DSAData['x'],
  1208. },
  1209. key.data())
  1210. def test_constructorPyCrypto(self):
  1211. """
  1212. Passing a PyCrypto key object to L{keys.Key} is deprecated.
  1213. """
  1214. pycryptoKey = Crypto.PublicKey.RSA.construct((
  1215. keydata.RSAData['n'],
  1216. keydata.RSAData['e']))
  1217. key = self.callDeprecated(
  1218. (Version('Twisted', 16, 0, 0),
  1219. 'passing a cryptography key object'),
  1220. keys.Key,
  1221. pycryptoKey)
  1222. self.assertEqual('RSA', key.type())
  1223. self.assertEqual({
  1224. 'n': keydata.RSAData['n'],
  1225. 'e': keydata.RSAData['e'],
  1226. },
  1227. key.data())
  1228. class PersistentRSAKeyTests(unittest.TestCase):
  1229. """
  1230. Tests for L{keys._getPersistentRSAKey}.
  1231. """
  1232. if cryptography is None:
  1233. skip = skipCryptography
  1234. def test_providedArguments(self):
  1235. """
  1236. L{keys._getPersistentRSAKey} will put the key in
  1237. C{directory}/C{filename}, with the key length of C{keySize}.
  1238. """
  1239. tempDir = FilePath(self.mktemp())
  1240. keyFile = tempDir.child("mykey.pem")
  1241. key = keys._getPersistentRSAKey(keyFile, keySize=512)
  1242. self.assertEqual(key.size(), 512)
  1243. self.assertTrue(keyFile.exists())
  1244. def test_noRegeneration(self):
  1245. """
  1246. L{keys._getPersistentRSAKey} will not regenerate the key if the key
  1247. already exists.
  1248. """
  1249. tempDir = FilePath(self.mktemp())
  1250. keyFile = tempDir.child("mykey.pem")
  1251. key = keys._getPersistentRSAKey(keyFile, keySize=512)
  1252. self.assertEqual(key.size(), 512)
  1253. self.assertTrue(keyFile.exists())
  1254. keyContent = keyFile.getContent()
  1255. # Set the key size to 1024 bits. Since it exists already, it will find
  1256. # the 512 bit key, and not generate a 1024 bit key.
  1257. key = keys._getPersistentRSAKey(keyFile, keySize=1024)
  1258. self.assertEqual(key.size(), 512)
  1259. self.assertEqual(keyFile.getContent(), keyContent)
  1260. def test_keySizeZero(self):
  1261. """
  1262. If the key generated by L{keys.getPersistentRSAKey} is set to None
  1263. the key size should then become 0.
  1264. """
  1265. tempDir = FilePath(self.mktemp())
  1266. keyFile = tempDir.child("mykey.pem")
  1267. key = keys._getPersistentRSAKey(keyFile, keySize=512)
  1268. key._keyObject = None
  1269. self.assertEqual( key.size(), 0)