123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512 |
- # Copyright (c) Twisted Matrix Laboratories.
- # See LICENSE for details.
- """
- Tests for L{twisted.conch.ssh.keys}.
- """
- from __future__ import absolute_import, division
- try:
- import cryptography
- except ImportError:
- cryptography = None
- skipCryptography = 'Cannot run without cryptography.'
- try:
- import Crypto.Cipher.DES3
- import Crypto.PublicKey.RSA
- import Crypto.PublicKey.DSA
- except ImportError:
- # we'll have to skip some tests without PyCypto
- Crypto = None
- skipPyCrypto = 'Cannot run without PyCrypto.'
- try:
- import pyasn1
- except ImportError:
- pyasn1 = None
- if cryptography and pyasn1:
- from twisted.conch.ssh import keys, common, sexpy
- import base64
- import os
- from twisted.conch.test import keydata
- from twisted.python import randbytes
- from twisted.trial import unittest
- from twisted.python.compat import long, _PY3
- from incremental import Version
- from twisted.python.filepath import FilePath
- class ObjectTypeTests(unittest.TestCase):
- """
- Unit tests for the objectType method.
- """
- if cryptography is None:
- skip = skipCryptography
- if Crypto is None:
- skip = "Cannot run without PyCrypto."
- if _PY3:
- skip = "objectType is deprecated and is not being ported to Python 3."
- def getRSAKey(self):
- """
- Return a PyCrypto RSA key to support the tests.
- @return: The RSA key to support the tests.
- @rtype: C{Crypto.PublicKey.RSA}
- """
- # Use lazy import as PyCrypto will be deprecated.
- from Crypto.PublicKey import RSA
- return RSA.construct((
- keydata.RSAData['n'],
- keydata.RSAData['e'],
- keydata.RSAData['d'],
- ))
- def getDSAKey(self):
- """
- Return a PyCrypto DSA key to support the tests.
- @return: The DSA key to support the tests.
- @rtype: C{Crypto.PublicKey.DSA}
- """
- # Use lazy import as PyCrypto will be deprecated.
- from Crypto.PublicKey import DSA
- return DSA.construct((
- keydata.DSAData['y'],
- keydata.DSAData['g'],
- keydata.DSAData['p'],
- keydata.DSAData['q'],
- keydata.DSAData['x'],
- ))
- def checkDeprecation(self):
- """
- Check that we have a deprecation warning for C{objectType}.
- """
- warnings = self.flushWarnings()
- self.assertEqual(1, len(warnings))
- self.assertIs(DeprecationWarning, warnings[0]['category'])
- self.assertEqual(
- 'twisted.conch.ssh.keys.objectType was deprecated in '
- 'Twisted 15.5.0',
- warnings[0]['message'])
- def test_objectType_rsa(self):
- """
- C{ssh-rsa} is the type of the RSA keys.
- """
- key = self.getRSAKey()
- self.assertEqual(keys.objectType(key), b'ssh-rsa')
- self.checkDeprecation()
- def test_objectType_dsa(self):
- """
- C{ssh-dss} is the type of the DSA keys.
- """
- key = self.getDSAKey()
- self.assertEqual(keys.objectType(key), b'ssh-dss')
- self.checkDeprecation()
- def test_objectKey_none(self):
- """
- A BadKeyError is raised when getting the type of L{None}.
- """
- self.assertRaises(keys.BadKeyError, keys.objectType, None)
- self.checkDeprecation()
- def test_deprecation(self):
- """
- It is deprecated.
- """
- key = self.getRSAKey()
- keys.objectType(key)
- self.checkDeprecation()
- class KeyTests(unittest.TestCase):
- if cryptography is None:
- skip = skipCryptography
- if pyasn1 is None:
- skip = "Cannot run without PyASN1"
- def setUp(self):
- self.rsaObj = keys.Key._fromRSAComponents(
- n=keydata.RSAData['n'],
- e=keydata.RSAData['e'],
- d=keydata.RSAData['d'],
- p=keydata.RSAData['p'],
- q=keydata.RSAData['q'],
- u=keydata.RSAData['u'],
- )._keyObject
- self.dsaObj = keys.Key._fromDSAComponents(
- y=keydata.DSAData['y'],
- p=keydata.DSAData['p'],
- q=keydata.DSAData['q'],
- g=keydata.DSAData['g'],
- x=keydata.DSAData['x'],
- )._keyObject
- self.ecObj = keys.Key._fromECComponents(
- x=keydata.ECDatanistp256['x'],
- y=keydata.ECDatanistp256['y'],
- privateValue=keydata.ECDatanistp256['privateValue'],
- curve=keydata.ECDatanistp256['curve']
- )._keyObject
- self.ecObj384 = keys.Key._fromECComponents(
- x=keydata.ECDatanistp384['x'],
- y=keydata.ECDatanistp384['y'],
- privateValue=keydata.ECDatanistp384['privateValue'],
- curve=keydata.ECDatanistp384['curve']
- )._keyObject
- self.ecObj521 = keys.Key._fromECComponents(
- x=keydata.ECDatanistp521['x'],
- y=keydata.ECDatanistp521['y'],
- privateValue=keydata.ECDatanistp521['privateValue'],
- curve=keydata.ECDatanistp521['curve']
- )._keyObject
- self.rsaSignature = (b'\x00\x00\x00\x07ssh-rsa\x00'
- b'\x00\x00`N\xac\xb4@qK\xa0(\xc3\xf2h \xd3\xdd\xee6Np\x9d_'
- b'\xb0>\xe3\x0c(L\x9d{\txUd|!\xf6m\x9c\xd3\x93\x842\x7fU'
- b'\x05\xf4\xf7\xfaD\xda\xce\x81\x8ea\x7f=Y\xed*\xb7\xba\x81'
- b'\xf2\xad\xda\xeb(\x97\x03S\x08\x81\xc7\xb1\xb7\xe6\xe3'
- b'\xcd*\xd4\xbd\xc0wt\xf7y\xcd\xf0\xb7\x7f\xfb\x1e>\xf9r'
- b'\x8c\xba')
- self.dsaSignature = (
- b'\x00\x00\x00\x07ssh-dss\x00\x00\x00(?\xc7\xeb\x86;\xd5TFA\xb4'
- b'\xdf\x0c\xc4E@4,d\xbc\t\xd9\xae\xdd[\xed-\x82nQ\x8cf\x9b\xe8\xe1'
- b'jrg\x84p<'
- )
- self.patch(randbytes, 'secureRandom', lambda x: b'\xff' * x)
- self.keyFile = self.mktemp()
- with open(self.keyFile, 'wb') as f:
- f.write(keydata.privateRSA_lsh)
- def tearDown(self):
- os.unlink(self.keyFile)
- def test_size(self):
- """
- The L{keys.Key.size} method returns the size of key object in bits.
- """
- self.assertEqual(keys.Key(self.rsaObj).size(), 768)
- self.assertEqual(keys.Key(self.dsaObj).size(), 1024)
- self.assertEqual(keys.Key(self.ecObj).size(), 256)
- self.assertEqual(keys.Key(self.ecObj384).size(), 384)
- self.assertEqual(keys.Key(self.ecObj521).size(), 521)
- def test__guessStringType(self):
- """
- Test that the _guessStringType method guesses string types
- correctly.
- """
- self.assertEqual(keys.Key._guessStringType(keydata.publicRSA_openssh),
- 'public_openssh')
- self.assertEqual(keys.Key._guessStringType(keydata.publicDSA_openssh),
- 'public_openssh')
- self.assertEqual(keys.Key._guessStringType(keydata.publicECDSA_openssh),
- 'public_openssh')
- self.assertEqual(keys.Key._guessStringType(
- keydata.privateRSA_openssh), 'private_openssh')
- self.assertEqual(keys.Key._guessStringType(
- keydata.privateDSA_openssh), 'private_openssh')
- self.assertEqual(keys.Key._guessStringType(
- keydata.privateECDSA_openssh), 'private_openssh')
- self.assertEqual(keys.Key._guessStringType(keydata.publicRSA_lsh),
- 'public_lsh')
- self.assertEqual(keys.Key._guessStringType(keydata.publicDSA_lsh),
- 'public_lsh')
- self.assertEqual(keys.Key._guessStringType(keydata.privateRSA_lsh),
- 'private_lsh')
- self.assertEqual(keys.Key._guessStringType(keydata.privateDSA_lsh),
- 'private_lsh')
- self.assertEqual(keys.Key._guessStringType(
- keydata.privateRSA_agentv3), 'agentv3')
- self.assertEqual(keys.Key._guessStringType(
- keydata.privateDSA_agentv3), 'agentv3')
- self.assertEqual(keys.Key._guessStringType(
- b'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x01\x01'),
- 'blob')
- self.assertEqual(keys.Key._guessStringType(
- b'\x00\x00\x00\x07ssh-dss\x00\x00\x00\x01\x01'),
- 'blob')
- self.assertEqual(keys.Key._guessStringType(b'not a key'),
- None)
- def test_isPublic(self):
- """
- The L{keys.Key.isPublic} method returns True for public keys
- otherwise False.
- """
- rsaKey = keys.Key.fromString(keydata.privateRSA_openssh)
- dsaKey = keys.Key.fromString(keydata.privateDSA_openssh)
- ecdsaKey = keys.Key.fromString(keydata.privateECDSA_openssh)
- self.assertTrue(rsaKey.public().isPublic())
- self.assertFalse(rsaKey.isPublic())
- self.assertTrue(dsaKey.public().isPublic())
- self.assertFalse(dsaKey.isPublic())
- self.assertTrue(ecdsaKey.public().isPublic())
- self.assertFalse(ecdsaKey.isPublic())
- def _testPublicPrivateFromString(self, public, private, type, data):
- self._testPublicFromString(public, type, data)
- self._testPrivateFromString(private, type, data)
- def _testPublicFromString(self, public, type, data):
- publicKey = keys.Key.fromString(public)
- self.assertTrue(publicKey.isPublic())
- self.assertEqual(publicKey.type(), type)
- for k, v in publicKey.data().items():
- self.assertEqual(data[k], v)
- def _testPrivateFromString(self, private, type, data):
- privateKey = keys.Key.fromString(private)
- self.assertFalse(privateKey.isPublic())
- self.assertEqual(privateKey.type(), type)
- for k, v in data.items():
- self.assertEqual(privateKey.data()[k], v)
- def test_fromOpenSSH(self):
- """
- Test that keys are correctly generated from OpenSSH strings.
- """
- self._testPublicPrivateFromString(keydata.publicECDSA_openssh,
- keydata.privateECDSA_openssh, 'EC', keydata.ECDatanistp256)
- self._testPublicPrivateFromString(keydata.publicRSA_openssh,
- keydata.privateRSA_openssh, 'RSA', keydata.RSAData)
- self.assertEqual(keys.Key.fromString(
- keydata.privateRSA_openssh_encrypted,
- passphrase=b'encrypted'),
- keys.Key.fromString(keydata.privateRSA_openssh))
- self.assertEqual(keys.Key.fromString(
- keydata.privateRSA_openssh_alternate),
- keys.Key.fromString(keydata.privateRSA_openssh))
- self._testPublicPrivateFromString(keydata.publicDSA_openssh,
- keydata.privateDSA_openssh, 'DSA', keydata.DSAData)
- def test_fromOpenSSHErrors(self):
- """
- Tests for invalid key types.
- """
- badKey = b"""-----BEGIN FOO PRIVATE KEY-----
- MIGkAgEBBDAtAi7I8j73WCX20qUM5hhHwHuFzYWYYILs2Sh8UZ+awNkARZ/Fu2LU
- LLl5RtOQpbWgBwYFK4EEACKhZANiAATU17sA9P5FRwSknKcFsjjsk0+E3CeXPYX0
- Tk/M0HK3PpWQWgrO8JdRHP9eFE9O/23P8BumwFt7F/AvPlCzVd35VfraFT0o4cCW
- G0RqpQ+np31aKmeJshkcYALEchnU+tQ=
- -----END EC PRIVATE KEY-----"""
- self.assertRaises(keys.BadKeyError,
- keys.Key._fromString_PRIVATE_OPENSSH, badKey, None)
- def test_fromOpenSSH_with_whitespace(self):
- """
- If key strings have trailing whitespace, it should be ignored.
- """
- # from bug #3391, since our test key data doesn't have
- # an issue with appended newlines
- privateDSAData = b"""-----BEGIN DSA PRIVATE KEY-----
- MIIBuwIBAAKBgQDylESNuc61jq2yatCzZbenlr9llG+p9LhIpOLUbXhhHcwC6hrh
- EZIdCKqTO0USLrGoP5uS9UHAUoeN62Z0KXXWTwOWGEQn/syyPzNJtnBorHpNUT9D
- Qzwl1yUa53NNgEctpo4NoEFOx8PuU6iFLyvgHCjNn2MsuGuzkZm7sI9ZpQIVAJiR
- 9dPc08KLdpJyRxz8T74b4FQRAoGAGBc4Z5Y6R/HZi7AYM/iNOM8su6hrk8ypkBwR
- a3Dbhzk97fuV3SF1SDrcQu4zF7c4CtH609N5nfZs2SUjLLGPWln83Ysb8qhh55Em
- AcHXuROrHS/sDsnqu8FQp86MaudrqMExCOYyVPE7jaBWW+/JWFbKCxmgOCSdViUJ
- esJpBFsCgYEA7+jtVvSt9yrwsS/YU1QGP5wRAiDYB+T5cK4HytzAqJKRdC5qS4zf
- C7R0eKcDHHLMYO39aPnCwXjscisnInEhYGNblTDyPyiyNxAOXuC8x7luTmwzMbNJ
- /ow0IqSj0VF72VJN9uSoPpFd4lLT0zN8v42RWja0M8ohWNf+YNJluPgCFE0PT4Vm
- SUrCyZXsNh6VXwjs3gKQ
- -----END DSA PRIVATE KEY-----"""
- self.assertEqual(keys.Key.fromString(privateDSAData),
- keys.Key.fromString(privateDSAData + b'\n'))
- def test_fromNewerOpenSSH(self):
- """
- Newer versions of OpenSSH generate encrypted keys which have a longer
- IV than the older versions. These newer keys are also loaded.
- """
- key = keys.Key.fromString(keydata.privateRSA_openssh_encrypted_aes,
- passphrase=b'testxp')
- self.assertEqual(key.type(), 'RSA')
- key2 = keys.Key.fromString(
- keydata.privateRSA_openssh_encrypted_aes + b'\n',
- passphrase=b'testxp')
- self.assertEqual(key, key2)
- def test_fromOpenSSH_windows_line_endings(self):
- """
- Test that keys are correctly generated from OpenSSH strings with Windows
- line endings.
- """
- privateDSAData = b"""-----BEGIN DSA PRIVATE KEY-----
- MIIBuwIBAAKBgQDylESNuc61jq2yatCzZbenlr9llG+p9LhIpOLUbXhhHcwC6hrh
- EZIdCKqTO0USLrGoP5uS9UHAUoeN62Z0KXXWTwOWGEQn/syyPzNJtnBorHpNUT9D
- Qzwl1yUa53NNgEctpo4NoEFOx8PuU6iFLyvgHCjNn2MsuGuzkZm7sI9ZpQIVAJiR
- 9dPc08KLdpJyRxz8T74b4FQRAoGAGBc4Z5Y6R/HZi7AYM/iNOM8su6hrk8ypkBwR
- a3Dbhzk97fuV3SF1SDrcQu4zF7c4CtH609N5nfZs2SUjLLGPWln83Ysb8qhh55Em
- AcHXuROrHS/sDsnqu8FQp86MaudrqMExCOYyVPE7jaBWW+/JWFbKCxmgOCSdViUJ
- esJpBFsCgYEA7+jtVvSt9yrwsS/YU1QGP5wRAiDYB+T5cK4HytzAqJKRdC5qS4zf
- C7R0eKcDHHLMYO39aPnCwXjscisnInEhYGNblTDyPyiyNxAOXuC8x7luTmwzMbNJ
- /ow0IqSj0VF72VJN9uSoPpFd4lLT0zN8v42RWja0M8ohWNf+YNJluPgCFE0PT4Vm
- SUrCyZXsNh6VXwjs3gKQ
- -----END DSA PRIVATE KEY-----"""
- self.assertEqual(
- keys.Key.fromString(privateDSAData),
- keys.Key.fromString(privateDSAData.replace(b'\n', b'\r\n')))
- def test_fromLSHPublicUnsupportedType(self):
- """
- C{BadKeyError} exception is raised when public key has an unknown
- type.
- """
- sexp = sexpy.pack([[b'public-key', [b'bad-key', [b'p', b'2']]]])
- self.assertRaises(
- keys.BadKeyError,
- keys.Key.fromString, data=b'{' + base64.encodestring(sexp) + b'}',
- )
- def test_fromLSHPrivateUnsupportedType(self):
- """
- C{BadKeyError} exception is raised when private key has an unknown
- type.
- """
- sexp = sexpy.pack([[b'private-key', [b'bad-key', [b'p', b'2']]]])
- self.assertRaises(
- keys.BadKeyError,
- keys.Key.fromString, sexp,
- )
- def test_fromLSHRSA(self):
- """
- RSA public and private keys can be generated from a LSH strings.
- """
- self._testPublicPrivateFromString(
- keydata.publicRSA_lsh,
- keydata.privateRSA_lsh,
- 'RSA',
- keydata.RSAData,
- )
- def test_fromLSHDSA(self):
- """
- DSA public and private key can be generated from LSHs.
- """
- self._testPublicPrivateFromString(
- keydata.publicDSA_lsh,
- keydata.privateDSA_lsh,
- 'DSA',
- keydata.DSAData,
- )
- def test_fromAgentv3(self):
- """
- Test that keys are correctly generated from Agent v3 strings.
- """
- self._testPrivateFromString(keydata.privateRSA_agentv3, 'RSA',
- keydata.RSAData)
- self._testPrivateFromString(keydata.privateDSA_agentv3, 'DSA',
- keydata.DSAData)
- self.assertRaises(keys.BadKeyError, keys.Key.fromString,
- b'\x00\x00\x00\x07ssh-foo'+ b'\x00\x00\x00\x01\x01'*5)
- def test_fromStringErrors(self):
- """
- keys.Key.fromString should raise BadKeyError when the key is invalid.
- """
- self.assertRaises(keys.BadKeyError, keys.Key.fromString, b'')
- # no key data with a bad key type
- self.assertRaises(keys.BadKeyError, keys.Key.fromString, b'',
- 'bad_type')
- # trying to decrypt a key which doesn't support encryption
- self.assertRaises(keys.BadKeyError, keys.Key.fromString,
- keydata.publicRSA_lsh, passphrase = b'unencrypted')
- # trying to decrypt a key with the wrong passphrase
- self.assertRaises(keys.EncryptedKeyError, keys.Key.fromString,
- keys.Key(self.rsaObj).toString('openssh', b'encrypted'))
- # key with no key data
- self.assertRaises(keys.BadKeyError, keys.Key.fromString,
- b'-----BEGIN RSA KEY-----\nwA==\n')
- # key with invalid DEK Info
- self.assertRaises(
- keys.BadKeyError, keys.Key.fromString,
- b"""-----BEGIN ENCRYPTED RSA KEY-----
- Proc-Type: 4,ENCRYPTED
- DEK-Info: weird type
- 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
- T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
- g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
- sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
- 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
- gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
- 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
- vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
- hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
- 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
- qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
- 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
- EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
- 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
- fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
- V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
- 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
- xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
- dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
- VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
- gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
- 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
- SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
- CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
- xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
- -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
- # key with invalid encryption type
- self.assertRaises(
- keys.BadKeyError, keys.Key.fromString,
- b"""-----BEGIN ENCRYPTED RSA KEY-----
- Proc-Type: 4,ENCRYPTED
- DEK-Info: FOO-123-BAR,01234567
- 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
- T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
- g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
- sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
- 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
- gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
- 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
- vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
- hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
- 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
- qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
- 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
- EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
- 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
- fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
- V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
- 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
- xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
- dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
- VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
- gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
- 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
- SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
- CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
- xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
- -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
- # key with bad IV (AES)
- self.assertRaises(
- keys.BadKeyError, keys.Key.fromString,
- b"""-----BEGIN ENCRYPTED RSA KEY-----
- Proc-Type: 4,ENCRYPTED
- DEK-Info: AES-128-CBC,01234
- 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
- T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
- g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
- sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
- 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
- gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
- 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
- vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
- hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
- 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
- qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
- 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
- EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
- 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
- fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
- V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
- 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
- xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
- dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
- VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
- gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
- 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
- SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
- CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
- xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
- -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
- # key with bad IV (DES3)
- self.assertRaises(
- keys.BadKeyError, keys.Key.fromString,
- b"""-----BEGIN ENCRYPTED RSA KEY-----
- Proc-Type: 4,ENCRYPTED
- DEK-Info: DES-EDE3-CBC,01234
- 4Ed/a9OgJWHJsne7yOGWeWMzHYKsxuP9w1v0aYcp+puS75wvhHLiUnNwxz0KDi6n
- T3YkKLBsoCWS68ApR2J9yeQ6R+EyS+UQDrO9nwqo3DB5BT3Ggt8S1wE7vjNLQD0H
- g/SJnlqwsECNhh8aAx+Ag0m3ZKOZiRD5mCkcDQsZET7URSmFytDKOjhFn3u6ZFVB
- sXrfpYc6TJtOQlHd/52JB6aAbjt6afSv955Z7enIi+5yEJ5y7oYQTaE5zrFMP7N5
- 9LbfJFlKXxEddy/DErRLxEjmC+t4svHesoJKc2jjjyNPiOoGGF3kJXea62vsjdNV
- gMK5Eged3TBVIk2dv8rtJUvyFeCUtjQ1UJZIebScRR47KrbsIpCmU8I4/uHWm5hW
- 0mOwvdx1L/mqx/BHqVU9Dw2COhOdLbFxlFI92chkovkmNk4P48ziyVnpm7ME22sE
- vfCMsyirdqB1mrL4CSM7FXONv+CgfBfeYVkYW8RfJac9U1L/O+JNn7yee414O/rS
- hRYw4UdWnH6Gg6niklVKWNY0ZwUZC8zgm2iqy8YCYuneS37jC+OEKP+/s6HSKuqk
- 2bzcl3/TcZXNSM815hnFRpz0anuyAsvwPNRyvxG2/DacJHL1f6luV4B0o6W410yf
- qXQx01DLo7nuyhJqoH3UGCyyXB+/QUs0mbG2PAEn3f5dVs31JMdbt+PrxURXXjKk
- 4cexpUcIpqqlfpIRe3RD0sDVbH4OXsGhi2kiTfPZu7mgyFxKopRbn1KwU1qKinfY
- EU9O4PoTak/tPT+5jFNhaP+HrURoi/pU8EAUNSktl7xAkHYwkN/9Cm7DeBghgf3n
- 8+tyCGYDsB5utPD0/Xe9yx0Qhc/kMm4xIyQDyA937dk3mUvLC9vulnAP8I+Izim0
- fZ182+D1bWwykoD0997mUHG/AUChWR01V1OLwRyPv2wUtiS8VNG76Y2aqKlgqP1P
- V+IvIEqR4ERvSBVFzXNF8Y6j/sVxo8+aZw+d0L1Ns/R55deErGg3B8i/2EqGd3r+
- 0jps9BqFHHWW87n3VyEB3jWCMj8Vi2EJIfa/7pSaViFIQn8LiBLf+zxG5LTOToK5
- xkN42fReDcqi3UNfKNGnv4dsplyTR2hyx65lsj4bRKDGLKOuB1y7iB0AGb0LtcAI
- dcsVlcCeUquDXtqKvRnwfIMg+ZunyjqHBhj3qgRgbXbT6zjaSdNnih569aTg0Vup
- VykzZ7+n/KVcGLmvX0NesdoI7TKbq4TnEIOynuG5Sf+2GpARO5bjcWKSZeN/Ybgk
- gccf8Cqf6XWqiwlWd0B7BR3SymeHIaSymC45wmbgdstrbk7Ppa2Tp9AZku8M2Y7c
- 8mY9b+onK075/ypiwBm4L4GRNTFLnoNQJXx0OSl4FNRWsn6ztbD+jZhu8Seu10Jw
- SEJVJ+gmTKdRLYORJKyqhDet6g7kAxs4EoJ25WsOnX5nNr00rit+NkMPA7xbJT+7
- CfI51GQLw7pUPeO2WNt6yZO/YkzZrqvTj5FEwybkUyBv7L0gkqu9wjfDdUw0fVHE
- xEm4DxjEoaIp8dW/JOzXQ2EF+WaSOgdYsw3Ac+rnnjnNptCdOEDGP6QBkt+oXj4P
- -----END RSA PRIVATE KEY-----""", passphrase='encrypted')
- def test_fromFile(self):
- """
- Test that fromFile works correctly.
- """
- self.assertEqual(keys.Key.fromFile(self.keyFile),
- keys.Key.fromString(keydata.privateRSA_lsh))
- self.assertRaises(keys.BadKeyError, keys.Key.fromFile,
- self.keyFile, 'bad_type')
- self.assertRaises(keys.BadKeyError, keys.Key.fromFile,
- self.keyFile, passphrase='unencrypted')
- def test_init(self):
- """
- Test that the PublicKey object is initialized correctly.
- """
- obj = keys.Key._fromRSAComponents(n=long(5), e=long(3))._keyObject
- key = keys.Key(obj)
- self.assertEqual(key._keyObject, obj)
- def test_equal(self):
- """
- Test that Key objects are compared correctly.
- """
- rsa1 = keys.Key(self.rsaObj)
- rsa2 = keys.Key(self.rsaObj)
- rsa3 = keys.Key(
- keys.Key._fromRSAComponents(n=long(5), e=long(3))._keyObject)
- dsa = keys.Key(self.dsaObj)
- self.assertTrue(rsa1 == rsa2)
- self.assertFalse(rsa1 == rsa3)
- self.assertFalse(rsa1 == dsa)
- self.assertFalse(rsa1 == object)
- self.assertFalse(rsa1 == None)
- def test_notEqual(self):
- """
- Test that Key objects are not-compared correctly.
- """
- rsa1 = keys.Key(self.rsaObj)
- rsa2 = keys.Key(self.rsaObj)
- rsa3 = keys.Key(
- keys.Key._fromRSAComponents(n=long(5), e=long(3))._keyObject)
- dsa = keys.Key(self.dsaObj)
- self.assertFalse(rsa1 != rsa2)
- self.assertTrue(rsa1 != rsa3)
- self.assertTrue(rsa1 != dsa)
- self.assertTrue(rsa1 != object)
- self.assertTrue(rsa1 != None)
- def test_dataError(self):
- """
- The L{keys.Key.data} method raises RuntimeError for bad keys.
- """
- badKey = keys.Key(b'')
- self.assertRaises(RuntimeError, badKey.data)
- def test_fingerprintdefault(self):
- """
- Test that the fingerprint method returns fingerprint in
- L{FingerprintFormats.MD5-HEX} format by default.
- """
- self.assertEqual(keys.Key(self.rsaObj).fingerprint(),
- '3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af')
- self.assertEqual(keys.Key(self.dsaObj).fingerprint(),
- '63:15:b3:0e:e6:4f:50:de:91:48:3d:01:6b:b3:13:c1')
- def test_fingerprint_md5_hex(self):
- """
- fingerprint method generates key fingerprint in
- L{FingerprintFormats.MD5-HEX} format if explicitly specified.
- """
- self.assertEqual(
- keys.Key(self.rsaObj).fingerprint(
- keys.FingerprintFormats.MD5_HEX),
- '3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af')
- self.assertEqual(
- keys.Key(self.dsaObj).fingerprint(
- keys.FingerprintFormats.MD5_HEX),
- '63:15:b3:0e:e6:4f:50:de:91:48:3d:01:6b:b3:13:c1')
- def test_fingerprintsha256(self):
- """
- fingerprint method generates key fingerprint in
- L{FingerprintFormats.SHA256-BASE64} format if explicitly specified.
- """
- self.assertEqual(
- keys.Key(self.rsaObj).fingerprint(
- keys.FingerprintFormats.SHA256_BASE64),
- 'ryaugIFT0B8ItuszldMEU7q14rG/wj9HkRosMeBWkts=')
- self.assertEqual(
- keys.Key(self.dsaObj).fingerprint(
- keys.FingerprintFormats.SHA256_BASE64),
- 'Wz5o2YbKyxOEcJn1au/UaALSVruUzfz0vaLI1xiIGyY=')
- def test_fingerprintBadFormat(self):
- """
- A C{BadFingerPrintFormat} error is raised when unsupported
- formats are requested.
- """
- with self.assertRaises(keys.BadFingerPrintFormat) as em:
- keys.Key(self.rsaObj).fingerprint('sha256-base')
- self.assertEqual('Unsupported fingerprint format: sha256-base',
- em.exception.args[0])
- def test_type(self):
- """
- Test that the type method returns the correct type for an object.
- """
- self.assertEqual(keys.Key(self.rsaObj).type(), 'RSA')
- self.assertEqual(keys.Key(self.rsaObj).sshType(), b'ssh-rsa')
- self.assertEqual(keys.Key(self.dsaObj).type(), 'DSA')
- self.assertEqual(keys.Key(self.dsaObj).sshType(), b'ssh-dss')
- self.assertEqual(keys.Key(self.ecObj).type(), 'EC')
- self.assertEqual(keys.Key(self.ecObj).sshType(),
- keydata.ECDatanistp256['curve'])
- self.assertRaises(RuntimeError, keys.Key(None).type)
- self.assertRaises(RuntimeError, keys.Key(None).sshType)
- self.assertRaises(RuntimeError, keys.Key(self).type)
- self.assertRaises(RuntimeError, keys.Key(self).sshType)
- def test_fromBlobUnsupportedType(self):
- """
- A C{BadKeyError} error is raised whey the blob has an unsupported
- key type.
- """
- badBlob = common.NS(b'ssh-bad')
- self.assertRaises(keys.BadKeyError,
- keys.Key.fromString, badBlob)
- def test_fromBlobRSA(self):
- """
- A public RSA key is correctly generated from a public key blob.
- """
- rsaPublicData = {
- 'n': keydata.RSAData['n'],
- 'e': keydata.RSAData['e'],
- }
- rsaBlob = (
- common.NS(b'ssh-rsa') +
- common.MP(rsaPublicData['e']) +
- common.MP(rsaPublicData['n'])
- )
- rsaKey = keys.Key.fromString(rsaBlob)
- self.assertTrue(rsaKey.isPublic())
- self.assertEqual(rsaPublicData, rsaKey.data())
- def test_fromBlobDSA(self):
- """
- A public DSA key is correctly generated from a public key blob.
- """
- dsaPublicData = {
- 'p': keydata.DSAData['p'],
- 'q': keydata.DSAData['q'],
- 'g': keydata.DSAData['g'],
- 'y': keydata.DSAData['y'],
- }
- dsaBlob = (
- common.NS(b'ssh-dss') +
- common.MP(dsaPublicData['p']) +
- common.MP(dsaPublicData['q']) +
- common.MP(dsaPublicData['g']) +
- common.MP(dsaPublicData['y'])
- )
- dsaKey = keys.Key.fromString(dsaBlob)
- self.assertTrue(dsaKey.isPublic())
- self.assertEqual(dsaPublicData, dsaKey.data())
- def test_fromBlobECDSA(self):
- """
- Key.fromString generates ECDSA keys from blobs.
- """
- from cryptography import utils
- ecPublicData = {
- 'x': keydata.ECDatanistp256['x'],
- 'y': keydata.ECDatanistp256['y'],
- 'curve': keydata.ECDatanistp256['curve']
- }
- ecblob = (common.NS(ecPublicData['curve']) +
- common.NS(ecPublicData['curve'][-8:]) +
- common.NS(b'\x04' +
- utils.int_to_bytes(ecPublicData['x'], 32) +
- utils.int_to_bytes(ecPublicData['y'], 32))
- )
- eckey = keys.Key.fromString(ecblob)
- self.assertTrue(eckey.isPublic())
- self.assertEqual(ecPublicData, eckey.data())
- def test_fromPrivateBlobUnsupportedType(self):
- """
- C{BadKeyError} is raised when loading a private blob with an
- unsupported type.
- """
- badBlob = common.NS(b'ssh-bad')
- self.assertRaises(
- keys.BadKeyError, keys.Key._fromString_PRIVATE_BLOB, badBlob)
- def test_fromPrivateBlobRSA(self):
- """
- A private RSA key is correctly generated from a private key blob.
- """
- rsaBlob = (
- common.NS(b'ssh-rsa') +
- common.MP(keydata.RSAData['n']) +
- common.MP(keydata.RSAData['e']) +
- common.MP(keydata.RSAData['d']) +
- common.MP(keydata.RSAData['u']) +
- common.MP(keydata.RSAData['p']) +
- common.MP(keydata.RSAData['q'])
- )
- rsaKey = keys.Key._fromString_PRIVATE_BLOB(rsaBlob)
- self.assertFalse(rsaKey.isPublic())
- self.assertEqual(keydata.RSAData, rsaKey.data())
- def test_fromPrivateBlobDSA(self):
- """
- A private DSA key is correctly generated from a private key blob.
- """
- dsaBlob = (
- common.NS(b'ssh-dss') +
- common.MP(keydata.DSAData['p']) +
- common.MP(keydata.DSAData['q']) +
- common.MP(keydata.DSAData['g']) +
- common.MP(keydata.DSAData['y']) +
- common.MP(keydata.DSAData['x'])
- )
- dsaKey = keys.Key._fromString_PRIVATE_BLOB(dsaBlob)
- self.assertFalse(dsaKey.isPublic())
- self.assertEqual(keydata.DSAData, dsaKey.data())
- def test_fromPrivateBlobECDSA(self):
- """
- A private EC key is correctly generated from a private key blob.
- """
- ecblob = (
- common.NS(keydata.ECDatanistp256['curve']) +
- common.MP(keydata.ECDatanistp256['x']) +
- common.MP(keydata.ECDatanistp256['y']) +
- common.MP(keydata.ECDatanistp256['privateValue'])
- )
- eckey = keys.Key._fromString_PRIVATE_BLOB(ecblob)
- self.assertFalse(eckey.isPublic())
- self.assertEqual(keydata.ECDatanistp256, eckey.data())
- def test_blobRSA(self):
- """
- Return the over-the-wire SSH format of the RSA public key.
- """
- self.assertEqual(
- keys.Key(self.rsaObj).blob(),
- common.NS(b'ssh-rsa') +
- common.MP(self.rsaObj.private_numbers().public_numbers.e) +
- common.MP(self.rsaObj.private_numbers().public_numbers.n)
- )
- def test_blobDSA(self):
- """
- Return the over-the-wire SSH format of the DSA public key.
- """
- publicNumbers = self.dsaObj.private_numbers().public_numbers
- self.assertEqual(
- keys.Key(self.dsaObj).blob(),
- common.NS(b'ssh-dss') +
- common.MP(publicNumbers.parameter_numbers.p) +
- common.MP(publicNumbers.parameter_numbers.q) +
- common.MP(publicNumbers.parameter_numbers.g) +
- common.MP(publicNumbers.y)
- )
- def test_blobEC(self):
- """
- Return the over-the-wire SSH format of the EC public key.
- """
- from cryptography import utils
- byteLength = (self.ecObj.curve.key_size + 7) // 8
- self.assertEqual(
- keys.Key(self.ecObj).blob(),
- common.NS(keydata.ECDatanistp256['curve']) +
- common.NS(keydata.ECDatanistp256['curve'][-8:]) +
- common.NS(b'\x04' +
- utils.int_to_bytes(
- self.ecObj.private_numbers().public_numbers.x, byteLength) +
- utils.int_to_bytes(
- self.ecObj.private_numbers().public_numbers.y, byteLength))
- )
- def test_blobNoKey(self):
- """
- C{RuntimeError} is raised when the blob is requested for a Key
- which is not wrapping anything.
- """
- badKey = keys.Key(None)
- self.assertRaises(RuntimeError, badKey.blob)
- def test_privateBlobRSA(self):
- """
- L{keys.Key.privateBlob} returns the SSH protocol-level format of an
- RSA private key.
- """
- from cryptography.hazmat.primitives.asymmetric import rsa
- numbers = self.rsaObj.private_numbers()
- u = rsa.rsa_crt_iqmp(numbers.q, numbers.p)
- self.assertEqual(
- keys.Key(self.rsaObj).privateBlob(),
- common.NS(b'ssh-rsa') +
- common.MP(self.rsaObj.private_numbers().public_numbers.n) +
- common.MP(self.rsaObj.private_numbers().public_numbers.e) +
- common.MP(self.rsaObj.private_numbers().d) +
- common.MP(u) +
- common.MP(self.rsaObj.private_numbers().p) +
- common.MP(self.rsaObj.private_numbers().q)
- )
- def test_privateBlobDSA(self):
- """
- L{keys.Key.privateBlob} returns the SSH protocol-level format of a DSA
- private key.
- """
- publicNumbers = self.dsaObj.private_numbers().public_numbers
- self.assertEqual(
- keys.Key(self.dsaObj).privateBlob(),
- common.NS(b'ssh-dss') +
- common.MP(publicNumbers.parameter_numbers.p) +
- common.MP(publicNumbers.parameter_numbers.q) +
- common.MP(publicNumbers.parameter_numbers.g) +
- common.MP(publicNumbers.y) +
- common.MP(self.dsaObj.private_numbers().x)
- )
- def test_privateBlobEC(self):
- """
- L{keys.Key.privateBlob} returns the SSH ptotocol-level format of EC
- private key.
- """
- self.assertEqual(
- keys.Key(self.ecObj).privateBlob(),
- common.NS(keydata.ECDatanistp256['curve']) +
- common.MP(self.ecObj.private_numbers().public_numbers.x) +
- common.MP(self.ecObj.private_numbers().public_numbers.y) +
- common.MP(self.ecObj.private_numbers().private_value)
- )
- def test_privateBlobNoKeyObject(self):
- """
- Raises L{RuntimeError} if the underlying key object does not exists.
- """
- badKey = keys.Key(None)
- self.assertRaises(RuntimeError, badKey.privateBlob)
- def test_toOpenSSHRSA(self):
- """
- L{keys.Key.toString} serializes an RSA key in OpenSSH format.
- """
- key = keys.Key.fromString(keydata.privateRSA_agentv3)
- self.assertEqual(key.toString('openssh'), keydata.privateRSA_openssh)
- self.assertEqual(key.toString('openssh', b'encrypted'),
- keydata.privateRSA_openssh_encrypted)
- self.assertEqual(key.public().toString('openssh'),
- keydata.publicRSA_openssh[:-8]) # no comment
- self.assertEqual(key.public().toString('openssh', b'comment'),
- keydata.publicRSA_openssh)
- def test_toOpenSSHDSA(self):
- """
- L{keys.Key.toString} serializes a DSA key in OpenSSH format.
- """
- key = keys.Key.fromString(keydata.privateDSA_lsh)
- self.assertEqual(key.toString('openssh'), keydata.privateDSA_openssh)
- self.assertEqual(key.public().toString('openssh', b'comment'),
- keydata.publicDSA_openssh)
- self.assertEqual(key.public().toString('openssh'),
- keydata.publicDSA_openssh[:-8]) # no comment
- def test_toOpenSSHECDSA(self):
- """
- L{keys.Key.toString} serializes a ECDSA key in OpenSSH format.
- """
- key = keys.Key.fromString(keydata.privateECDSA_openssh)
- self.assertEqual(key.public().toString('openssh', b'comment'),
- keydata.publicECDSA_openssh)
- self.assertEqual(key.public().toString('openssh'),
- keydata.publicECDSA_openssh[:-8]) # no comment
- def test_toLSHRSA(self):
- """
- L{keys.Key.toString} serializes an RSA key in LSH format.
- """
- key = keys.Key.fromString(keydata.privateRSA_openssh)
- self.assertEqual(key.toString('lsh'), keydata.privateRSA_lsh)
- self.assertEqual(key.public().toString('lsh'),
- keydata.publicRSA_lsh)
- def test_toLSHDSA(self):
- """
- L{keys.Key.toString} serializes a DSA key in LSH format.
- """
- key = keys.Key.fromString(keydata.privateDSA_openssh)
- self.assertEqual(key.toString('lsh'), keydata.privateDSA_lsh)
- self.assertEqual(key.public().toString('lsh'),
- keydata.publicDSA_lsh)
- def test_toAgentv3RSA(self):
- """
- L{keys.Key.toString} serializes an RSA key in Agent v3 format.
- """
- key = keys.Key.fromString(keydata.privateRSA_openssh)
- self.assertEqual(key.toString('agentv3'), keydata.privateRSA_agentv3)
- def test_toAgentv3DSA(self):
- """
- L{keys.Key.toString} serializes a DSA key in Agent v3 format.
- """
- key = keys.Key.fromString(keydata.privateDSA_openssh)
- self.assertEqual(key.toString('agentv3'), keydata.privateDSA_agentv3)
- def test_toStringErrors(self):
- """
- L{keys.Key.toString} raises L{keys.BadKeyError} when passed an invalid
- format type.
- """
- self.assertRaises(keys.BadKeyError, keys.Key(self.rsaObj).toString,
- 'bad_type')
- def test_signAndVerifyRSA(self):
- """
- Signed data can be verified using RSA.
- """
- data = b'some-data'
- key = keys.Key.fromString(keydata.privateRSA_openssh)
- signature = key.sign(data)
- self.assertTrue(key.public().verify(signature, data))
- self.assertTrue(key.verify(signature, data))
- def test_signAndVerifyDSA(self):
- """
- Signed data can be verified using DSA.
- """
- data = b'some-data'
- key = keys.Key.fromString(keydata.privateDSA_openssh)
- signature = key.sign(data)
- self.assertTrue(key.public().verify(signature, data))
- self.assertTrue(key.verify(signature, data))
- def test_signAndVerifyEC(self):
- """
- Signed data can be verified using EC.
- """
- data = b'some-data'
- key = keys.Key.fromString(keydata.privateECDSA_openssh)
- signature = key.sign(data)
- key384 = keys.Key.fromString(keydata.privateECDSA_openssh384)
- signature384 = key384.sign(data)
- key521 = keys.Key.fromString(keydata.privateECDSA_openssh521)
- signature521 = key521.sign(data)
- self.assertTrue(key.public().verify(signature, data))
- self.assertTrue(key.verify(signature, data))
- self.assertTrue(key384.public().verify(signature384, data))
- self.assertTrue(key384.verify(signature384, data))
- self.assertTrue(key521.public().verify(signature521, data))
- self.assertTrue(key521.verify(signature521, data))
- def test_verifyRSA(self):
- """
- A known-good RSA signature verifies successfully.
- """
- key = keys.Key.fromString(keydata.publicRSA_openssh)
- self.assertTrue(key.verify(self.rsaSignature, b''))
- self.assertFalse(key.verify(self.rsaSignature, b'a'))
- self.assertFalse(key.verify(self.dsaSignature, b''))
- def test_verifyDSA(self):
- """
- A known-good DSA signature verifies successfully.
- """
- key = keys.Key.fromString(keydata.publicDSA_openssh)
- self.assertTrue(key.verify(self.dsaSignature, b''))
- self.assertFalse(key.verify(self.dsaSignature, b'a'))
- self.assertFalse(key.verify(self.rsaSignature, b''))
- def test_verifyDSANoPrefix(self):
- """
- Some commercial SSH servers send DSA keys as 2 20-byte numbers;
- they are still verified as valid keys.
- """
- key = keys.Key.fromString(keydata.publicDSA_openssh)
- self.assertTrue(key.verify(self.dsaSignature[-40:], b''))
- def test_reprPrivateRSA(self):
- """
- The repr of a L{keys.Key} contains all of the RSA components for an RSA
- private key.
- """
- self.assertEqual(repr(keys.Key(self.rsaObj)),
- """<RSA Private Key (768 bits)
- attr d:
- \t6e:1f:b5:55:97:eb:ed:67:ed:2b:99:6e:ec:c1:ed:
- \ta8:4d:52:d6:f3:d6:65:06:04:df:e5:54:9f:cc:89:
- \t00:3c:9b:67:87:ec:65:a0:ab:cd:6f:65:90:8a:97:
- \t90:4d:c6:21:8f:a8:8d:d8:59:86:43:b5:81:b1:b4:
- \td7:5f:2c:22:0a:61:c1:25:8a:47:12:b4:9a:f8:7a:
- \t11:1c:4a:a8:8b:75:c4:91:09:3b:be:04:ca:45:d9:
- \t57:8a:0d:27:cb:23
- attr e:
- \t23
- attr n:
- \t00:af:32:71:f0:e6:0e:9c:99:b3:7f:8b:5f:04:4b:
- \tcb:8b:c0:d5:3e:b2:77:fd:cf:64:d8:8f:c0:cf:ae:
- \t1f:c6:31:df:f6:29:b2:44:96:e2:c6:d4:21:94:7f:
- \t65:7c:d8:d4:23:1f:b8:2e:6a:c9:1f:94:0d:46:c1:
- \t69:a2:b7:07:0c:a3:93:c1:34:d8:2e:1e:4a:99:1a:
- \t6c:96:46:07:46:2b:dc:25:29:1b:87:f0:be:05:1d:
- \tee:b4:34:b9:e7:99:95
- attr p:
- \t00:cb:4a:4b:d0:40:47:e8:45:52:f7:c7:af:0c:20:
- \t6d:43:0d:b6:39:94:f9:da:a5:e5:03:06:76:83:24:
- \teb:88:a1:55:a2:a8:de:12:3b:77:49:92:8a:a9:71:
- \td2:02:93:ff
- attr q:
- \t00:dc:9f:6b:d9:98:21:56:11:8d:e9:5f:03:9d:0a:
- \td3:93:6e:13:77:41:3c:85:4f:00:70:fd:05:54:ff:
- \tbc:3d:09:bf:83:f6:97:7f:64:10:91:04:fe:a2:67:
- \t47:54:42:6b
- attr u:
- \t00:b4:73:97:4b:50:10:a3:17:b3:a8:47:f1:3a:14:
- \t76:52:d1:38:2a:cf:12:14:34:c1:a8:54:4c:29:35:
- \t80:a0:38:b8:f0:fa:4c:c4:c2:85:ab:db:87:82:ba:
- \tdc:eb:db:2a>""")
- def test_reprPublicRSA(self):
- """
- The repr of a L{keys.Key} contains all of the RSA components for an RSA
- public key.
- """
- self.assertEqual(repr(keys.Key(self.rsaObj).public()),
- """<RSA Public Key (768 bits)
- attr e:
- \t23
- attr n:
- \t00:af:32:71:f0:e6:0e:9c:99:b3:7f:8b:5f:04:4b:
- \tcb:8b:c0:d5:3e:b2:77:fd:cf:64:d8:8f:c0:cf:ae:
- \t1f:c6:31:df:f6:29:b2:44:96:e2:c6:d4:21:94:7f:
- \t65:7c:d8:d4:23:1f:b8:2e:6a:c9:1f:94:0d:46:c1:
- \t69:a2:b7:07:0c:a3:93:c1:34:d8:2e:1e:4a:99:1a:
- \t6c:96:46:07:46:2b:dc:25:29:1b:87:f0:be:05:1d:
- \tee:b4:34:b9:e7:99:95>""")
- def test_reprPublicECDSA(self):
- """
- The repr of a L{keys.Key} contains all the OpenSSH format for an ECDSA
- public key.
- """
- self.assertEqual(repr(keys.Key(self.ecObj).public()),
- """<Elliptic Curve Public Key (256 bits)
- curve:
- \tecdsa-sha2-nistp256
- x:
- \t76282513020392096317118503144964731774299773481750550543382904345687059013883
- y:""" +
- "\n\t8154319786460285263226566476944164753434437589431431968106113715931064" +
- "6683104>\n")
- def test_reprPrivateECDSA(self):
- """
- The repr of a L{keys.Key} contains all the OpenSSH format for an ECDSA
- private key.
- """
- self.assertEqual(repr(keys.Key(self.ecObj)),
- """<Elliptic Curve Private Key (256 bits)
- curve:
- \tecdsa-sha2-nistp256
- privateValue:
- \t34638743477210341700964008455655698253555655678826059678074967909361042656500
- x:
- \t76282513020392096317118503144964731774299773481750550543382904345687059013883
- y:""" +
- "\n\t8154319786460285263226566476944164753434437589431431968106113715931064" +
- "6683104>\n")
- class KeyKeyObjectTests(unittest.TestCase):
- """
- The L{keys.Key.keyObject} property provides deprecated access to a PyCrypto
- key instance of the corresponding type.
- """
- if cryptography is None:
- skip = skipCryptography
- if Crypto is None:
- skip = skipPyCrypto
- def test_deprecation(self):
- """
- Accessing the L{keys.Key.keyObject} property emits a deprecation
- warning.
- """
- keys.Key.fromString(keydata.publicRSA_openssh).keyObject
- [warning] = self.flushWarnings([KeyKeyObjectTests.test_deprecation])
- self.assertIs(warning['category'], DeprecationWarning)
- def test_keyObjectGetRSAPublic(self):
- """
- The PyCrypto key instance for an RSA public key has the same components
- as the internal key.
- """
- key = keys.Key.fromString(keydata.publicRSA_openssh)
- result = key.keyObject
- self.assertIsInstance(result, Crypto.PublicKey.RSA._RSAobj)
- self.assertEqual(keydata.RSAData['e'], result.key.e)
- self.assertEqual(keydata.RSAData['n'], result.key.n)
- def test_keyObjectGetRSAPrivate(self):
- """
- The PyCrypto key instance for an RSA private key has the same
- components as the internal key.
- """
- key = keys.Key.fromString(keydata.privateRSA_openssh)
- result = key.keyObject
- self.assertIsInstance(result, Crypto.PublicKey.RSA._RSAobj)
- self.assertEqual(keydata.RSAData['e'], result.key.e)
- self.assertEqual(keydata.RSAData['n'], result.key.n)
- self.assertEqual(keydata.RSAData['d'], result.key.d)
- self.assertEqual(keydata.RSAData['p'], result.key.p)
- self.assertEqual(keydata.RSAData['q'], result.key.q)
- self.assertEqual(keydata.RSAData['u'], result.key.u)
- def test_keyObjectGetDSAPublic(self):
- """
- The PyCrypto key instance for a DSA public key has the same components
- as the internal key.
- """
- key = keys.Key.fromString(keydata.publicDSA_openssh)
- result = key.keyObject
- self.assertIsInstance(result, Crypto.PublicKey.DSA._DSAobj)
- self.assertEqual(keydata.DSAData['y'], result.key.y)
- self.assertEqual(keydata.DSAData['g'], result.key.g)
- self.assertEqual(keydata.DSAData['p'], result.key.p)
- self.assertEqual(keydata.DSAData['q'], result.key.q)
- def test_keyObjectGetDSAPrivate(self):
- """
- The PyCrypto key instance for a DSA private key has the same components
- as the internal key.
- """
- key = keys.Key.fromString(keydata.privateDSA_openssh)
- result = key.keyObject
- self.assertIsInstance(result, Crypto.PublicKey.DSA._DSAobj)
- self.assertEqual(keydata.DSAData['y'], result.key.y)
- self.assertEqual(keydata.DSAData['g'], result.key.g)
- self.assertEqual(keydata.DSAData['p'], result.key.p)
- self.assertEqual(keydata.DSAData['q'], result.key.q)
- self.assertEqual(keydata.DSAData['x'], result.key.x)
- def test_keyObjectSetRSAPublic(self):
- """
- Setting the L{keys.Key.keyObject} property to a PyCrypto public RSA key
- instance updates the internal key.
- """
- key = keys.Key.fromString(keydata.publicDSA_openssh)
- newPyCryptoKey = Crypto.PublicKey.RSA.construct((
- keydata.RSAData['n'],
- keydata.RSAData['e'],
- ))
- self.assertEqual('DSA', key.type())
- key.keyObject = newPyCryptoKey
- [warning] = self.flushWarnings([
- KeyKeyObjectTests.test_keyObjectSetRSAPublic])
- self.assertIs(warning['category'], DeprecationWarning)
- self.assertEqual('RSA', key.type())
- self.assertEqual({
- 'n': keydata.RSAData['n'],
- 'e': keydata.RSAData['e'],
- },
- key.data())
- def test_keyObjectSetRSAPrivate(self):
- """
- Setting the L{keys.Key.keyObject} property to a PyCrypto private RSA
- key instance updates the internal key.
- """
- key = keys.Key.fromString(keydata.publicDSA_openssh)
- newPyCryptoKey = Crypto.PublicKey.RSA.construct((
- keydata.RSAData['n'],
- keydata.RSAData['e'],
- keydata.RSAData['d'],
- keydata.RSAData['p'],
- keydata.RSAData['q'],
- keydata.RSAData['u'],
- ))
- self.assertEqual('DSA', key.type())
- key.keyObject = newPyCryptoKey
- self.assertEqual('RSA', key.type())
- self.assertEqual({
- 'n': keydata.RSAData['n'],
- 'e': keydata.RSAData['e'],
- 'd': keydata.RSAData['d'],
- 'p': keydata.RSAData['p'],
- 'q': keydata.RSAData['q'],
- 'u': keydata.RSAData['u'],
- },
- key.data())
- def test_keyObjectSetDSAPublic(self):
- """
- Setting the L{keys.Key.keyObject} property to a PyCrypto public DSA key
- instance updates the internal key.
- """
- key = keys.Key.fromString(keydata.publicRSA_openssh)
- newPyCryptoKey = Crypto.PublicKey.DSA.construct((
- keydata.DSAData['y'],
- keydata.DSAData['g'],
- keydata.DSAData['p'],
- keydata.DSAData['q'],
- ))
- self.assertEqual('RSA', key.type())
- key.keyObject = newPyCryptoKey
- self.assertEqual('DSA', key.type())
- self.assertEqual({
- 'y': keydata.DSAData['y'],
- 'g': keydata.DSAData['g'],
- 'p': keydata.DSAData['p'],
- 'q': keydata.DSAData['q'],
- },
- key.data())
- def test_keyObjectSetDSAPrivate(self):
- """
- Setting the L{keys.Key.keyObject} property to a PyCrypto private DSA
- key instance updates the internal key.
- """
- key = keys.Key.fromString(keydata.publicRSA_openssh)
- newPyCryptoKey = Crypto.PublicKey.DSA.construct((
- keydata.DSAData['y'],
- keydata.DSAData['g'],
- keydata.DSAData['p'],
- keydata.DSAData['q'],
- keydata.DSAData['x'],
- ))
- self.assertEqual('RSA', key.type())
- key.keyObject = newPyCryptoKey
- self.assertEqual('DSA', key.type())
- self.assertEqual({
- 'y': keydata.DSAData['y'],
- 'g': keydata.DSAData['g'],
- 'p': keydata.DSAData['p'],
- 'q': keydata.DSAData['q'],
- 'x': keydata.DSAData['x'],
- },
- key.data())
- def test_constructorPyCrypto(self):
- """
- Passing a PyCrypto key object to L{keys.Key} is deprecated.
- """
- pycryptoKey = Crypto.PublicKey.RSA.construct((
- keydata.RSAData['n'],
- keydata.RSAData['e']))
- key = self.callDeprecated(
- (Version('Twisted', 16, 0, 0),
- 'passing a cryptography key object'),
- keys.Key,
- pycryptoKey)
- self.assertEqual('RSA', key.type())
- self.assertEqual({
- 'n': keydata.RSAData['n'],
- 'e': keydata.RSAData['e'],
- },
- key.data())
- class PersistentRSAKeyTests(unittest.TestCase):
- """
- Tests for L{keys._getPersistentRSAKey}.
- """
- if cryptography is None:
- skip = skipCryptography
- def test_providedArguments(self):
- """
- L{keys._getPersistentRSAKey} will put the key in
- C{directory}/C{filename}, with the key length of C{keySize}.
- """
- tempDir = FilePath(self.mktemp())
- keyFile = tempDir.child("mykey.pem")
- key = keys._getPersistentRSAKey(keyFile, keySize=512)
- self.assertEqual(key.size(), 512)
- self.assertTrue(keyFile.exists())
- def test_noRegeneration(self):
- """
- L{keys._getPersistentRSAKey} will not regenerate the key if the key
- already exists.
- """
- tempDir = FilePath(self.mktemp())
- keyFile = tempDir.child("mykey.pem")
- key = keys._getPersistentRSAKey(keyFile, keySize=512)
- self.assertEqual(key.size(), 512)
- self.assertTrue(keyFile.exists())
- keyContent = keyFile.getContent()
- # Set the key size to 1024 bits. Since it exists already, it will find
- # the 512 bit key, and not generate a 1024 bit key.
- key = keys._getPersistentRSAKey(keyFile, keySize=1024)
- self.assertEqual(key.size(), 512)
- self.assertEqual(keyFile.getContent(), keyContent)
- def test_keySizeZero(self):
- """
- If the key generated by L{keys.getPersistentRSAKey} is set to None
- the key size should then become 0.
- """
- tempDir = FilePath(self.mktemp())
- keyFile = tempDir.child("mykey.pem")
- key = keys._getPersistentRSAKey(keyFile, keySize=512)
- key._keyObject = None
- self.assertEqual( key.size(), 0)
|