1
# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
Tests for L{twisted.conch.ssh.keys}.
9
import Crypto.Cipher.DES3
11
# we'll have to skip these tests without PyCypto and pyasn1
20
from twisted.conch.ssh import asn1, keys, common, sexpy
23
from twisted.conch.test import keydata
24
from twisted.python import randbytes
25
from twisted.python.hashlib import sha1
26
from twisted.trial import unittest
28
class SSHKeysHandlingTestCase(unittest.TestCase):
30
test the handling of reading/signing/verifying with RSA and DSA keys
31
assumed test keys are in test/
35
skip = "cannot run w/o PyCrypto"
37
skip = "cannot run w/o/ PyASN1"
40
self.tmpdir = self.mktemp()
42
self.privateKeyFile = os.path.join(self.tmpdir, 'private')
43
self.publicKeyFile = os.path.join(self.tmpdir, 'public')
44
file(self.privateKeyFile, 'wb').write(keydata.privateRSA_openssh)
45
file(self.publicKeyFile, 'wb').write('first line\n' +
46
keydata.publicRSA_openssh)
48
def test_readFile(self):
50
Test that reading a key from a file works as expected.
52
self.assertEquals(self.assertWarns(DeprecationWarning,
53
"getPublicKeyString is deprecated since Twisted Conch 0.9. "
54
"Use Key.fromString().blob().", unittest.__file__,
55
keys.getPublicKeyString, self.publicKeyFile, 1),
56
keys.Key.fromString(keydata.publicRSA_openssh).blob())
57
self.assertEquals(self.assertWarns(DeprecationWarning,
58
"getPrivateKeyObject is deprecated since Twisted Conch 0.9. "
59
"Use Key.fromString().", unittest.__file__,
60
keys.getPrivateKeyObject, self.privateKeyFile),
61
keys.Key.fromString(keydata.privateRSA_openssh).keyObject)
65
Test DSA keys using both OpenSSH and LSH formats.
67
self._testKey(keydata.publicDSA_openssh, keydata.privateDSA_openssh,
68
keydata.DSAData, 'openssh')
69
self._testKey(keydata.publicDSA_lsh, keydata.privateDSA_lsh,
70
keydata.DSAData,'lsh')
71
obj = self.assertWarns(DeprecationWarning, "getPrivateKeyObject is "
72
"deprecated since Twisted Conch 0.9. Use Key.fromString().",
73
unittest.__file__, keys.getPrivateKeyObject,
74
data=keydata.privateDSA_agentv3)
75
self._testGeneratePrivateKey(obj, keydata.privateDSA_agentv3,
80
Same as test_DSA but for RSA keys.
82
self._testKey(keydata.publicRSA_openssh, keydata.privateRSA_openssh,
83
keydata.RSAData, 'openssh')
84
self._testKey(keydata.publicRSA_lsh, keydata.privateRSA_lsh,
85
keydata.RSAData, 'lsh')
86
obj = self.assertWarns(DeprecationWarning, "getPrivateKeyObject is "
87
"deprecated since Twisted Conch 0.9. Use Key.fromString().",
88
unittest.__file__, keys.getPrivateKeyObject,
89
data=keydata.privateRSA_agentv3)
90
self._testGeneratePrivateKey(obj, keydata.privateRSA_agentv3,
94
def test_fingerprint(self):
96
L{Key.fingerprint} returns a hex-encoded colon-separated md5 sum of the
100
'3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af',
101
keys.Key.fromString(keydata.publicRSA_openssh).fingerprint())
104
def _testKey(self, pubStr, privStr, data, keyType):
106
Run each of the key tests with the public/private keypairs.
108
@param pubStr: The data for a public key in the format defined by
110
@param privStr: The data for a private key in the format defined by
112
@param data: The numerical values encoded in the key.
113
@param keyType: the type of the public and private key data: either
116
pubBlob = self.assertWarns(DeprecationWarning, "getPublicKeyString is "
117
"deprecated since Twisted Conch 0.9. "
118
"Use Key.fromString().blob().",
119
unittest.__file__, keys.getPublicKeyString, data=pubStr)
120
pubObj = self.assertWarns(DeprecationWarning, "getPublicKeyObject is "
121
"deprecated since Twisted Conch 0.9. Use Key.fromString().",
122
unittest.__file__, keys.getPublicKeyObject, pubBlob)
123
privObj = self.assertWarns(DeprecationWarning, "getPrivateKeyObject is "
124
"deprecated since Twisted Conch 0.9. Use Key.fromString().",
125
unittest.__file__, keys.getPrivateKeyObject, data=privStr)
127
self._testKeySignVerify(privObj, pubObj)
128
self._testKeyFromString(privObj, pubObj, data, keyType)
129
self._testGeneratePublicKey(privObj, pubObj, pubStr, keyType)
130
self._testGeneratePrivateKey(privObj, privStr, keyType)
131
self._testGenerateBlob(privObj, pubObj, pubBlob)
133
def _testKeySignVerify(self, privObj, pubObj):
135
Test that signing and verifying works correctly.
136
@param privObj: a private key object.
137
@type privObj: C{Crypto.PublicKey.pubkey.pubkey}
138
@param pubObj: a public key object.
139
@type pubObj: C{Crypto.PublicKey.pubkey.pubkey}
142
testData = 'this is the test data'
143
sig = self.assertWarns(DeprecationWarning,
144
"signData is deprecated since Twisted Conch 0.9. "
145
"Use Key(obj).sign(data).", unittest.__file__, keys.signData,
147
self.assertTrue(self.assertWarns(DeprecationWarning,
148
"verifySignature is deprecated since Twisted Conch 0.9. "
149
"Use Key(obj).verify(signature, data).", unittest.__file__,
150
keys.verifySignature, privObj, sig, testData),
151
'verifying with private %s failed' %
152
keys.objectType(privObj))
154
self.assertTrue(self.assertWarns(DeprecationWarning,
155
"verifySignature is deprecated since Twisted Conch 0.9. "
156
"Use Key(obj).verify(signature, data).", unittest.__file__,
157
keys.verifySignature, pubObj, sig, testData),
158
'verifying with public %s failed' %
159
keys.objectType(pubObj))
161
self.failIf(self.assertWarns(DeprecationWarning,
162
"verifySignature is deprecated since Twisted Conch 0.9. "
163
"Use Key(obj).verify(signature, data).", unittest.__file__,
164
keys.verifySignature,privObj, sig, 'other data'),
165
'verified bad data with %s' %
166
keys.objectType(privObj))
168
self.failIf(self.assertWarns(DeprecationWarning,
169
"verifySignature is deprecated since Twisted Conch 0.9. "
170
"Use Key(obj).verify(signature, data).", unittest.__file__,
171
keys.verifySignature, privObj, 'bad sig', testData),
172
'verified badsign with %s' %
173
keys.objectType(privObj))
175
def _testKeyFromString(self, privObj, pubObj, data, keyType):
177
Test key object generation from a string. The public key objects
178
were generated in _testKey; just check that they were created
181
for k in data.keys():
182
self.assertEquals(getattr(privObj, k), data[k])
183
for k in pubObj.keydata:
184
if hasattr(pubObj, k): # public key objects don't have all the
186
self.assertEquals(getattr(pubObj, k), data[k])
188
def _testGeneratePublicKey(self, privObj, pubObj, pubStr, keyType):
190
Test public key string generation from an object.
192
self.assertEquals(self.assertWarns(DeprecationWarning,
193
"makePublicKeyString is deprecated since Twisted Conch 0.9. "
194
"Use Key(obj).public().toString().", unittest.__file__,
195
keys.makePublicKeyString, pubObj, 'comment',
197
self.assertEquals(self.assertWarns(DeprecationWarning,
198
"makePublicKeyString is deprecated since Twisted Conch 0.9. "
199
"Use Key(obj).public().toString().", unittest.__file__,
200
keys.makePublicKeyString, privObj, 'comment',
203
def _testGeneratePrivateKey(self, privObj, privStr, keyType):
205
Test private key string generation from an object.
207
self.assertEquals(self.assertWarns(DeprecationWarning,
208
"makePrivateKeyString is deprecated since Twisted Conch 0.9. "
209
"Use Key(obj).toString().", unittest.__file__,
210
keys.makePrivateKeyString, privObj, kind=keyType),
212
if keyType == 'openssh':
213
encData = self.assertWarns(DeprecationWarning,
214
"makePrivateKeyString is deprecated since Twisted Conch "
215
"0.9. Use Key(obj).toString().", unittest.__file__,
216
keys.makePrivateKeyString, privObj, passphrase='test',
218
self.assertEquals(self.assertWarns(DeprecationWarning,
219
"getPrivateKeyObject is deprecated since Twisted Conch 0.9. "
220
"Use Key.fromString().", unittest.__file__,
221
keys.getPrivateKeyObject, data = encData, passphrase='test'),
224
def _testGenerateBlob(self, privObj, pubObj, pubBlob):
226
Test wire-format blob generation.
228
self.assertEquals(self.assertWarns(DeprecationWarning,
229
"makePublicKeyBlob is deprecated since Twisted Conch 0.9. "
230
"Use Key(obj).blob().", unittest.__file__,
231
keys.makePublicKeyBlob, pubObj), pubBlob)
232
self.assertEquals(self.assertWarns(DeprecationWarning,
233
"makePublicKeyBlob is deprecated since Twisted Conch 0.9. "
234
"Use Key(obj).blob().", unittest.__file__,
235
keys.makePublicKeyBlob, privObj), pubBlob)
237
def test_getPublicKeyStringErrors(self):
239
Test that getPublicKeyString raises errors in appropriate cases.
241
self.assertWarns(DeprecationWarning, "getPublicKeyString is deprecated"
242
" since Twisted Conch 0.9. Use Key.fromString().blob().",
243
unittest.__file__, self.assertRaises, keys.BadKeyError,
244
keys.getPublicKeyString, self.publicKeyFile, 1,
245
data=keydata.publicRSA_openssh)
246
self.assertWarns(DeprecationWarning, "getPublicKeyString is deprecated"
247
" since Twisted Conch 0.9. Use Key.fromString().blob().",
248
unittest.__file__, self.assertRaises, keys.BadKeyError,
249
keys.getPublicKeyString, data = 'invalid key')
250
sexp = sexpy.pack([['public-key', ['bad-key', ['p', '2']]]])
251
self.assertWarns(DeprecationWarning, "getPublicKeyString is deprecated"
252
" since Twisted Conch 0.9. Use Key.fromString().blob().",
253
unittest.__file__, self.assertRaises, keys.BadKeyError,
254
keys.getPublicKeyString, data='{'+base64.encodestring(sexp)+'}')
256
def test_getPrivateKeyObjectErrors(self):
258
Test that getPrivateKeyObject raises errors in appropriate cases.
260
self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated"
261
" since Twisted Conch 0.9. Use Key.fromString().",
262
unittest.__file__, self.assertRaises, keys.BadKeyError,
263
keys.getPrivateKeyObject, self.privateKeyFile,
264
keydata.privateRSA_openssh)
265
self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated"
266
" since Twisted Conch 0.9. Use Key.fromString().",
267
unittest.__file__, self.assertRaises, keys.BadKeyError,
268
keys.getPrivateKeyObject, data = 'invalid key')
269
sexp = sexpy.pack([['private-key', ['bad-key', ['p', '2']]]])
270
self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated"
271
" since Twisted Conch 0.9. Use Key.fromString().",
272
unittest.__file__, self.assertRaises, keys.BadKeyError,
273
keys.getPrivateKeyObject, data=sexp)
274
self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated"
275
" since Twisted Conch 0.9. Use Key.fromString().",
276
unittest.__file__, self.assertRaises, keys.BadKeyError,
277
keys.getPrivateKeyObject,
278
data='\x00\x00\x00\x07ssh-foo'+'\x00\x00\x00\x01\x01'*5)
280
def test_makePublicKeyStringErrors(self):
282
Test that makePublicKeyString raises errors in appropriate cases.
284
self.assertWarns(DeprecationWarning, "makePublicKeyString is deprecated"
285
" since Twisted Conch 0.9. Use Key(obj).public().toString().",
286
unittest.__file__, self.assertRaises, Exception,
287
keys.makePublicKeyString, None, kind='bad type')
288
self.assertWarns(DeprecationWarning, "makePublicKeyString is deprecated"
289
" since Twisted Conch 0.9. Use Key(obj).public().toString().",
290
unittest.__file__, self.assertRaises, Exception,
291
keys.makePublicKeyString, None)
292
self.assertWarns(DeprecationWarning, "makePublicKeyString is deprecated"
293
" since Twisted Conch 0.9. Use Key(obj).public().toString().",
294
unittest.__file__, self.assertRaises, Exception,
295
keys.makePublicKeyString, None, kind='lsh')
297
def test_getPublicKeyObjectErrors(self):
299
Test that getPublicKeyObject raises errors in appropriate cases.
301
self.assertWarns(DeprecationWarning, "getPublicKeyObject is deprecated"
302
" since Twisted Conch 0.9. Use Key.fromString().",
303
unittest.__file__, self.assertRaises, keys.BadKeyError,
304
keys.getPublicKeyObject, '\x00\x00\x00\x01A')
306
def test_makePrivateKeyStringErrors(self):
308
Test that makePrivateKeyString raises errors in appropriate cases.
310
self.assertWarns(DeprecationWarning, "makePrivateKeyString is "
311
"deprecated since Twisted Conch 0.9. Use Key(obj).toString().",
312
unittest.__file__, self.assertRaises, Exception,
313
keys.makePrivateKeyString, None, kind='bad type')
314
self.assertWarns(DeprecationWarning, "makePrivateKeyString is "
315
"deprecated since Twisted Conch 0.9. Use Key(obj).toString().",
316
unittest.__file__, self.assertRaises, Exception,
317
keys.makePrivateKeyString, None)
318
self.assertWarns(DeprecationWarning, "makePrivateKeyString is "
319
"deprecated since Twisted Conch 0.9. Use Key(obj).toString().",
320
unittest.__file__, self.assertRaises, Exception,
321
keys.makePrivateKeyString, None, kind='lsh')
323
class HelpersTestCase(unittest.TestCase):
326
skip = "cannot run w/o PyCrypto"
328
skip = "cannot run w/o/ PyASN1"
331
self._secureRandom = randbytes.secureRandom
332
randbytes.secureRandom = lambda x: '\x55' * x
335
randbytes.secureRandom = self._secureRandom
336
self._secureRandom = None
338
def test_pkcs1(self):
340
Test Public Key Cryptographic Standard #1 functions.
344
self.assertEquals(keys.pkcs1Pad(data, messageSize),
346
hash = sha1().digest()
348
self.assertEquals(keys.pkcs1Digest('', messageSize),
349
'\x01\xff\xff\xff\x00' + keys.ID_SHA1 + hash)
351
def _signRSA(self, data):
352
key = keys.Key.fromString(keydata.privateRSA_openssh)
354
return key.keyObject, sig
356
def _signDSA(self, data):
357
key = keys.Key.fromString(keydata.privateDSA_openssh)
359
return key.keyObject, sig
361
def test_signRSA(self):
363
Test that RSA keys return appropriate signatures.
366
key, sig = self._signRSA(data)
367
sigData = keys.pkcs1Digest(data, keys.lenSig(key))
368
v = key.sign(sigData, '')[0]
369
self.assertEquals(sig, common.NS('ssh-rsa') + common.MP(v))
372
def test_signDSA(self):
374
Test that DSA keys return appropriate signatures.
377
key, sig = self._signDSA(data)
378
sigData = sha1(data).digest()
379
v = key.sign(sigData, '\x55' * 19)
380
self.assertEquals(sig, common.NS('ssh-dss') + common.NS(
381
Crypto.Util.number.long_to_bytes(v[0], 20) +
382
Crypto.Util.number.long_to_bytes(v[1], 20)))
385
def test_verifyRSA(self):
387
Test that RSA signatures are verified appropriately.
390
key, sig = self._signRSA(data)
391
self.assertTrue(self.assertWarns(DeprecationWarning, "verifySignature "
392
"is deprecated since Twisted Conch 0.9. Use "
393
"Key(obj).verify(signature, data).", unittest.__file__,
394
keys.verifySignature, key, sig, data))
396
def test_verifyDSA(self):
398
Test that RSA signatures are verified appropriately.
401
key, sig = self._signDSA(data)
402
self.assertTrue(self.assertWarns(DeprecationWarning, "verifySignature "
403
"is deprecated since Twisted Conch 0.9. Use "
404
"Key(obj).verify(signature, data).", unittest.__file__,
405
keys.verifySignature, key, sig, data))
407
def test_objectType(self):
409
Test that objectType, returns the correct type for objects.
411
self.assertEquals(keys.objectType(keys.Key.fromString(
412
keydata.privateRSA_openssh).keyObject), 'ssh-rsa')
413
self.assertEquals(keys.objectType(keys.Key.fromString(
414
keydata.privateDSA_openssh).keyObject), 'ssh-dss')
415
self.assertRaises(keys.BadKeyError, keys.objectType, None)
417
def test_asn1PackError(self):
419
L{asn1.pack} should raise a C{ValueError} when given a type not
422
self.assertRaises(ValueError, asn1.pack, [object()])
423
self.assertEquals(len(self.flushWarnings()), 1)
425
def test_asn1DeprecationWarnings(self):
427
L{asn1.pack} and L{asn1.parse} were deprecated in Twisted 9.0.0. Make
428
sure that they tell their callers.
431
self.callDeprecated(asn1.Twisted9point0, asn1.pack, []),
434
len(self.callDeprecated(asn1.Twisted9point0, asn1.parse,
438
def test_printKey(self):
440
Test that the printKey function prints correctly.
442
obj = keys.Key.fromString(keydata.privateRSA_openssh).keyObject
443
self.assertEquals(self.assertWarns(DeprecationWarning, "printKey is "
444
"deprecated since Twisted Conch 0.9. Use repr(Key(obj)).",
445
unittest.__file__, keys.printKey, obj),
446
"""RSA Private Key (767 bits)
450
\t6e:1f:b5:55:97:eb:ed:67:ed:2b:99:6e:ec:c1:ed:
451
\ta8:4d:52:d6:f3:d6:65:06:04:df:e5:54:9f:cc:89:
452
\t00:3c:9b:67:87:ec:65:a0:ab:cd:6f:65:90:8a:97:
453
\t90:4d:c6:21:8f:a8:8d:d8:59:86:43:b5:81:b1:b4:
454
\td7:5f:2c:22:0a:61:c1:25:8a:47:12:b4:9a:f8:7a:
455
\t11:1c:4a:a8:8b:75:c4:91:09:3b:be:04:ca:45:d9:
458
\t00:af:32:71:f0:e6:0e:9c:99:b3:7f:8b:5f:04:4b:
459
\tcb:8b:c0:d5:3e:b2:77:fd:cf:64:d8:8f:c0:cf:ae:
460
\t1f:c6:31:df:f6:29:b2:44:96:e2:c6:d4:21:94:7f:
461
\t65:7c:d8:d4:23:1f:b8:2e:6a:c9:1f:94:0d:46:c1:
462
\t69:a2:b7:07:0c:a3:93:c1:34:d8:2e:1e:4a:99:1a:
463
\t6c:96:46:07:46:2b:dc:25:29:1b:87:f0:be:05:1d:
464
\tee:b4:34:b9:e7:99:95
466
\t00:dc:9f:6b:d9:98:21:56:11:8d:e9:5f:03:9d:0a:
467
\td3:93:6e:13:77:41:3c:85:4f:00:70:fd:05:54:ff:
468
\tbc:3d:09:bf:83:f6:97:7f:64:10:91:04:fe:a2:67:
471
\t00:cb:4a:4b:d0:40:47:e8:45:52:f7:c7:af:0c:20:
472
\t6d:43:0d:b6:39:94:f9:da:a5:e5:03:06:76:83:24:
473
\teb:88:a1:55:a2:a8:de:12:3b:77:49:92:8a:a9:71:
476
\t00:b4:73:97:4b:50:10:a3:17:b3:a8:47:f1:3a:14:
477
\t76:52:d1:38:2a:cf:12:14:34:c1:a8:54:4c:29:35:
478
\t80:a0:38:b8:f0:fa:4c:c4:c2:85:ab:db:87:82:ba:
481
class KeyTestCase(unittest.TestCase):
484
skip = "cannot run w/o PyCrypto"
486
skip = "cannot run w/o/ PyASN1"
489
self.rsaObj = Crypto.PublicKey.RSA.construct((1L, 2L, 3L, 4L, 5L))
490
self.dsaObj = Crypto.PublicKey.DSA.construct((1L, 2L, 3L, 4L, 5L))
491
self.rsaSignature = ('\x00\x00\x00\x07ssh-rsa\x00'
492
'\x00\x00`N\xac\xb4@qK\xa0(\xc3\xf2h \xd3\xdd\xee6Np\x9d_'
493
'\xb0>\xe3\x0c(L\x9d{\txUd|!\xf6m\x9c\xd3\x93\x842\x7fU'
494
'\x05\xf4\xf7\xfaD\xda\xce\x81\x8ea\x7f=Y\xed*\xb7\xba\x81'
495
'\xf2\xad\xda\xeb(\x97\x03S\x08\x81\xc7\xb1\xb7\xe6\xe3'
496
'\xcd*\xd4\xbd\xc0wt\xf7y\xcd\xf0\xb7\x7f\xfb\x1e>\xf9r'
498
self.dsaSignature = ('\x00\x00\x00\x07ssh-dss\x00\x00'
499
'\x00(\x18z)H\x8a\x1b\xc6\r\xbbq\xa2\xd7f\x7f$\xa7\xbf'
500
'\xe8\x87\x8c\x88\xef\xd9k\x1a\x98\xdd{=\xdec\x18\t\xe3'
501
'\x87\xa9\xc72h\x95')
502
self.oldSecureRandom = randbytes.secureRandom
503
randbytes.secureRandom = lambda x: '\xff' * x
504
self.keyFile = self.mktemp()
505
file(self.keyFile, 'wb').write(keydata.privateRSA_lsh)
508
randbytes.secureRandom = self.oldSecureRandom
509
del self.oldSecureRandom
510
os.unlink(self.keyFile)
512
def test__guessStringType(self):
514
Test that the _guessStringType method guesses string types
517
self.assertEquals(keys.Key._guessStringType(keydata.publicRSA_openssh),
519
self.assertEquals(keys.Key._guessStringType(keydata.publicDSA_openssh),
521
self.assertEquals(keys.Key._guessStringType(
522
keydata.privateRSA_openssh), 'private_openssh')
523
self.assertEquals(keys.Key._guessStringType(
524
keydata.privateDSA_openssh), 'private_openssh')
525
self.assertEquals(keys.Key._guessStringType(keydata.publicRSA_lsh),
527
self.assertEquals(keys.Key._guessStringType(keydata.publicDSA_lsh),
529
self.assertEquals(keys.Key._guessStringType(keydata.privateRSA_lsh),
531
self.assertEquals(keys.Key._guessStringType(keydata.privateDSA_lsh),
533
self.assertEquals(keys.Key._guessStringType(
534
keydata.privateRSA_agentv3), 'agentv3')
535
self.assertEquals(keys.Key._guessStringType(
536
keydata.privateDSA_agentv3), 'agentv3')
537
self.assertEquals(keys.Key._guessStringType(
538
'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x01\x01'),
540
self.assertEquals(keys.Key._guessStringType(
541
'\x00\x00\x00\x07ssh-dss\x00\x00\x00\x01\x01'),
543
self.assertEquals(keys.Key._guessStringType('not a key'),
546
def _testPublicPrivateFromString(self, public, private, type, data):
547
self._testPublicFromString(public, type, data)
548
self._testPrivateFromString(private, type, data)
550
def _testPublicFromString(self, public, type, data):
551
publicKey = keys.Key.fromString(public)
552
self.assertTrue(publicKey.isPublic())
553
self.assertEquals(publicKey.type(), type)
554
for k, v in publicKey.data().items():
555
self.assertEquals(data[k], v)
557
def _testPrivateFromString(self, private, type, data):
558
privateKey = keys.Key.fromString(private)
559
self.assertFalse(privateKey.isPublic())
560
self.assertEquals(privateKey.type(), type)
561
for k, v in data.items():
562
self.assertEquals(privateKey.data()[k], v)
564
def test_fromOpenSSH(self):
566
Test that keys are correctly generated from OpenSSH strings.
568
self._testPublicPrivateFromString(keydata.publicRSA_openssh,
569
keydata.privateRSA_openssh, 'RSA', keydata.RSAData)
570
self.assertEquals(keys.Key.fromString(
571
keydata.privateRSA_openssh_encrypted,
572
passphrase='encrypted'),
573
keys.Key.fromString(keydata.privateRSA_openssh))
574
self.assertEquals(keys.Key.fromString(
575
keydata.privateRSA_openssh_alternate),
576
keys.Key.fromString(keydata.privateRSA_openssh))
577
self._testPublicPrivateFromString(keydata.publicDSA_openssh,
578
keydata.privateDSA_openssh, 'DSA', keydata.DSAData)
580
def test_fromOpenSSH_with_whitespace(self):
582
If key strings have trailing whitespace, it should be ignored.
584
# from bug #3391, since our test key data doesn't have
585
# an issue with appended newlines
586
privateDSAData = """-----BEGIN DSA PRIVATE KEY-----
587
MIIBuwIBAAKBgQDylESNuc61jq2yatCzZbenlr9llG+p9LhIpOLUbXhhHcwC6hrh
588
EZIdCKqTO0USLrGoP5uS9UHAUoeN62Z0KXXWTwOWGEQn/syyPzNJtnBorHpNUT9D
589
Qzwl1yUa53NNgEctpo4NoEFOx8PuU6iFLyvgHCjNn2MsuGuzkZm7sI9ZpQIVAJiR
590
9dPc08KLdpJyRxz8T74b4FQRAoGAGBc4Z5Y6R/HZi7AYM/iNOM8su6hrk8ypkBwR
591
a3Dbhzk97fuV3SF1SDrcQu4zF7c4CtH609N5nfZs2SUjLLGPWln83Ysb8qhh55Em
592
AcHXuROrHS/sDsnqu8FQp86MaudrqMExCOYyVPE7jaBWW+/JWFbKCxmgOCSdViUJ
593
esJpBFsCgYEA7+jtVvSt9yrwsS/YU1QGP5wRAiDYB+T5cK4HytzAqJKRdC5qS4zf
594
C7R0eKcDHHLMYO39aPnCwXjscisnInEhYGNblTDyPyiyNxAOXuC8x7luTmwzMbNJ
595
/ow0IqSj0VF72VJN9uSoPpFd4lLT0zN8v42RWja0M8ohWNf+YNJluPgCFE0PT4Vm
597
-----END DSA PRIVATE KEY-----"""
598
self.assertEquals(keys.Key.fromString(privateDSAData),
599
keys.Key.fromString(privateDSAData + '\n'))
601
def test_fromLSH(self):
603
Test that keys are correctly generated from LSH strings.
605
self._testPublicPrivateFromString(keydata.publicRSA_lsh,
606
keydata.privateRSA_lsh, 'RSA', keydata.RSAData)
607
self._testPublicPrivateFromString(keydata.publicDSA_lsh,
608
keydata.privateDSA_lsh, 'DSA', keydata.DSAData)
609
sexp = sexpy.pack([['public-key', ['bad-key', ['p', '2']]]])
610
self.assertRaises(keys.BadKeyError, keys.Key.fromString,
611
data='{'+base64.encodestring(sexp)+'}')
612
sexp = sexpy.pack([['private-key', ['bad-key', ['p', '2']]]])
613
self.assertRaises(keys.BadKeyError, keys.Key.fromString,
616
def test_fromAgentv3(self):
618
Test that keys are correctly generated from Agent v3 strings.
620
self._testPrivateFromString(keydata.privateRSA_agentv3, 'RSA',
622
self._testPrivateFromString(keydata.privateDSA_agentv3, 'DSA',
624
self.assertRaises(keys.BadKeyError, keys.Key.fromString,
625
'\x00\x00\x00\x07ssh-foo'+'\x00\x00\x00\x01\x01'*5)
627
def test_fromStringErrors(self):
629
keys.Key.fromString should raise BadKeyError when the key is invalid.
631
self.assertRaises(keys.BadKeyError, keys.Key.fromString, '')
632
# no key data with a bad key type
633
self.assertRaises(keys.BadKeyError, keys.Key.fromString, '',
635
# trying to decrypt a key which doesn't support encryption
636
self.assertRaises(keys.BadKeyError, keys.Key.fromString,
637
keydata.publicRSA_lsh, passphrase = 'unencrypted')
638
# trying to decrypt an unencrypted key
639
self.assertRaises(keys.EncryptedKeyError, keys.Key.fromString,
640
keys.Key(self.rsaObj).toString('openssh', 'encrypted'))
641
# key with no key data
642
self.assertRaises(keys.BadKeyError, keys.Key.fromString,
643
'-----BEGIN RSA KEY-----\nwA==\n')
645
def test_fromFile(self):
647
Test that fromFile works correctly.
649
self.assertEquals(keys.Key.fromFile(self.keyFile),
650
keys.Key.fromString(keydata.privateRSA_lsh))
651
self.assertRaises(keys.BadKeyError, keys.Key.fromFile,
652
self.keyFile, 'bad_type')
653
self.assertRaises(keys.BadKeyError, keys.Key.fromFile,
654
self.keyFile, passphrase='unencrypted')
658
Test that the PublicKey object is initialized correctly.
660
obj = Crypto.PublicKey.RSA.construct((1L, 2L))
662
self.assertEquals(key.keyObject, obj)
664
def test_equal(self):
666
Test that Key objects are compared correctly.
668
rsa1 = keys.Key(self.rsaObj)
669
rsa2 = keys.Key(self.rsaObj)
670
rsa3 = keys.Key(Crypto.PublicKey.RSA.construct((1L, 2L)))
671
dsa = keys.Key(self.dsaObj)
672
self.assertTrue(rsa1 == rsa2)
673
self.assertFalse(rsa1 == rsa3)
674
self.assertFalse(rsa1 == dsa)
675
self.assertFalse(rsa1 == object)
676
self.assertFalse(rsa1 == None)
678
def test_notEqual(self):
680
Test that Key objects are not-compared correctly.
682
rsa1 = keys.Key(self.rsaObj)
683
rsa2 = keys.Key(self.rsaObj)
684
rsa3 = keys.Key(Crypto.PublicKey.RSA.construct((1L, 2L)))
685
dsa = keys.Key(self.dsaObj)
686
self.assertFalse(rsa1 != rsa2)
687
self.assertTrue(rsa1 != rsa3)
688
self.assertTrue(rsa1 != dsa)
689
self.assertTrue(rsa1 != object)
690
self.assertTrue(rsa1 != None)
694
Test that the type method returns the correct type for an object.
696
self.assertEquals(keys.Key(self.rsaObj).type(), 'RSA')
697
self.assertEquals(keys.Key(self.rsaObj).sshType(), 'ssh-rsa')
698
self.assertEquals(keys.Key(self.dsaObj).type(), 'DSA')
699
self.assertEquals(keys.Key(self.dsaObj).sshType(), 'ssh-dss')
700
self.assertRaises(RuntimeError, keys.Key(None).type)
701
self.assertRaises(RuntimeError, keys.Key(None).sshType)
702
self.assertRaises(RuntimeError, keys.Key(self).type)
703
self.assertRaises(RuntimeError, keys.Key(self).sshType)
705
def test_fromBlob(self):
707
Test that a public key is correctly generated from a public key blob.
709
rsaBlob = common.NS('ssh-rsa') + common.MP(2) + common.MP(3)
710
rsaKey = keys.Key.fromString(rsaBlob)
711
dsaBlob = (common.NS('ssh-dss') + common.MP(2) + common.MP(3) +
712
common.MP(4) + common.MP(5))
713
dsaKey = keys.Key.fromString(dsaBlob)
714
badBlob = common.NS('ssh-bad')
715
self.assertTrue(rsaKey.isPublic())
716
self.assertEquals(rsaKey.data(), {'e':2L, 'n':3L})
717
self.assertTrue(dsaKey.isPublic())
718
self.assertEquals(dsaKey.data(), {'p':2L, 'q':3L, 'g':4L, 'y':5L})
719
self.assertRaises(keys.BadKeyError,
720
keys.Key.fromString, badBlob)
723
def test_fromPrivateBlob(self):
725
Test that a private key is correctly generated from a private key blob.
727
rsaBlob = (common.NS('ssh-rsa') + common.MP(2) + common.MP(3) +
728
common.MP(4) + common.MP(5) + common.MP(6) + common.MP(7))
729
rsaKey = keys.Key._fromString_PRIVATE_BLOB(rsaBlob)
730
dsaBlob = (common.NS('ssh-dss') + common.MP(2) + common.MP(3) +
731
common.MP(4) + common.MP(5) + common.MP(6))
732
dsaKey = keys.Key._fromString_PRIVATE_BLOB(dsaBlob)
733
badBlob = common.NS('ssh-bad')
734
self.assertFalse(rsaKey.isPublic())
736
rsaKey.data(), {'n':2L, 'e':3L, 'd':4L, 'u':5L, 'p':6L, 'q':7L})
737
self.assertFalse(dsaKey.isPublic())
738
self.assertEqual(dsaKey.data(), {'p':2L, 'q':3L, 'g':4L, 'y':5L, 'x':6L})
740
keys.BadKeyError, keys.Key._fromString_PRIVATE_BLOB, badBlob)
745
Test that the Key object generates blobs correctly.
747
self.assertEquals(keys.Key(self.rsaObj).blob(),
748
'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x01\x02'
749
'\x00\x00\x00\x01\x01')
750
self.assertEquals(keys.Key(self.dsaObj).blob(),
751
'\x00\x00\x00\x07ssh-dss\x00\x00\x00\x01\x03'
752
'\x00\x00\x00\x01\x04\x00\x00\x00\x01\x02'
753
'\x00\x00\x00\x01\x01')
755
badKey = keys.Key(None)
756
self.assertRaises(RuntimeError, badKey.blob)
759
def test_privateBlob(self):
761
L{Key.privateBlob} returns the SSH protocol-level format of the private
762
key and raises L{RuntimeError} if the underlying key object is invalid.
764
self.assertEquals(keys.Key(self.rsaObj).privateBlob(),
765
'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x01\x01'
766
'\x00\x00\x00\x01\x02\x00\x00\x00\x01\x03\x00'
767
'\x00\x00\x01\x04\x00\x00\x00\x01\x04\x00\x00'
769
self.assertEquals(keys.Key(self.dsaObj).privateBlob(),
770
'\x00\x00\x00\x07ssh-dss\x00\x00\x00\x01\x03'
771
'\x00\x00\x00\x01\x04\x00\x00\x00\x01\x02\x00'
772
'\x00\x00\x01\x01\x00\x00\x00\x01\x05')
774
badKey = keys.Key(None)
775
self.assertRaises(RuntimeError, badKey.privateBlob)
778
def test_toOpenSSH(self):
780
Test that the Key object generates OpenSSH keys correctly.
782
key = keys.Key.fromString(keydata.privateRSA_lsh)
783
self.assertEquals(key.toString('openssh'), keydata.privateRSA_openssh)
784
self.assertEquals(key.toString('openssh', 'encrypted'),
785
keydata.privateRSA_openssh_encrypted)
786
self.assertEquals(key.public().toString('openssh'),
787
keydata.publicRSA_openssh[:-8]) # no comment
788
self.assertEquals(key.public().toString('openssh', 'comment'),
789
keydata.publicRSA_openssh)
790
key = keys.Key.fromString(keydata.privateDSA_lsh)
791
self.assertEquals(key.toString('openssh'), keydata.privateDSA_openssh)
792
self.assertEquals(key.public().toString('openssh', 'comment'),
793
keydata.publicDSA_openssh)
794
self.assertEquals(key.public().toString('openssh'),
795
keydata.publicDSA_openssh[:-8]) # no comment
797
def test_toLSH(self):
799
Test that the Key object generates LSH keys correctly.
801
key = keys.Key.fromString(keydata.privateRSA_openssh)
802
self.assertEquals(key.toString('lsh'), keydata.privateRSA_lsh)
803
self.assertEquals(key.public().toString('lsh'),
804
keydata.publicRSA_lsh)
805
key = keys.Key.fromString(keydata.privateDSA_openssh)
806
self.assertEquals(key.toString('lsh'), keydata.privateDSA_lsh)
807
self.assertEquals(key.public().toString('lsh'),
808
keydata.publicDSA_lsh)
810
def test_toAgentv3(self):
812
Test that the Key object generates Agent v3 keys correctly.
814
key = keys.Key.fromString(keydata.privateRSA_openssh)
815
self.assertEquals(key.toString('agentv3'), keydata.privateRSA_agentv3)
816
key = keys.Key.fromString(keydata.privateDSA_openssh)
817
self.assertEquals(key.toString('agentv3'), keydata.privateDSA_agentv3)
819
def test_toStringErrors(self):
821
Test that toString raises errors appropriately.
823
self.assertRaises(keys.BadKeyError, keys.Key(self.rsaObj).toString,
828
Test that the Key object generates correct signatures.
830
key = keys.Key.fromString(keydata.privateRSA_openssh)
831
self.assertEquals(key.sign(''), self.rsaSignature)
832
key = keys.Key.fromString(keydata.privateDSA_openssh)
833
self.assertEquals(key.sign(''), self.dsaSignature)
836
def test_verify(self):
838
Test that the Key object correctly verifies signatures.
840
key = keys.Key.fromString(keydata.publicRSA_openssh)
841
self.assertTrue(key.verify(self.rsaSignature, ''))
842
self.assertFalse(key.verify(self.rsaSignature, 'a'))
843
self.assertFalse(key.verify(self.dsaSignature, ''))
844
key = keys.Key.fromString(keydata.publicDSA_openssh)
845
self.assertTrue(key.verify(self.dsaSignature, ''))
846
self.assertFalse(key.verify(self.dsaSignature, 'a'))
847
self.assertFalse(key.verify(self.rsaSignature, ''))
851
Test the pretty representation of Key.
853
self.assertEquals(repr(keys.Key(self.rsaObj)),
854
"""<RSA Private Key (0 bits)
868
class WarningsTestCase(unittest.TestCase):
870
Test that deprecated functions warn the user of their deprecation.
873
skip = "cannot run w/o PyCrypto"
875
skip = "cannot run w/o/ PyASN1"
878
self.keyObject = keys.Key.fromString(keydata.privateRSA_lsh).keyObject
880
def test_getPublicKeyString(self):
882
Test that getPublicKeyString warns with a DeprecationWarning.
884
self.assertWarns(DeprecationWarning,
885
"getPublicKeyString is deprecated since Twisted Conch 0.9."
886
" Use Key.fromString().blob().",
887
unittest.__file__, keys.getPublicKeyString,
888
data=keydata.publicRSA_openssh)
890
def test_makePublicKeyString(self):
892
Test that makePublicKeyString warns with a DeprecationWarning.
894
self.assertWarns(DeprecationWarning,
895
"makePublicKeyString is deprecated since Twisted Conch 0.9."
896
" Use Key(obj).public().toString().", unittest.__file__,
897
keys.makePublicKeyString, self.keyObject)
899
def test_getPublicKeyObject(self):
901
Test that getPublicKeyObject warns with a DeprecationWarning.
903
self.assertWarns(DeprecationWarning,
904
"getPublicKeyObject is deprecated since Twisted Conch 0.9."
905
" Use Key.fromString().", unittest.__file__,
906
keys.getPublicKeyObject, keydata.publicRSA_lsh)
908
def test_getPrivateKeyObject(self):
910
Test that getPrivateKeyObject warns with a DeprecationWarning.
912
self.assertWarns(DeprecationWarning,
913
"getPrivateKeyObject is deprecated since Twisted Conch 0.9."
914
" Use Key.fromString().", unittest.__file__,
915
keys.getPrivateKeyObject, data=keydata.privateRSA_lsh)
917
def test_makePrivateKeyString(self):
919
Test that makePrivateKeyString warns with a DeprecationWarning.
921
self.assertWarns(DeprecationWarning,
922
"makePrivateKeyString is deprecated since Twisted Conch 0.9."
923
" Use Key(obj).toString().", unittest.__file__,
924
keys.makePrivateKeyString, self.keyObject)
926
def test_makePublicKeyBlob(self):
928
Test that makePublicKeyBlob warns with a DeprecationWarning.
930
self.assertWarns(DeprecationWarning,
931
"makePublicKeyBlob is deprecated since Twisted Conch 0.9."
932
" Use Key(obj).blob().", unittest.__file__,
933
keys.makePublicKeyBlob, self.keyObject)
935
def test_signData(self):
937
Test that signData warns with a DeprecationWarning.
939
self.assertWarns(DeprecationWarning,
940
"signData is deprecated since Twisted Conch 0.9."
941
" Use Key(obj).sign(data).", unittest.__file__,
942
keys.signData, self.keyObject, '')
944
def test_verifySignature(self):
946
Test that signData warns with a DeprecationWarning.
948
self.assertWarns(DeprecationWarning,
949
"verifySignature is deprecated since Twisted Conch 0.9."
950
" Use Key(obj).verify(signature, data).", unittest.__file__,
951
keys.verifySignature, self.keyObject, '\x00\x00\x00\x00', '')
953
def test_printKey(self):
955
Test that signData warns with a DeprecationWarning.
957
self.assertWarns(DeprecationWarning,
958
"printKey is deprecated since Twisted Conch 0.9."
959
" Use repr(Key(obj)).", unittest.__file__,
960
keys.printKey, self.keyObject)