OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.conch.test.test_keys -*- | |
2 # Copyright (c) 2001-2008 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 try: | |
6 import Crypto | |
7 except ImportError: | |
8 Crypto = None | |
9 else: | |
10 from twisted.conch.ssh import keys, common, sexpy, asn1 | |
11 | |
12 from twisted.conch.test import keydata | |
13 from twisted.python import randbytes | |
14 from twisted.trial import unittest | |
15 import sha, os, base64 | |
16 | |
17 class SSHKeysHandlingTestCase(unittest.TestCase): | |
18 """ | |
19 test the handling of reading/signing/verifying with RSA and DSA keys | |
20 assumed test keys are in test/ | |
21 """ | |
22 | |
23 if not Crypto: | |
24 skip = "cannot run w/o PyCrypto" | |
25 | |
26 def setUp(self): | |
27 self.tmpdir = self.mktemp() | |
28 os.mkdir(self.tmpdir) | |
29 self.privateKeyFile = os.path.join(self.tmpdir, 'private') | |
30 self.publicKeyFile = os.path.join(self.tmpdir, 'public') | |
31 file(self.privateKeyFile, 'wb').write(keydata.privateRSA_openssh) | |
32 file(self.publicKeyFile, 'wb').write('first line\n' + | |
33 keydata.publicRSA_openssh) | |
34 | |
35 def test_readFile(self): | |
36 """ | |
37 Test that reading a key from a file works as expected. | |
38 """ | |
39 self.assertEquals(self.assertWarns(DeprecationWarning, | |
40 "getPublicKeyString is deprecated since Twisted Conch 0.9. " | |
41 "Use Key.fromString().", unittest.__file__, | |
42 keys.getPublicKeyString, self.publicKeyFile, 1), | |
43 keys.Key.fromString(keydata.publicRSA_openssh).blob()) | |
44 self.assertEquals(self.assertWarns(DeprecationWarning, | |
45 "getPrivateKeyObject is deprecated since Twisted Conch 0.9. " | |
46 "Use Key.fromString().", unittest.__file__, | |
47 keys.getPrivateKeyObject, self.privateKeyFile), | |
48 keys.Key.fromString(keydata.privateRSA_openssh).keyObject) | |
49 | |
50 def test_DSA(self): | |
51 """ | |
52 Test DSA keys using both OpenSSH and LSH formats. | |
53 """ | |
54 self._testKey(keydata.publicDSA_openssh, keydata.privateDSA_openssh, | |
55 keydata.DSAData, 'openssh') | |
56 self._testKey(keydata.publicDSA_lsh, keydata.privateDSA_lsh, | |
57 keydata.DSAData,'lsh') | |
58 obj = self.assertWarns(DeprecationWarning, "getPrivateKeyObject is " | |
59 "deprecated since Twisted Conch 0.9. Use Key.fromString().", | |
60 unittest.__file__, keys.getPrivateKeyObject, | |
61 data=keydata.privateDSA_agentv3) | |
62 self._testGeneratePrivateKey(obj, keydata.privateDSA_agentv3, | |
63 'agentv3') | |
64 | |
65 def test_RSA(self): | |
66 """ | |
67 Same as test_DSA but for RSA keys. | |
68 """ | |
69 self._testKey(keydata.publicRSA_openssh, keydata.privateRSA_openssh, | |
70 keydata.RSAData, 'openssh') | |
71 self._testKey(keydata.publicRSA_lsh, keydata.privateRSA_lsh, | |
72 keydata.RSAData, 'lsh') | |
73 obj = self.assertWarns(DeprecationWarning, "getPrivateKeyObject is " | |
74 "deprecated since Twisted Conch 0.9. Use Key.fromString().", | |
75 unittest.__file__, keys.getPrivateKeyObject, | |
76 data=keydata.privateRSA_agentv3) | |
77 self._testGeneratePrivateKey(obj, keydata.privateRSA_agentv3, | |
78 'agentv3') | |
79 | |
80 def _testKey(self, pubStr, privStr, data, keyType): | |
81 """ | |
82 Run each of the key tests with the public/private keypairs. | |
83 | |
84 @param pubStr: The data for a public key in the format defined by | |
85 keyType. | |
86 @param privStr: The data for a private key in the format defined by | |
87 keyType. | |
88 @param data: The numerical values encoded in the key. | |
89 @param keyType: the type of the public and private key data: either | |
90 "openssh" or "lsh". | |
91 """ | |
92 pubBlob = self.assertWarns(DeprecationWarning, "getPublicKeyString is " | |
93 "deprecated since Twisted Conch 0.9. Use Key.fromString().", | |
94 unittest.__file__, keys.getPublicKeyString, data=pubStr) | |
95 pubObj = self.assertWarns(DeprecationWarning, "getPublicKeyObject is " | |
96 "deprecated since Twisted Conch 0.9. Use Key.fromString().", | |
97 unittest.__file__, keys.getPublicKeyObject, pubBlob) | |
98 privObj = self.assertWarns(DeprecationWarning, "getPrivateKeyObject is " | |
99 "deprecated since Twisted Conch 0.9. Use Key.fromString().", | |
100 unittest.__file__, keys.getPrivateKeyObject, data=privStr) | |
101 | |
102 self._testKeySignVerify(privObj, pubObj) | |
103 self._testKeyFromString(privObj, pubObj, data, keyType) | |
104 self._testGeneratePublicKey(privObj, pubObj, pubStr, keyType) | |
105 self._testGeneratePrivateKey(privObj, privStr, keyType) | |
106 self._testGenerateBlob(privObj, pubObj, pubBlob) | |
107 | |
108 def _testKeySignVerify(self, privObj, pubObj): | |
109 """ | |
110 Test that signing and verifying works correctly. | |
111 @param privObj: a private key object. | |
112 @type privObj: C{Crypto.PublicKey.pubkey.pubkey} | |
113 @param pubObj: a public key object. | |
114 @type pubObj: C{Crypto.PublicKey.pubkey.pubkey} | |
115 """ | |
116 | |
117 testData = 'this is the test data' | |
118 sig = self.assertWarns(DeprecationWarning, | |
119 "signData is deprecated since Twisted Conch 0.9. " | |
120 "Use Key(obj).sign(data).", unittest.__file__, keys.signData, | |
121 privObj, testData) | |
122 self.assertTrue(self.assertWarns(DeprecationWarning, | |
123 "verifySignature is deprecated since Twisted Conch 0.9. " | |
124 "Use Key(obj).verify(signature, data).", unittest.__file__, | |
125 keys.verifySignature, privObj, sig, testData), | |
126 'verifying with private %s failed' % | |
127 keys.objectType(privObj)) | |
128 | |
129 self.assertTrue(self.assertWarns(DeprecationWarning, | |
130 "verifySignature is deprecated since Twisted Conch 0.9. " | |
131 "Use Key(obj).verify(signature, data).", unittest.__file__, | |
132 keys.verifySignature, pubObj, sig, testData), | |
133 'verifying with public %s failed' % | |
134 keys.objectType(pubObj)) | |
135 | |
136 self.failIf(self.assertWarns(DeprecationWarning, | |
137 "verifySignature is deprecated since Twisted Conch 0.9. " | |
138 "Use Key(obj).verify(signature, data).", unittest.__file__, | |
139 keys.verifySignature,privObj, sig, 'other data'), | |
140 'verified bad data with %s' % | |
141 keys.objectType(privObj)) | |
142 | |
143 self.failIf(self.assertWarns(DeprecationWarning, | |
144 "verifySignature is deprecated since Twisted Conch 0.9. " | |
145 "Use Key(obj).verify(signature, data).", unittest.__file__, | |
146 keys.verifySignature, privObj, 'bad sig', testData), | |
147 'verified badsign with %s' % | |
148 keys.objectType(privObj)) | |
149 | |
150 def _testKeyFromString(self, privObj, pubObj, data, keyType): | |
151 """ | |
152 Test key object generation from a string. The public key objects | |
153 were generated in _testKey; just check that they were created | |
154 correctly. | |
155 """ | |
156 for k in data.keys(): | |
157 self.assertEquals(getattr(privObj, k), data[k]) | |
158 for k in pubObj.keydata: | |
159 if hasattr(pubObj, k): # public key objects don't have all the | |
160 # attributes | |
161 self.assertEquals(getattr(pubObj, k), data[k]) | |
162 | |
163 def _testGeneratePublicKey(self, privObj, pubObj, pubStr, keyType): | |
164 """ | |
165 Test public key string generation from an object. | |
166 """ | |
167 self.assertEquals(self.assertWarns(DeprecationWarning, | |
168 "makePublicKeyString is deprecated since Twisted Conch 0.9. " | |
169 "Use Key(obj).toString().", unittest.__file__, | |
170 keys.makePublicKeyString, pubObj, 'comment', | |
171 keyType), pubStr) | |
172 self.assertEquals(self.assertWarns(DeprecationWarning, | |
173 "makePublicKeyString is deprecated since Twisted Conch 0.9. " | |
174 "Use Key(obj).toString().", unittest.__file__, | |
175 keys.makePublicKeyString, privObj, 'comment', | |
176 keyType), pubStr) | |
177 | |
178 def _testGeneratePrivateKey(self, privObj, privStr, keyType): | |
179 """ | |
180 Test private key string generation from an object. | |
181 """ | |
182 self.assertEquals(self.assertWarns(DeprecationWarning, | |
183 "makePrivateKeyString is deprecated since Twisted Conch 0.9. " | |
184 "Use Key(obj).toString().", unittest.__file__, | |
185 keys.makePrivateKeyString, privObj, kind=keyType), | |
186 privStr) | |
187 if keyType == 'openssh': | |
188 encData = self.assertWarns(DeprecationWarning, | |
189 "makePrivateKeyString is deprecated since Twisted Conch " | |
190 "0.9. Use Key(obj).toString().", unittest.__file__, | |
191 keys.makePrivateKeyString, privObj, passphrase='test', | |
192 kind=keyType) | |
193 self.assertEquals(self.assertWarns(DeprecationWarning, | |
194 "getPrivateKeyObject is deprecated since Twisted Conch 0.9. " | |
195 "Use Key.fromString().", unittest.__file__, | |
196 keys.getPrivateKeyObject, data = encData, passphrase='test'), | |
197 privObj) | |
198 | |
199 def _testGenerateBlob(self, privObj, pubObj, pubBlob): | |
200 """ | |
201 Test wire-format blob generation. | |
202 """ | |
203 self.assertEquals(self.assertWarns(DeprecationWarning, | |
204 "makePublicKeyBlob is deprecated since Twisted Conch 0.9. " | |
205 "Use Key(obj).blob().", unittest.__file__, | |
206 keys.makePublicKeyBlob, pubObj), pubBlob) | |
207 self.assertEquals(self.assertWarns(DeprecationWarning, | |
208 "makePublicKeyBlob is deprecated since Twisted Conch 0.9. " | |
209 "Use Key(obj).blob().", unittest.__file__, | |
210 keys.makePublicKeyBlob, privObj), pubBlob) | |
211 | |
212 def test_getPublicKeyStringErrors(self): | |
213 """ | |
214 Test that getPublicKeyString raises errors in appropriate cases. | |
215 """ | |
216 self.assertWarns(DeprecationWarning, "getPublicKeyString is deprecated" | |
217 " since Twisted Conch 0.9. Use Key.fromString().", | |
218 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
219 keys.getPublicKeyString, self.publicKeyFile, 1, | |
220 data=keydata.publicRSA_openssh) | |
221 self.assertWarns(DeprecationWarning, "getPublicKeyString is deprecated" | |
222 " since Twisted Conch 0.9. Use Key.fromString().", | |
223 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
224 keys.getPublicKeyString, data = 'invalid key') | |
225 sexp = sexpy.pack([['public-key', ['bad-key', ['p', '2']]]]) | |
226 self.assertWarns(DeprecationWarning, "getPublicKeyString is deprecated" | |
227 " since Twisted Conch 0.9. Use Key.fromString().", | |
228 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
229 keys.getPublicKeyString, data='{'+base64.encodestring(sexp)+'}') | |
230 | |
231 def test_getPrivateKeyObjectErrors(self): | |
232 """ | |
233 Test that getPrivateKeyObject raises errors in appropriate cases. | |
234 """ | |
235 self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated" | |
236 " since Twisted Conch 0.9. Use Key.fromString().", | |
237 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
238 keys.getPrivateKeyObject, self.privateKeyFile, | |
239 keydata.privateRSA_openssh) | |
240 self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated" | |
241 " since Twisted Conch 0.9. Use Key.fromString().", | |
242 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
243 keys.getPrivateKeyObject, data = 'invalid key') | |
244 sexp = sexpy.pack([['private-key', ['bad-key', ['p', '2']]]]) | |
245 self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated" | |
246 " since Twisted Conch 0.9. Use Key.fromString().", | |
247 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
248 keys.getPrivateKeyObject, data=sexp) | |
249 self.assertWarns(DeprecationWarning, "getPrivateKeyObject is deprecated" | |
250 " since Twisted Conch 0.9. Use Key.fromString().", | |
251 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
252 keys.getPrivateKeyObject, | |
253 data='\x00\x00\x00\x07ssh-foo'+'\x00\x00\x00\x01\x01'*5) | |
254 | |
255 def test_makePublicKeyStringErrors(self): | |
256 """ | |
257 Test that makePublicKeyString raises errors in appropriate cases. | |
258 """ | |
259 self.assertWarns(DeprecationWarning, "makePublicKeyString is deprecated" | |
260 " since Twisted Conch 0.9. Use Key(obj).toString().", | |
261 unittest.__file__, self.assertRaises, Exception, | |
262 keys.makePublicKeyString, None, kind='bad type') | |
263 self.assertWarns(DeprecationWarning, "makePublicKeyString is deprecated" | |
264 " since Twisted Conch 0.9. Use Key(obj).toString().", | |
265 unittest.__file__, self.assertRaises, Exception, | |
266 keys.makePublicKeyString, None) | |
267 self.assertWarns(DeprecationWarning, "makePublicKeyString is deprecated" | |
268 " since Twisted Conch 0.9. Use Key(obj).toString().", | |
269 unittest.__file__, self.assertRaises, Exception, | |
270 keys.makePublicKeyString, None, kind='lsh') | |
271 | |
272 def test_getPublicKeyObjectErrors(self): | |
273 """ | |
274 Test that getPublicKeyObject raises errors in appropriate cases. | |
275 """ | |
276 self.assertWarns(DeprecationWarning, "getPublicKeyObject is deprecated" | |
277 " since Twisted Conch 0.9. Use Key.fromString().", | |
278 unittest.__file__, self.assertRaises, keys.BadKeyError, | |
279 keys.getPublicKeyObject, '\x00\x00\x00\x01A') | |
280 | |
281 def test_makePrivateKeyStringErrors(self): | |
282 """ | |
283 Test that makePrivateKeyString raises errors in appropriate cases. | |
284 """ | |
285 self.assertWarns(DeprecationWarning, "makePrivateKeyString is " | |
286 "deprecated since Twisted Conch 0.9. Use Key(obj).toString().", | |
287 unittest.__file__, self.assertRaises, Exception, | |
288 keys.makePrivateKeyString, None, kind='bad type') | |
289 self.assertWarns(DeprecationWarning, "makePrivateKeyString is " | |
290 "deprecated since Twisted Conch 0.9. Use Key(obj).toString().", | |
291 unittest.__file__, self.assertRaises, Exception, | |
292 keys.makePrivateKeyString, None) | |
293 self.assertWarns(DeprecationWarning, "makePrivateKeyString is " | |
294 "deprecated since Twisted Conch 0.9. Use Key(obj).toString().", | |
295 unittest.__file__, self.assertRaises, Exception, | |
296 keys.makePrivateKeyString, None, kind='lsh') | |
297 | |
298 class HelpersTestCase(unittest.TestCase): | |
299 | |
300 if not Crypto: | |
301 skip = "cannot run w/o PyCrypto" | |
302 | |
303 def setUp(self): | |
304 self._secureRandom = randbytes.secureRandom | |
305 randbytes.secureRandom = lambda x: '\x55' * x | |
306 | |
307 def tearDown(self): | |
308 randbytes.secureRandom = self._secureRandom | |
309 self._secureRandom = None | |
310 | |
311 def test_pkcs1(self): | |
312 """ | |
313 Test Public Key Cryptographic Standard #1 functions. | |
314 """ | |
315 data = 'ABC' | |
316 messageSize = 6 | |
317 self.assertEquals(keys.pkcs1Pad(data, messageSize), | |
318 '\x01\xff\x00ABC') | |
319 hash = sha.new().digest() | |
320 messageSize = 40 | |
321 self.assertEquals(keys.pkcs1Digest('', messageSize), | |
322 '\x01\xff\xff\xff\x00' + keys.ID_SHA1 + hash) | |
323 | |
324 def _signRSA(self, data): | |
325 key = keys.Key.fromString(keydata.privateRSA_openssh) | |
326 sig = key.sign(data) | |
327 return key.keyObject, sig | |
328 | |
329 def _signDSA(self, data): | |
330 key = keys.Key.fromString(keydata.privateDSA_openssh) | |
331 sig = key.sign(data) | |
332 return key.keyObject, sig | |
333 | |
334 def test_signRSA(self): | |
335 """ | |
336 Test that RSA keys return appropriate signatures. | |
337 """ | |
338 data = 'data' | |
339 key, sig = self._signRSA(data) | |
340 sigData = keys.pkcs1Digest(data, keys.lenSig(key)) | |
341 v = key.sign(sigData, '')[0] | |
342 self.assertEquals(sig, common.NS('ssh-rsa') + common.MP(v)) | |
343 return key, sig | |
344 | |
345 def test_signDSA(self): | |
346 """ | |
347 Test that DSA keys return appropriate signatures. | |
348 """ | |
349 data = 'data' | |
350 key, sig = self._signDSA(data) | |
351 sigData = sha.new(data).digest() | |
352 v = key.sign(sigData, '\x55' * 19) | |
353 self.assertEquals(sig, common.NS('ssh-dss') + common.NS( | |
354 Crypto.Util.number.long_to_bytes(v[0], 20) + | |
355 Crypto.Util.number.long_to_bytes(v[1], 20))) | |
356 return key, sig | |
357 | |
358 def test_verifyRSA(self): | |
359 """ | |
360 Test that RSA signatures are verified appropriately. | |
361 """ | |
362 data = 'data' | |
363 key, sig = self._signRSA(data) | |
364 self.assertTrue(self.assertWarns(DeprecationWarning, "verifySignature " | |
365 "is deprecated since Twisted Conch 0.9. Use " | |
366 "Key(obj).verify(signature, data).", unittest.__file__, | |
367 keys.verifySignature, key, sig, data)) | |
368 | |
369 def test_verifyDSA(self): | |
370 """ | |
371 Test that RSA signatures are verified appropriately. | |
372 """ | |
373 data = 'data' | |
374 key, sig = self._signDSA(data) | |
375 self.assertTrue(self.assertWarns(DeprecationWarning, "verifySignature " | |
376 "is deprecated since Twisted Conch 0.9. Use " | |
377 "Key(obj).verify(signature, data).", unittest.__file__, | |
378 keys.verifySignature, key, sig, data)) | |
379 | |
380 def test_objectType(self): | |
381 """ | |
382 Test that objectType, returns the correct type for objects. | |
383 """ | |
384 self.assertEquals(keys.objectType(keys.Key.fromString( | |
385 keydata.privateRSA_openssh).keyObject), 'ssh-rsa') | |
386 self.assertEquals(keys.objectType(keys.Key.fromString( | |
387 keydata.privateDSA_openssh).keyObject), 'ssh-dss') | |
388 self.assertRaises(keys.BadKeyError, keys.objectType, None) | |
389 | |
390 def test_asn1PackError(self): | |
391 """ | |
392 L{asn1.pack} should raise a C{ValueError} when given a type not | |
393 handled. | |
394 """ | |
395 self.assertRaises(ValueError, asn1.pack, [object()]) | |
396 | |
397 def test_printKey(self): | |
398 """ | |
399 Test that the printKey function prints correctly. | |
400 """ | |
401 obj = keys.Key.fromString(keydata.privateRSA_openssh).keyObject | |
402 self.assertEquals(self.assertWarns(DeprecationWarning, "printKey is " | |
403 "deprecated since Twisted Conch 0.9. Use repr(Key(obj)).", | |
404 unittest.__file__, keys.printKey, obj), | |
405 """RSA Private Key (767 bits) | |
406 attr e: | |
407 \t23 | |
408 attr d: | |
409 \t6e:1f:b5:55:97:eb:ed:67:ed:2b:99:6e:ec:c1:ed: | |
410 \ta8:4d:52:d6:f3:d6:65:06:04:df:e5:54:9f:cc:89: | |
411 \t00:3c:9b:67:87:ec:65:a0:ab:cd:6f:65:90:8a:97: | |
412 \t90:4d:c6:21:8f:a8:8d:d8:59:86:43:b5:81:b1:b4: | |
413 \td7:5f:2c:22:0a:61:c1:25:8a:47:12:b4:9a:f8:7a: | |
414 \t11:1c:4a:a8:8b:75:c4:91:09:3b:be:04:ca:45:d9: | |
415 \t57:8a:0d:27:cb:23 | |
416 attr n: | |
417 \t00:af:32:71:f0:e6:0e:9c:99:b3:7f:8b:5f:04:4b: | |
418 \tcb:8b:c0:d5:3e:b2:77:fd:cf:64:d8:8f:c0:cf:ae: | |
419 \t1f:c6:31:df:f6:29:b2:44:96:e2:c6:d4:21:94:7f: | |
420 \t65:7c:d8:d4:23:1f:b8:2e:6a:c9:1f:94:0d:46:c1: | |
421 \t69:a2:b7:07:0c:a3:93:c1:34:d8:2e:1e:4a:99:1a: | |
422 \t6c:96:46:07:46:2b:dc:25:29:1b:87:f0:be:05:1d: | |
423 \tee:b4:34:b9:e7:99:95 | |
424 attr q: | |
425 \t00:dc:9f:6b:d9:98:21:56:11:8d:e9:5f:03:9d:0a: | |
426 \td3:93:6e:13:77:41:3c:85:4f:00:70:fd:05:54:ff: | |
427 \tbc:3d:09:bf:83:f6:97:7f:64:10:91:04:fe:a2:67: | |
428 \t47:54:42:6b | |
429 attr p: | |
430 \t00:cb:4a:4b:d0:40:47:e8:45:52:f7:c7:af:0c:20: | |
431 \t6d:43:0d:b6:39:94:f9:da:a5:e5:03:06:76:83:24: | |
432 \teb:88:a1:55:a2:a8:de:12:3b:77:49:92:8a:a9:71: | |
433 \td2:02:93:ff | |
434 attr u: | |
435 \t00:b4:73:97:4b:50:10:a3:17:b3:a8:47:f1:3a:14: | |
436 \t76:52:d1:38:2a:cf:12:14:34:c1:a8:54:4c:29:35: | |
437 \t80:a0:38:b8:f0:fa:4c:c4:c2:85:ab:db:87:82:ba: | |
438 \tdc:eb:db:2a""") | |
439 | |
440 class KeyTestCase(unittest.TestCase): | |
441 | |
442 def setUp(self): | |
443 self.rsaObj = Crypto.PublicKey.RSA.construct((1L, 2L, 3L, 4L, 5L)) | |
444 self.dsaObj = Crypto.PublicKey.DSA.construct((1L, 2L, 3L, 4L, 5L)) | |
445 self.rsaSignature = ('\x00\x00\x00\x07ssh-rsa\x00' | |
446 '\x00\x00`N\xac\xb4@qK\xa0(\xc3\xf2h \xd3\xdd\xee6Np\x9d_' | |
447 '\xb0>\xe3\x0c(L\x9d{\txUd|!\xf6m\x9c\xd3\x93\x842\x7fU' | |
448 '\x05\xf4\xf7\xfaD\xda\xce\x81\x8ea\x7f=Y\xed*\xb7\xba\x81' | |
449 '\xf2\xad\xda\xeb(\x97\x03S\x08\x81\xc7\xb1\xb7\xe6\xe3' | |
450 '\xcd*\xd4\xbd\xc0wt\xf7y\xcd\xf0\xb7\x7f\xfb\x1e>\xf9r' | |
451 '\x8c\xba') | |
452 self.dsaSignature = ('\x00\x00\x00\x07ssh-dss\x00\x00' | |
453 '\x00(\x18z)H\x8a\x1b\xc6\r\xbbq\xa2\xd7f\x7f$\xa7\xbf' | |
454 '\xe8\x87\x8c\x88\xef\xd9k\x1a\x98\xdd{=\xdec\x18\t\xe3' | |
455 '\x87\xa9\xc72h\x95') | |
456 self.oldSecureRandom = randbytes.secureRandom | |
457 randbytes.secureRandom = lambda x: '\xff' * x | |
458 self.keyFile = self.mktemp() | |
459 file(self.keyFile, 'wb').write(keydata.privateRSA_lsh) | |
460 | |
461 def tearDown(self): | |
462 randbytes.secureRandom = self.oldSecureRandom | |
463 del self.oldSecureRandom | |
464 os.unlink(self.keyFile) | |
465 | |
466 def test__guessStringType(self): | |
467 """ | |
468 Test that the _guessStringType method guesses string types | |
469 correctly. | |
470 """ | |
471 self.assertEquals(keys.Key._guessStringType(keydata.publicRSA_openssh), | |
472 'public_openssh') | |
473 self.assertEquals(keys.Key._guessStringType(keydata.publicDSA_openssh), | |
474 'public_openssh') | |
475 self.assertEquals(keys.Key._guessStringType( | |
476 keydata.privateRSA_openssh), 'private_openssh') | |
477 self.assertEquals(keys.Key._guessStringType( | |
478 keydata.privateDSA_openssh), 'private_openssh') | |
479 self.assertEquals(keys.Key._guessStringType(keydata.publicRSA_lsh), | |
480 'public_lsh') | |
481 self.assertEquals(keys.Key._guessStringType(keydata.publicDSA_lsh), | |
482 'public_lsh') | |
483 self.assertEquals(keys.Key._guessStringType(keydata.privateRSA_lsh), | |
484 'private_lsh') | |
485 self.assertEquals(keys.Key._guessStringType(keydata.privateDSA_lsh), | |
486 'private_lsh') | |
487 self.assertEquals(keys.Key._guessStringType( | |
488 keydata.privateRSA_agentv3), 'agentv3') | |
489 self.assertEquals(keys.Key._guessStringType( | |
490 keydata.privateDSA_agentv3), 'agentv3') | |
491 self.assertEquals(keys.Key._guessStringType( | |
492 '\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x01\x01'), | |
493 'blob') | |
494 self.assertEquals(keys.Key._guessStringType( | |
495 '\x00\x00\x00\x07ssh-dss\x00\x00\x00\x01\x01'), | |
496 'blob') | |
497 self.assertEquals(keys.Key._guessStringType('not a key'), | |
498 None) | |
499 | |
500 def _testPublicPrivateFromString(self, public, private, type, data): | |
501 self._testPublicFromString(public, type, data) | |
502 self._testPrivateFromString(private, type, data) | |
503 | |
504 def _testPublicFromString(self, public, type, data): | |
505 publicKey = keys.Key.fromString(public) | |
506 self.assertTrue(publicKey.isPublic()) | |
507 self.assertEquals(publicKey.type(), type) | |
508 for k, v in publicKey.data().items(): | |
509 self.assertEquals(data[k], v) | |
510 | |
511 def _testPrivateFromString(self, private, type, data): | |
512 privateKey = keys.Key.fromString(private) | |
513 self.assertFalse(privateKey.isPublic()) | |
514 self.assertEquals(privateKey.type(), type) | |
515 for k, v in data.items(): | |
516 self.assertEquals(privateKey.data()[k], v) | |
517 | |
518 def test_fromOpenSSH(self): | |
519 """ | |
520 Test that keys are correctly generated from OpenSSH strings. | |
521 """ | |
522 self._testPublicPrivateFromString(keydata.publicRSA_openssh, | |
523 keydata.privateRSA_openssh, 'RSA', keydata.RSAData) | |
524 self.assertEquals(keys.Key.fromString( | |
525 keydata.privateRSA_openssh_encrypted, | |
526 passphrase='encrypted'), | |
527 keys.Key.fromString(keydata.privateRSA_openssh)) | |
528 self.assertEquals(keys.Key.fromString( | |
529 keydata.privateRSA_openssh_alternate), | |
530 keys.Key.fromString(keydata.privateRSA_openssh)) | |
531 self._testPublicPrivateFromString(keydata.publicDSA_openssh, | |
532 keydata.privateDSA_openssh, 'DSA', keydata.DSAData) | |
533 | |
534 def test_fromLSH(self): | |
535 """ | |
536 Test that keys are correctly generated from LSH strings. | |
537 """ | |
538 self._testPublicPrivateFromString(keydata.publicRSA_lsh, | |
539 keydata.privateRSA_lsh, 'RSA', keydata.RSAData) | |
540 self._testPublicPrivateFromString(keydata.publicDSA_lsh, | |
541 keydata.privateDSA_lsh, 'DSA', keydata.DSAData) | |
542 sexp = sexpy.pack([['public-key', ['bad-key', ['p', '2']]]]) | |
543 self.assertRaises(keys.BadKeyError, keys.Key.fromString, | |
544 data='{'+base64.encodestring(sexp)+'}') | |
545 sexp = sexpy.pack([['private-key', ['bad-key', ['p', '2']]]]) | |
546 self.assertRaises(keys.BadKeyError, keys.Key.fromString, | |
547 sexp) | |
548 | |
549 def test_fromAgentv3(self): | |
550 """ | |
551 Test that keys are correctly generated from Agent v3 strings. | |
552 """ | |
553 self._testPrivateFromString(keydata.privateRSA_agentv3, 'RSA', | |
554 keydata.RSAData) | |
555 self._testPrivateFromString(keydata.privateDSA_agentv3, 'DSA', | |
556 keydata.DSAData) | |
557 self.assertRaises(keys.BadKeyError, keys.Key.fromString, | |
558 '\x00\x00\x00\x07ssh-foo'+'\x00\x00\x00\x01\x01'*5) | |
559 | |
560 def test_fromStringErrors(self): | |
561 """ | |
562 Test that fromString raises errors appropriately. | |
563 """ | |
564 self.assertRaises(keys.BadKeyError, keys.Key.fromString, '') | |
565 self.assertRaises(keys.BadKeyError, keys.Key.fromString, '', | |
566 'bad_type') | |
567 self.assertRaises(keys.BadKeyError, keys.Key.fromString, | |
568 keydata.publicRSA_lsh, passphrase = 'unencrypted') | |
569 self.assertRaises(keys.EncryptedKeyError, keys.Key.fromString, | |
570 keys.Key(self.rsaObj).toString('openssh', 'encrypted')) | |
571 self.assertRaises(keys.BadKeyError, keys.Key.fromString, | |
572 '-----BEGIN RSA KEY-----\nwA==\n') | |
573 | |
574 def test_fromFile(self): | |
575 """ | |
576 Test that fromFile works correctly. | |
577 """ | |
578 self.assertEquals(keys.Key.fromFile(self.keyFile), | |
579 keys.Key.fromString(keydata.privateRSA_lsh)) | |
580 self.assertRaises(keys.BadKeyError, keys.Key.fromFile, | |
581 self.keyFile, 'bad_type') | |
582 self.assertRaises(keys.BadKeyError, keys.Key.fromFile, | |
583 self.keyFile, passphrase='unencrypted') | |
584 | |
585 def test_init(self): | |
586 """ | |
587 Test that the PublicKey object is initialized correctly. | |
588 """ | |
589 obj = Crypto.PublicKey.RSA.construct((1L, 2L)) | |
590 key = keys.Key(obj) | |
591 self.assertEquals(key.keyObject, obj) | |
592 | |
593 def test_equal(self): | |
594 """ | |
595 Test that Key objects are compared correctly. | |
596 """ | |
597 rsa1 = keys.Key(self.rsaObj) | |
598 rsa2 = keys.Key(self.rsaObj) | |
599 rsa3 = keys.Key(Crypto.PublicKey.RSA.construct((1L, 2L))) | |
600 dsa = keys.Key(self.dsaObj) | |
601 self.assertTrue(rsa1 == rsa2) | |
602 self.assertFalse(rsa1 == rsa3) | |
603 self.assertFalse(rsa1 == dsa) | |
604 self.assertFalse(rsa1 == object) | |
605 self.assertFalse(rsa1 == None) | |
606 | |
607 def test_notEqual(self): | |
608 """ | |
609 Test that Key objects are not-compared correctly. | |
610 """ | |
611 rsa1 = keys.Key(self.rsaObj) | |
612 rsa2 = keys.Key(self.rsaObj) | |
613 rsa3 = keys.Key(Crypto.PublicKey.RSA.construct((1L, 2L))) | |
614 dsa = keys.Key(self.dsaObj) | |
615 self.assertFalse(rsa1 != rsa2) | |
616 self.assertTrue(rsa1 != rsa3) | |
617 self.assertTrue(rsa1 != dsa) | |
618 self.assertTrue(rsa1 != object) | |
619 self.assertTrue(rsa1 != None) | |
620 | |
621 def test_type(self): | |
622 """ | |
623 Test that the type method returns the correct type for an object. | |
624 """ | |
625 self.assertEquals(keys.Key(self.rsaObj).type(), 'RSA') | |
626 self.assertEquals(keys.Key(self.rsaObj).sshType(), 'ssh-rsa') | |
627 self.assertEquals(keys.Key(self.dsaObj).type(), 'DSA') | |
628 self.assertEquals(keys.Key(self.dsaObj).sshType(), 'ssh-dss') | |
629 self.assertRaises(RuntimeError, keys.Key(None).type) | |
630 self.assertRaises(RuntimeError, keys.Key(None).sshType) | |
631 self.assertRaises(RuntimeError, keys.Key(self).type) | |
632 self.assertRaises(RuntimeError, keys.Key(self).sshType) | |
633 | |
634 def test_fromBlob(self): | |
635 """ | |
636 Test that a public key is correctly generated from a public key blob. | |
637 """ | |
638 rsaBlob = common.NS('ssh-rsa') + common.MP(2) + common.MP(3) | |
639 rsaKey = keys.Key.fromString(rsaBlob) | |
640 dsaBlob = (common.NS('ssh-dss') + common.MP(2) + common.MP(3) + | |
641 common.MP(4) + common.MP(5)) | |
642 dsaKey = keys.Key.fromString(dsaBlob) | |
643 badBlob = common.NS('ssh-bad') | |
644 self.assertTrue(rsaKey.isPublic()) | |
645 self.assertEquals(rsaKey.data(), {'e':2L, 'n':3L}) | |
646 self.assertTrue(dsaKey.isPublic()) | |
647 self.assertEquals(dsaKey.data(), {'p':2L, 'q':3L, 'g':4L, 'y':5L}) | |
648 self.assertRaises(keys.BadKeyError, | |
649 keys.Key.fromString, badBlob) | |
650 | |
651 | |
652 def test_blob(self): | |
653 """ | |
654 Test that the Key object generates blobs correctly. | |
655 """ | |
656 self.assertEquals(keys.Key(self.rsaObj).blob(), | |
657 '\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x01\x02' | |
658 '\x00\x00\x00\x01\x01') | |
659 self.assertEquals(keys.Key(self.dsaObj).blob(), | |
660 '\x00\x00\x00\x07ssh-dss\x00\x00\x00\x01\x03' | |
661 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x02' | |
662 '\x00\x00\x00\x01\x01') | |
663 | |
664 badKey = keys.Key(None) | |
665 self.assertRaises(RuntimeError, badKey.blob) | |
666 | |
667 def test_toOpenSSH(self): | |
668 """ | |
669 Test that the Key object generates OpenSSH keys correctly. | |
670 """ | |
671 key = keys.Key.fromString(keydata.privateRSA_lsh) | |
672 self.assertEquals(key.toString('openssh'), keydata.privateRSA_openssh) | |
673 self.assertEquals(key.toString('openssh', 'encrypted'), | |
674 keydata.privateRSA_openssh_encrypted) | |
675 self.assertEquals(key.public().toString('openssh'), | |
676 keydata.publicRSA_openssh[:-8]) # no comment | |
677 self.assertEquals(key.public().toString('openssh', 'comment'), | |
678 keydata.publicRSA_openssh) | |
679 key = keys.Key.fromString(keydata.privateDSA_lsh) | |
680 self.assertEquals(key.toString('openssh'), keydata.privateDSA_openssh) | |
681 self.assertEquals(key.public().toString('openssh', 'comment'), | |
682 keydata.publicDSA_openssh) | |
683 self.assertEquals(key.public().toString('openssh'), | |
684 keydata.publicDSA_openssh[:-8]) # no comment | |
685 | |
686 def test_toLSH(self): | |
687 """ | |
688 Test that the Key object generates LSH keys correctly. | |
689 """ | |
690 key = keys.Key.fromString(keydata.privateRSA_openssh) | |
691 self.assertEquals(key.toString('lsh'), keydata.privateRSA_lsh) | |
692 self.assertEquals(key.public().toString('lsh'), | |
693 keydata.publicRSA_lsh) | |
694 key = keys.Key.fromString(keydata.privateDSA_openssh) | |
695 self.assertEquals(key.toString('lsh'), keydata.privateDSA_lsh) | |
696 self.assertEquals(key.public().toString('lsh'), | |
697 keydata.publicDSA_lsh) | |
698 | |
699 def test_toAgentv3(self): | |
700 """ | |
701 Test that the Key object generates Agent v3 keys correctly. | |
702 """ | |
703 key = keys.Key.fromString(keydata.privateRSA_openssh) | |
704 self.assertEquals(key.toString('agentv3'), keydata.privateRSA_agentv3) | |
705 key = keys.Key.fromString(keydata.privateDSA_openssh) | |
706 self.assertEquals(key.toString('agentv3'), keydata.privateDSA_agentv3) | |
707 | |
708 def test_toStringErrors(self): | |
709 """ | |
710 Test that toString raises errors appropriately. | |
711 """ | |
712 self.assertRaises(keys.BadKeyError, keys.Key(self.rsaObj).toString, | |
713 'bad_type') | |
714 | |
715 def test_sign(self): | |
716 """ | |
717 Test that the Key object generates correct signatures. | |
718 """ | |
719 key = keys.Key.fromString(keydata.privateRSA_openssh) | |
720 self.assertEquals(key.sign(''), self.rsaSignature) | |
721 key = keys.Key.fromString(keydata.privateDSA_openssh) | |
722 self.assertEquals(key.sign(''), self.dsaSignature) | |
723 | |
724 | |
725 def test_verify(self): | |
726 """ | |
727 Test that the Key object correctly verifies signatures. | |
728 """ | |
729 key = keys.Key.fromString(keydata.publicRSA_openssh) | |
730 self.assertTrue(key.verify(self.rsaSignature, '')) | |
731 self.assertFalse(key.verify(self.rsaSignature, 'a')) | |
732 self.assertFalse(key.verify(self.dsaSignature, '')) | |
733 key = keys.Key.fromString(keydata.publicDSA_openssh) | |
734 self.assertTrue(key.verify(self.dsaSignature, '')) | |
735 self.assertFalse(key.verify(self.dsaSignature, 'a')) | |
736 self.assertFalse(key.verify(self.rsaSignature, '')) | |
737 | |
738 def test_repr(self): | |
739 """ | |
740 Test the pretty representation of Key. | |
741 """ | |
742 self.assertEquals(repr(keys.Key(self.rsaObj)), | |
743 """<RSA Private Key (0 bits) | |
744 attr e: | |
745 \t02 | |
746 attr d: | |
747 \t03 | |
748 attr n: | |
749 \t01 | |
750 attr q: | |
751 \t05 | |
752 attr p: | |
753 \t04 | |
754 attr u: | |
755 \t04>""") | |
756 | |
757 class WarningsTestCase(unittest.TestCase): | |
758 """ | |
759 Test that deprecated functions warn the user of their deprecation. | |
760 """ | |
761 | |
762 def setUp(self): | |
763 self.keyObject = keys.Key.fromString(keydata.privateRSA_lsh).keyObject | |
764 | |
765 def test_getPublicKeyString(self): | |
766 """ | |
767 Test that getPublicKeyString warns with a DeprecationWarning. | |
768 """ | |
769 self.assertWarns(DeprecationWarning, | |
770 "getPublicKeyString is deprecated since Twisted Conch 0.9." | |
771 " Use Key.fromString().", | |
772 unittest.__file__, keys.getPublicKeyString, | |
773 data=keydata.publicRSA_openssh) | |
774 | |
775 def test_makePublicKeyString(self): | |
776 """ | |
777 Test that makePublicKeyString warns with a DeprecationWarning. | |
778 """ | |
779 self.assertWarns(DeprecationWarning, | |
780 "makePublicKeyString is deprecated since Twisted Conch 0.9." | |
781 " Use Key(obj).toString().", unittest.__file__, | |
782 keys.makePublicKeyString, self.keyObject) | |
783 | |
784 def test_getPublicKeyObject(self): | |
785 """ | |
786 Test that getPublicKeyObject warns with a DeprecationWarning. | |
787 """ | |
788 self.assertWarns(DeprecationWarning, | |
789 "getPublicKeyObject is deprecated since Twisted Conch 0.9." | |
790 " Use Key.fromString().", unittest.__file__, | |
791 keys.getPublicKeyObject, keydata.publicRSA_lsh) | |
792 | |
793 def test_getPrivateKeyObject(self): | |
794 """ | |
795 Test that getPrivateKeyObject warns with a DeprecationWarning. | |
796 """ | |
797 self.assertWarns(DeprecationWarning, | |
798 "getPrivateKeyObject is deprecated since Twisted Conch 0.9." | |
799 " Use Key.fromString().", unittest.__file__, | |
800 keys.getPrivateKeyObject, data=keydata.privateRSA_lsh) | |
801 | |
802 def test_makePrivateKeyString(self): | |
803 """ | |
804 Test that makePrivateKeyString warns with a DeprecationWarning. | |
805 """ | |
806 self.assertWarns(DeprecationWarning, | |
807 "makePrivateKeyString is deprecated since Twisted Conch 0.9." | |
808 " Use Key(obj).toString().", unittest.__file__, | |
809 keys.makePrivateKeyString, self.keyObject) | |
810 | |
811 def test_makePublicKeyBlob(self): | |
812 """ | |
813 Test that makePublicKeyBlob warns with a DeprecationWarning. | |
814 """ | |
815 self.assertWarns(DeprecationWarning, | |
816 "makePublicKeyBlob is deprecated since Twisted Conch 0.9." | |
817 " Use Key(obj).blob().", unittest.__file__, | |
818 keys.makePublicKeyBlob, self.keyObject) | |
819 | |
820 def test_signData(self): | |
821 """ | |
822 Test that signData warns with a DeprecationWarning. | |
823 """ | |
824 self.assertWarns(DeprecationWarning, | |
825 "signData is deprecated since Twisted Conch 0.9." | |
826 " Use Key(obj).sign(data).", unittest.__file__, | |
827 keys.signData, self.keyObject, '') | |
828 | |
829 def test_verifySignature(self): | |
830 """ | |
831 Test that signData warns with a DeprecationWarning. | |
832 """ | |
833 self.assertWarns(DeprecationWarning, | |
834 "verifySignature is deprecated since Twisted Conch 0.9." | |
835 " Use Key(obj).verify(signature, data).", unittest.__file__, | |
836 keys.verifySignature, self.keyObject, '\x00\x00\x00\x00', '') | |
837 | |
838 def test_printKey(self): | |
839 """ | |
840 Test that signData warns with a DeprecationWarning. | |
841 """ | |
842 self.assertWarns(DeprecationWarning, | |
843 "printKey is deprecated since Twisted Conch 0.9." | |
844 " Use repr(Key(obj)).", unittest.__file__, | |
845 keys.printKey, self.keyObject) | |
846 | |
OLD | NEW |