| 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 |