1"""passlib.tests.test_handlers - tests for passlib hash algorithms""" 2#============================================================================= 3# imports 4#============================================================================= 5from __future__ import with_statement 6# core 7import logging; log = logging.getLogger(__name__) 8import os 9import sys 10import warnings 11# site 12# pkg 13from passlib import exc, hash 14from passlib.utils import repeat_string 15from passlib.utils.compat import irange, PY3, u, get_method_function 16from passlib.tests.utils import TestCase, HandlerCase, skipUnless, \ 17 TEST_MODE, UserHandlerMixin, EncodingHandlerMixin 18# module 19 20#============================================================================= 21# constants & support 22#============================================================================= 23 24# some common unicode passwords which used as test cases 25UPASS_WAV = u('\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2') 26UPASS_USD = u("\u20AC\u00A5$") 27UPASS_TABLE = u("t\u00e1\u0411\u2113\u0259") 28 29PASS_TABLE_UTF8 = b't\xc3\xa1\xd0\x91\xe2\x84\x93\xc9\x99' # utf-8 30 31# handlers which support multiple backends, but don't have multi-backend tests. 32_omitted_backend_tests = ["django_bcrypt", "django_bcrypt_sha256", "django_argon2"] 33 34#: modules where get_handler_case() should search for test cases. 35_handler_test_modules = [ 36 "test_handlers", 37 "test_handlers_argon2", 38 "test_handlers_bcrypt", 39 "test_handlers_cisco", 40 "test_handlers_django", 41 "test_handlers_pbkdf2", 42 "test_handlers_scrypt", 43] 44 45def get_handler_case(scheme): 46 """ 47 return HandlerCase instance for scheme, used by other tests. 48 49 :param scheme: name of hasher to locate test for (e.g. "bcrypt") 50 51 :raises KeyError: 52 if scheme isn't known hasher. 53 54 :raises MissingBackendError: 55 if hasher doesn't have any available backends. 56 57 :returns: 58 HandlerCase subclass (which derives from TestCase) 59 """ 60 from passlib.registry import get_crypt_handler 61 handler = get_crypt_handler(scheme) 62 if hasattr(handler, "backends") and scheme not in _omitted_backend_tests: 63 # XXX: if no backends available, could proceed to pick first backend for test lookup; 64 # should investigate if that would be useful to callers. 65 try: 66 backend = handler.get_backend() 67 except exc.MissingBackendError: 68 assert scheme in conditionally_available_hashes 69 raise 70 name = "%s_%s_test" % (scheme, backend) 71 else: 72 name = "%s_test" % scheme 73 for module in _handler_test_modules: 74 modname = "passlib.tests." + module 75 __import__(modname) 76 mod = sys.modules[modname] 77 try: 78 return getattr(mod, name) 79 except AttributeError: 80 pass 81 # every hasher should have test suite, so if we get here, means test is either missing, 82 # misnamed, or _handler_test_modules list is out of date. 83 raise RuntimeError("can't find test case named %r for %r" % (name, scheme)) 84 85#: hashes which there may not be a backend available for, 86#: and get_handler_case() may (correctly) throw a MissingBackendError 87conditionally_available_hashes = ["argon2", "bcrypt", "bcrypt_sha256"] 88 89#============================================================================= 90# apr md5 crypt 91#============================================================================= 92class apr_md5_crypt_test(HandlerCase): 93 handler = hash.apr_md5_crypt 94 95 known_correct_hashes = [ 96 # 97 # http://httpd.apache.org/docs/2.2/misc/password_encryptions.html 98 # 99 ('myPassword', '$apr1$r31.....$HqJZimcKQFAMYayBlzkrA/'), 100 101 # 102 # custom 103 # 104 105 # ensures utf-8 used for unicode 106 (UPASS_TABLE, '$apr1$bzYrOHUx$a1FcpXuQDJV3vPY20CS6N1'), 107 ] 108 109 known_malformed_hashes = [ 110 # bad char in otherwise correct hash ----\/ 111 '$apr1$r31.....$HqJZimcKQFAMYayBlzkrA!' 112 ] 113 114#============================================================================= 115# bigcrypt 116#============================================================================= 117class bigcrypt_test(HandlerCase): 118 handler = hash.bigcrypt 119 120 # TODO: find an authoritative source of test vectors 121 known_correct_hashes = [ 122 123 # 124 # various docs & messages on the web. 125 # 126 ("passphrase", "qiyh4XPJGsOZ2MEAyLkfWqeQ"), 127 ("This is very long passwd", "f8.SVpL2fvwjkAnxn8/rgTkwvrif6bjYB5c"), 128 129 # 130 # custom 131 # 132 133 # ensures utf-8 used for unicode 134 (UPASS_TABLE, 'SEChBAyMbMNhgGLyP7kD1HZU'), 135 ] 136 137 known_unidentified_hashes = [ 138 # one char short (10 % 11) 139 "qiyh4XPJGsOZ2MEAyLkfWqe" 140 141 # one char too many (1 % 11) 142 "f8.SVpL2fvwjkAnxn8/rgTkwvrif6bjYB5cd" 143 ] 144 145 # omit des_crypt from known_other since it's a valid bigcrypt hash too. 146 known_other_hashes = [row for row in HandlerCase.known_other_hashes 147 if row[0] != "des_crypt"] 148 149 def test_90_internal(self): 150 # check that _norm_checksum() also validates checksum size. 151 # (current code uses regex in parser) 152 self.assertRaises(ValueError, hash.bigcrypt, use_defaults=True, 153 checksum=u('yh4XPJGsOZ')) 154 155#============================================================================= 156# bsdi crypt 157#============================================================================= 158class _bsdi_crypt_test(HandlerCase): 159 """test BSDiCrypt algorithm""" 160 handler = hash.bsdi_crypt 161 162 known_correct_hashes = [ 163 # 164 # from JTR 1.7.9 165 # 166 ('U*U*U*U*', '_J9..CCCCXBrJUJV154M'), 167 ('U*U***U', '_J9..CCCCXUhOBTXzaiE'), 168 ('U*U***U*', '_J9..CCCC4gQ.mB/PffM'), 169 ('*U*U*U*U', '_J9..XXXXvlzQGqpPPdk'), 170 ('*U*U*U*U*', '_J9..XXXXsqM/YSSP..Y'), 171 ('*U*U*U*U*U*U*U*U', '_J9..XXXXVL7qJCnku0I'), 172 ('*U*U*U*U*U*U*U*U*', '_J9..XXXXAj8cFbP5scI'), 173 ('ab1234567', '_J9..SDizh.vll5VED9g'), 174 ('cr1234567', '_J9..SDizRjWQ/zePPHc'), 175 ('zxyDPWgydbQjgq', '_J9..SDizxmRI1GjnQuE'), 176 ('726 even', '_K9..SaltNrQgIYUAeoY'), 177 ('', '_J9..SDSD5YGyRCr4W4c'), 178 179 # 180 # custom 181 # 182 (" ", "_K1..crsmZxOLzfJH8iw"), 183 ("my", '_KR/.crsmykRplHbAvwA'), # <-- to detect old 12-bit rounds bug 184 ("my socra", "_K1..crsmf/9NzZr1fLM"), 185 ("my socrates", '_K1..crsmOv1rbde9A9o'), 186 ("my socrates note", "_K1..crsm/2qeAhdISMA"), 187 188 # ensures utf-8 used for unicode 189 (UPASS_TABLE, '_7C/.ABw0WIKy0ILVqo2'), 190 ] 191 known_unidentified_hashes = [ 192 # bad char in otherwise correctly formatted hash 193 # \/ 194 "_K1.!crsmZxOLzfJH8iw" 195 ] 196 197 platform_crypt_support = [ 198 # openbsd 5.8 dropped everything except bcrypt 199 ("openbsd[6789]", False), 200 ("openbsd5", None), 201 ("openbsd", True), 202 203 ("freebsd|netbsd|darwin", True), 204 ("solaris", False), 205 ("linux", None), # may be present if libxcrypt is in use 206 ] 207 208 def test_77_fuzz_input(self, **kwds): 209 # we want to generate even rounds to verify it's correct, but want to ignore warnings 210 warnings.filterwarnings("ignore", "bsdi_crypt rounds should be odd.*") 211 super(_bsdi_crypt_test, self).test_77_fuzz_input(**kwds) 212 213 def test_needs_update_w_even_rounds(self): 214 """needs_update() should flag even rounds""" 215 handler = self.handler 216 even_hash = '_Y/../cG0zkJa6LY6k4c' 217 odd_hash = '_Z/..TgFg0/ptQtpAgws' 218 secret = 'test' 219 220 # don't issue warning 221 self.assertTrue(handler.verify(secret, even_hash)) 222 self.assertTrue(handler.verify(secret, odd_hash)) 223 224 # *do* signal as needing updates 225 self.assertTrue(handler.needs_update(even_hash)) 226 self.assertFalse(handler.needs_update(odd_hash)) 227 228 # new hashes shouldn't have even rounds 229 new_hash = handler.hash("stub") 230 self.assertFalse(handler.needs_update(new_hash)) 231 232# create test cases for specific backends 233bsdi_crypt_os_crypt_test = _bsdi_crypt_test.create_backend_case("os_crypt") 234bsdi_crypt_builtin_test = _bsdi_crypt_test.create_backend_case("builtin") 235 236#============================================================================= 237# crypt16 238#============================================================================= 239class crypt16_test(HandlerCase): 240 handler = hash.crypt16 241 242 # TODO: find an authortative source of test vectors 243 known_correct_hashes = [ 244 # 245 # from messages around the web, including 246 # http://seclists.org/bugtraq/1999/Mar/76 247 # 248 ("passphrase", "qi8H8R7OM4xMUNMPuRAZxlY."), 249 ("printf", "aaCjFz4Sh8Eg2QSqAReePlq6"), 250 ("printf", "AA/xje2RyeiSU0iBY3PDwjYo"), 251 ("LOLOAQICI82QB4IP", "/.FcK3mad6JwYt8LVmDqz9Lc"), 252 ("LOLOAQICI", "/.FcK3mad6JwYSaRHJoTPzY2"), 253 ("LOLOAQIC", "/.FcK3mad6JwYelhbtlysKy6"), 254 ("L", "/.CIu/PzYCkl6elhbtlysKy6"), 255 256 # 257 # custom 258 # 259 260 # ensures utf-8 used for unicode 261 (UPASS_TABLE, 'YeDc9tKkkmDvwP7buzpwhoqQ'), 262 ] 263 264#============================================================================= 265# des crypt 266#============================================================================= 267class _des_crypt_test(HandlerCase): 268 """test des-crypt algorithm""" 269 handler = hash.des_crypt 270 271 known_correct_hashes = [ 272 # 273 # from JTR 1.7.9 274 # 275 ('U*U*U*U*', 'CCNf8Sbh3HDfQ'), 276 ('U*U***U', 'CCX.K.MFy4Ois'), 277 ('U*U***U*', 'CC4rMpbg9AMZ.'), 278 ('*U*U*U*U', 'XXxzOu6maQKqQ'), 279 ('', 'SDbsugeBiC58A'), 280 281 # 282 # custom 283 # 284 ('', 'OgAwTx2l6NADI'), 285 (' ', '/Hk.VPuwQTXbc'), 286 ('test', 'N1tQbOFcM5fpg'), 287 ('Compl3X AlphaNu3meric', 'um.Wguz3eVCx2'), 288 ('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', 'sNYqfOyauIyic'), 289 ('AlOtBsOl', 'cEpWz5IUCShqM'), 290 291 # ensures utf-8 used for unicode 292 (u('hell\u00D6'), 'saykDgk3BPZ9E'), 293 ] 294 known_unidentified_hashes = [ 295 # bad char in otherwise correctly formatted hash 296 #\/ 297 '!gAwTx2l6NADI', 298 299 # wrong size 300 'OgAwTx2l6NAD', 301 'OgAwTx2l6NADIj', 302 ] 303 304 platform_crypt_support = [ 305 # openbsd 5.8 dropped everything except bcrypt 306 ("openbsd[6789]", False), 307 ("openbsd5", None), 308 ("openbsd", True), 309 310 ("freebsd|netbsd|linux|solaris|darwin", True), 311 ] 312 313# create test cases for specific backends 314des_crypt_os_crypt_test = _des_crypt_test.create_backend_case("os_crypt") 315des_crypt_builtin_test = _des_crypt_test.create_backend_case("builtin") 316 317#============================================================================= 318# fshp 319#============================================================================= 320class fshp_test(HandlerCase): 321 """test fshp algorithm""" 322 handler = hash.fshp 323 324 known_correct_hashes = [ 325 # 326 # test vectors from FSHP reference implementation 327 # https://github.com/bdd/fshp-is-not-secure-anymore/blob/master/python/test.py 328 # 329 ('test', '{FSHP0|0|1}qUqP5cyxm6YcTAhz05Hph5gvu9M='), 330 331 ('test', 332 '{FSHP1|8|4096}MTIzNDU2NzjTdHcmoXwNc0f' 333 'f9+ArUHoN0CvlbPZpxFi1C6RDM/MHSA==' 334 ), 335 336 ('OrpheanBeholderScryDoubt', 337 '{FSHP1|8|4096}GVSUFDAjdh0vBosn1GUhz' 338 'GLHP7BmkbCZVH/3TQqGIjADXpc+6NCg3g==' 339 ), 340 ('ExecuteOrder66', 341 '{FSHP3|16|8192}0aY7rZQ+/PR+Rd5/I9ss' 342 'RM7cjguyT8ibypNaSp/U1uziNO3BVlg5qPU' 343 'ng+zHUDQC3ao/JbzOnIBUtAeWHEy7a2vZeZ' 344 '7jAwyJJa2EqOsq4Io=' 345 ), 346 347 # 348 # custom 349 # 350 351 # ensures utf-8 used for unicode 352 (UPASS_TABLE, '{FSHP1|16|16384}9v6/l3Lu/d9by5nznpOS' 353 'cqQo8eKu/b/CKli3RCkgYg4nRTgZu5y659YV8cCZ68UL'), 354 ] 355 356 known_unidentified_hashes = [ 357 # incorrect header 358 '{FSHX0|0|1}qUqP5cyxm6YcTAhz05Hph5gvu9M=', 359 'FSHP0|0|1}qUqP5cyxm6YcTAhz05Hph5gvu9M=', 360 ] 361 362 known_malformed_hashes = [ 363 # bad base64 padding 364 '{FSHP0|0|1}qUqP5cyxm6YcTAhz05Hph5gvu9M', 365 366 # wrong salt size 367 '{FSHP0|1|1}qUqP5cyxm6YcTAhz05Hph5gvu9M=', 368 369 # bad rounds 370 '{FSHP0|0|A}qUqP5cyxm6YcTAhz05Hph5gvu9M=', 371 ] 372 373 def test_90_variant(self): 374 """test variant keyword""" 375 handler = self.handler 376 kwds = dict(salt=b'a', rounds=1) 377 378 # accepts ints 379 handler(variant=1, **kwds) 380 381 # accepts bytes or unicode 382 handler(variant=u('1'), **kwds) 383 handler(variant=b'1', **kwds) 384 385 # aliases 386 handler(variant=u('sha256'), **kwds) 387 handler(variant=b'sha256', **kwds) 388 389 # rejects None 390 self.assertRaises(TypeError, handler, variant=None, **kwds) 391 392 # rejects other types 393 self.assertRaises(TypeError, handler, variant=complex(1,1), **kwds) 394 395 # invalid variant 396 self.assertRaises(ValueError, handler, variant='9', **kwds) 397 self.assertRaises(ValueError, handler, variant=9, **kwds) 398 399#============================================================================= 400# hex digests 401#============================================================================= 402class hex_md4_test(HandlerCase): 403 handler = hash.hex_md4 404 known_correct_hashes = [ 405 ("password", '8a9d093f14f8701df17732b2bb182c74'), 406 (UPASS_TABLE, '876078368c47817ce5f9115f3a42cf74'), 407 ] 408 409class hex_md5_test(HandlerCase): 410 handler = hash.hex_md5 411 known_correct_hashes = [ 412 ("password", '5f4dcc3b5aa765d61d8327deb882cf99'), 413 (UPASS_TABLE, '05473f8a19f66815e737b33264a0d0b0'), 414 ] 415 416 # XXX: should test this for ALL the create_hex_md5() hashers. 417 def test_mock_fips_mode(self): 418 """ 419 if md5 isn't available, a dummy instance should be created. 420 (helps on FIPS systems). 421 """ 422 from passlib.exc import UnknownHashError 423 from passlib.crypto.digest import lookup_hash, _set_mock_fips_mode 424 425 # check if md5 is available so we can test mock helper 426 supported = lookup_hash("md5", required=False).supported 427 self.assertEqual(self.handler.supported, supported) 428 if supported: 429 _set_mock_fips_mode() 430 self.addCleanup(_set_mock_fips_mode, False) 431 432 # HACK: have to recreate hasher, since underlying HashInfo has changed. 433 # could reload module and re-import, but this should be good enough. 434 from passlib.handlers.digests import create_hex_hash 435 hasher = create_hex_hash("md5", required=False) 436 self.assertFalse(hasher.supported) 437 438 # can identify hashes even if disabled 439 ref1 = '5f4dcc3b5aa765d61d8327deb882cf99' 440 ref2 = 'xxx' 441 self.assertTrue(hasher.identify(ref1)) 442 self.assertFalse(hasher.identify(ref2)) 443 444 # throw error if try to use it 445 pat = "'md5' hash disabled for fips" 446 self.assertRaisesRegex(UnknownHashError, pat, hasher.hash, "password") 447 self.assertRaisesRegex(UnknownHashError, pat, hasher.verify, "password", ref1) 448 449 450class hex_sha1_test(HandlerCase): 451 handler = hash.hex_sha1 452 known_correct_hashes = [ 453 ("password", '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'), 454 (UPASS_TABLE, 'e059b2628e3a3e2de095679de9822c1d1466e0f0'), 455 ] 456 457class hex_sha256_test(HandlerCase): 458 handler = hash.hex_sha256 459 known_correct_hashes = [ 460 ("password", '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8'), 461 (UPASS_TABLE, '6ed729e19bf24d3d20f564375820819932029df05547116cfc2cc868a27b4493'), 462 ] 463 464class hex_sha512_test(HandlerCase): 465 handler = hash.hex_sha512 466 known_correct_hashes = [ 467 ("password", 'b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c' 468 '706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cac' 469 'bc86'), 470 (UPASS_TABLE, 'd91bb0a23d66dca07a1781fd63ae6a05f6919ee5fc368049f350c9f' 471 '293b078a18165d66097cf0d89fdfbeed1ad6e7dba2344e57348cd6d51308c843a06f' 472 '29caf'), 473 ] 474 475#============================================================================= 476# htdigest hash 477#============================================================================= 478class htdigest_test(UserHandlerMixin, HandlerCase): 479 handler = hash.htdigest 480 481 known_correct_hashes = [ 482 # secret, user, realm 483 484 # from RFC 2617 485 (("Circle Of Life", "Mufasa", "testrealm@host.com"), 486 '939e7578ed9e3c518a452acee763bce9'), 487 488 # custom 489 ((UPASS_TABLE, UPASS_USD, UPASS_WAV), 490 '4dabed2727d583178777fab468dd1f17'), 491 ] 492 493 known_unidentified_hashes = [ 494 # bad char \/ - currently rejecting upper hex chars, may change 495 '939e7578edAe3c518a452acee763bce9', 496 497 # bad char \/ 498 '939e7578edxe3c518a452acee763bce9', 499 ] 500 501 def test_80_user(self): 502 raise self.skipTest("test case doesn't support 'realm' keyword") 503 504 def populate_context(self, secret, kwds): 505 """insert username into kwds""" 506 if isinstance(secret, tuple): 507 secret, user, realm = secret 508 else: 509 user, realm = "user", "realm" 510 kwds.setdefault("user", user) 511 kwds.setdefault("realm", realm) 512 return secret 513 514#============================================================================= 515# ldap hashes 516#============================================================================= 517class ldap_md5_test(HandlerCase): 518 handler = hash.ldap_md5 519 known_correct_hashes = [ 520 ("helloworld", '{MD5}/F4DjTilcDIIVEHn/nAQsA=='), 521 (UPASS_TABLE, '{MD5}BUc/ihn2aBXnN7MyZKDQsA=='), 522 ] 523 524class ldap_sha1_test(HandlerCase): 525 handler = hash.ldap_sha1 526 known_correct_hashes = [ 527 ("helloworld", '{SHA}at+xg6SiyUovktq1redipHiJpaE='), 528 (UPASS_TABLE, '{SHA}4FmyYo46Pi3glWed6YIsHRRm4PA='), 529 ] 530 531class ldap_salted_md5_test(HandlerCase): 532 handler = hash.ldap_salted_md5 533 known_correct_hashes = [ 534 ("testing1234", '{SMD5}UjFY34os/pnZQ3oQOzjqGu4yeXE='), 535 (UPASS_TABLE, '{SMD5}Z0ioJ58LlzUeRxm3K6JPGAvBGIM='), 536 537 # alternate salt sizes (8, 15, 16) 538 ('test', '{SMD5}LnuZPJhiaY95/4lmVFpg548xBsD4P4cw'), 539 ('test', '{SMD5}XRlncfRzvGi0FDzgR98tUgBg7B3jXOs9p9S615qTkg=='), 540 ('test', '{SMD5}FbAkzOMOxRbMp6Nn4hnZuel9j9Gas7a2lvI+x5hT6j0='), 541 ] 542 543 known_malformed_hashes = [ 544 # salt too small (3) 545 '{SMD5}IGVhwK+anvspmfDt2t0vgGjt/Q==', 546 547 # incorrect base64 encoding 548 '{SMD5}LnuZPJhiaY95/4lmVFpg548xBsD4P4c', 549 '{SMD5}LnuZPJhiaY95/4lmVFpg548xBsD4P4cw' 550 '{SMD5}LnuZPJhiaY95/4lmVFpg548xBsD4P4cw=', 551 '{SMD5}LnuZPJhiaY95/4lmV=pg548xBsD4P4cw', 552 '{SMD5}LnuZPJhiaY95/4lmVFpg548xBsD4P===', 553 ] 554 555class ldap_salted_sha1_test(HandlerCase): 556 handler = hash.ldap_salted_sha1 557 known_correct_hashes = [ 558 ("testing123", '{SSHA}0c0blFTXXNuAMHECS4uxrj3ZieMoWImr'), 559 ("secret", "{SSHA}0H+zTv8o4MR4H43n03eCsvw1luG8LdB7"), 560 (UPASS_TABLE, '{SSHA}3yCSD1nLZXznra4N8XzZgAL+s1sQYsx5'), 561 562 # alternate salt sizes (8, 15, 16) 563 ('test', '{SSHA}P90+qijSp8MJ1tN25j5o1PflUvlqjXHOGeOckw=='), 564 ('test', '{SSHA}/ZMF5KymNM+uEOjW+9STKlfCFj51bg3BmBNCiPHeW2ttbU0='), 565 ('test', '{SSHA}Pfx6Vf48AT9x3FVv8znbo8WQkEVSipHSWovxXmvNWUvp/d/7'), 566 ] 567 568 known_malformed_hashes = [ 569 # salt too small (3) 570 '{SSHA}ZQK3Yvtvl6wtIRoISgMGPkcWU7Nfq5U=', 571 572 # incorrect base64 encoding 573 '{SSHA}P90+qijSp8MJ1tN25j5o1PflUvlqjXHOGeOck', 574 '{SSHA}P90+qijSp8MJ1tN25j5o1PflUvlqjXHOGeOckw=', 575 '{SSHA}P90+qijSp8MJ1tN25j5o1Pf=UvlqjXHOGeOckw==', 576 '{SSHA}P90+qijSp8MJ1tN25j5o1PflUvlqjXHOGeOck===', 577 ] 578 579 580class ldap_salted_sha256_test(HandlerCase): 581 handler = hash.ldap_salted_sha256 582 known_correct_hashes = [ 583 # generated locally 584 # salt size = 8 585 ("password", '{SSHA256}x1tymSTVjozxQ2PtT46ysrzhZxbcskK0o2f8hEFx7fAQQmhtDSEkJA=='), 586 ("test", '{SSHA256}xfqc9aOR6z15YaEk3/Ufd7UL9+JozB/1EPmCDTizL0GkdA7BuNda6w=='), 587 ("toomanysecrets", '{SSHA256}RrTKrg6HFXcjJ+eDAq4UtbODxOr9RLeG+I69FoJvutcbY0zpfU+p1Q=='), 588 (u('letm\xe8\xefn'), '{SSHA256}km7UjUTBZN8a+gf1ND2/qn15N7LsO/jmGYJXvyTfJKAbI0RoLWWslQ=='), 589 590 # alternate salt sizes (4, 15, 16) 591 # generated locally 592 ('test', '{SSHA256}TFv2RpwyO0U9mA0Hk8FsXRa1I+4dNUtv27Qa8dzGVLinlDIm'), 593 ('test', '{SSHA256}J6MFQdkfjdmXz9UyUPb773kekJdm4dgSL4y8WQEQW11VipHSundOKaV0LsV4L6U='), 594 ('test', '{SSHA256}uBLazLaiBaPb6Cpnvq2XTYDkvXbYIuqRW1anMKk85d1/j1GqFQIgpHSOMUYIIcS4'), 595 ] 596 597 known_malformed_hashes = [ 598 # salt too small (3) 599 '{SSHA256}Lpdyr1+lR+rtxgp3SpQnUuNw33ENivTl28nzF2ZI4Gm41/o=', 600 601 # incorrect base64 encoding 602 '{SSHA256}TFv2RpwyO0U9mA0Hk8FsXRa1I+4dNUtv27Qa8dzGVLinlDI@', 603 '{SSHA256}TFv2RpwyO0U9mA0Hk8FsXRa1I+4dNUtv27Qa8dzGVLinlDI', 604 '{SSHA256}TFv2RpwyO0U9mA0Hk8FsXRa1I+4dNUtv27Qa8dzGVLinlDIm===', 605 ] 606 607 608 609class ldap_salted_sha512_test(HandlerCase): 610 handler = hash.ldap_salted_sha512 611 known_correct_hashes = [ 612 # generated by testing ldap server web interface (see issue 124 comments) 613 # salt size = 8 614 ("toomanysecrets", '{SSHA512}wExp4xjiCHS0zidJDC4UJq9EEeIebAQPJ1PWSwfhxWjfutI9XiiKuHm2AE41cEFfK+8HyI8bh+ztbczUGsvVFIgICWWPt7qu'), 615 (u('letm\xe8\xefn'), '{SSHA512}mpNUSmZc3TNx+RnPwkIAVMf7ocEKLPrIoQNsg4Eu8dHvyCeb2xzHp5A6n4tF7ntknSvfvRZaJII4ImvNJlYsgiwAm0FMqR+3'), 616 617 # generated locally 618 # salt size = 8 619 ("password", '{SSHA512}f/lFQskkl7PdMsTGJxHZq8LDt/l+UqRMm6/pj4pV7/xZkcOaKCgvQqp+KCeXc/Vd4RY6vEHWn4y0DnFcQ6wgyv9fyxk='), 620 ("test", '{SSHA512}Tgx/uhHnlM9/GgQvI31dN7cheDXg7WypZwaaIkyRsgV/BKIzBG3G/wUd9o1dpi06p3SYzMedg0lvTc3b6CtdO0Xo/f9/L+Uc'), 621 622 # alternate salt sizes (4, 15, 16) 623 # generated locally 624 ('test', '{SSHA512}Yg9DQ2wURCFGwobu7R2O6cq7nVbnGMPrFCX0aPQ9kj/y1hd6k9PEzkgWCB5aXdPwPzNrVb0PkiHiBnG1CxFiT+B8L8U='), 625 ('test', '{SSHA512}5ecDGWs5RY4xLszUO6hAcl90W3wAozGQoI4Gqj8xSZdcfU1lVEM4aY8s+4xVeLitcn7BO8i7xkzMFWLoxas7SeHc23sP4dx77937PyeE0A=='), 626 ('test', '{SSHA512}6FQv5W47HGg2MFBFZofoiIbO8KRW75Pm51NKoInpthYQQ5ujazHGhVGzrj3JXgA7j0k+UNmkHdbJjdY5xcUHPzynFEII4fwfIySEcG5NKSU='), 627 ] 628 629 known_malformed_hashes = [ 630 # salt too small (3) 631 '{SSHA512}zFnn4/8x8GveUaMqgrYWyIWqFQ0Irt6gADPtRk4Uv3nUC6uR5cD8+YdQni/0ZNij9etm6p17kSFuww3M6l+d6AbAeA==', 632 633 # incorrect base64 encoding 634 '{SSHA512}Tgx/uhHnlM9/GgQvI31dN7cheDXg7WypZwaaIkyRsgV/BKIzBG3G/wUd9o1dpi06p3SYzMedg0lvTc3b6CtdO0Xo/f9/L+U', 635 '{SSHA512}Tgx/uhHnlM9/GgQvI31dN7cheDXg7WypZwaaIkyRsgV/BKIzBG3G/wUd9o1dpi06p3SYzMedg0lvTc3b6CtdO0Xo/f9/L+U@', 636 '{SSHA512}Tgx/uhHnlM9/GgQvI31dN7cheDXg7WypZwaaIkyRsgV/BKIzBG3G/wUd9o1dpi06p3SYzMedg0lvTc3b6CtdO0Xo/f9/L+U===', 637 ] 638 639 640class ldap_plaintext_test(HandlerCase): 641 # TODO: integrate EncodingHandlerMixin 642 handler = hash.ldap_plaintext 643 known_correct_hashes = [ 644 ("password", 'password'), 645 (UPASS_TABLE, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), 646 (PASS_TABLE_UTF8, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), 647 ] 648 known_unidentified_hashes = [ 649 "{FOO}bar", 650 651 # NOTE: this hash currently rejects the empty string. 652 "", 653 ] 654 655 known_other_hashes = [ 656 ("ldap_md5", "{MD5}/F4DjTilcDIIVEHn/nAQsA==") 657 ] 658 659 class FuzzHashGenerator(HandlerCase.FuzzHashGenerator): 660 661 def random_password(self): 662 # NOTE: this hash currently rejects the empty string. 663 while True: 664 pwd = super(ldap_plaintext_test.FuzzHashGenerator, self).random_password() 665 if pwd: 666 return pwd 667 668class _ldap_md5_crypt_test(HandlerCase): 669 # NOTE: since the ldap_{crypt} handlers are all wrappers, don't need 670 # separate test; this is just to test the codebase end-to-end 671 handler = hash.ldap_md5_crypt 672 673 known_correct_hashes = [ 674 # 675 # custom 676 # 677 ('', '{CRYPT}$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o.'), 678 (' ', '{CRYPT}$1$m/5ee7ol$bZn0kIBFipq39e.KDXX8I0'), 679 ('test', '{CRYPT}$1$ec6XvcoW$ghEtNK2U1MC5l.Dwgi3020'), 680 ('Compl3X AlphaNu3meric', '{CRYPT}$1$nX1e7EeI$ljQn72ZUgt6Wxd9hfvHdV0'), 681 ('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', '{CRYPT}$1$jQS7o98J$V6iTcr71CGgwW2laf17pi1'), 682 ('test', '{CRYPT}$1$SuMrG47N$ymvzYjr7QcEQjaK5m1PGx1'), 683 684 # ensures utf-8 used for unicode 685 (UPASS_TABLE, '{CRYPT}$1$d6/Ky1lU$/xpf8m7ftmWLF.TjHCqel0'), 686 ] 687 688 known_malformed_hashes = [ 689 # bad char in otherwise correct hash 690 '{CRYPT}$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o!', 691 ] 692 693# create test cases for specific backends 694ldap_md5_crypt_os_crypt_test =_ldap_md5_crypt_test.create_backend_case("os_crypt") 695ldap_md5_crypt_builtin_test =_ldap_md5_crypt_test.create_backend_case("builtin") 696 697class _ldap_sha1_crypt_test(HandlerCase): 698 # NOTE: this isn't for testing the hash (see ldap_md5_crypt note) 699 # but as a self-test of the os_crypt patching code in HandlerCase. 700 handler = hash.ldap_sha1_crypt 701 702 known_correct_hashes = [ 703 ('password', '{CRYPT}$sha1$10$c.mcTzCw$gF8UeYst9yXX7WNZKc5Fjkq0.au7'), 704 (UPASS_TABLE, '{CRYPT}$sha1$10$rnqXlOsF$aGJf.cdRPewJAXo1Rn1BkbaYh0fP'), 705 ] 706 707 def populate_settings(self, kwds): 708 kwds.setdefault("rounds", 10) 709 super(_ldap_sha1_crypt_test, self).populate_settings(kwds) 710 711 def test_77_fuzz_input(self, **ignored): 712 raise self.skipTest("unneeded") 713 714# create test cases for specific backends 715ldap_sha1_crypt_os_crypt_test = _ldap_sha1_crypt_test.create_backend_case("os_crypt") 716 717#============================================================================= 718# lanman 719#============================================================================= 720class lmhash_test(EncodingHandlerMixin, HandlerCase): 721 handler = hash.lmhash 722 secret_case_insensitive = True 723 724 known_correct_hashes = [ 725 # 726 # http://msdn.microsoft.com/en-us/library/cc245828(v=prot.10).aspx 727 # 728 ("OLDPASSWORD", "c9b81d939d6fd80cd408e6b105741864"), 729 ("NEWPASSWORD", '09eeab5aa415d6e4d408e6b105741864'), 730 ("welcome", "c23413a8a1e7665faad3b435b51404ee"), 731 732 # 733 # custom 734 # 735 ('', 'aad3b435b51404eeaad3b435b51404ee'), 736 ('zzZZZzz', 'a5e6066de61c3e35aad3b435b51404ee'), 737 ('passphrase', '855c3697d9979e78ac404c4ba2c66533'), 738 ('Yokohama', '5ecd9236d21095ce7584248b8d2c9f9e'), 739 740 # ensures cp437 used for unicode 741 (u('ENCYCLOP\xC6DIA'), 'fed6416bffc9750d48462b9d7aaac065'), 742 (u('encyclop\xE6dia'), 'fed6416bffc9750d48462b9d7aaac065'), 743 744 # test various encoding values 745 ((u("\xC6"), None), '25d8ab4a0659c97aaad3b435b51404ee'), 746 ((u("\xC6"), "cp437"), '25d8ab4a0659c97aaad3b435b51404ee'), 747 ((u("\xC6"), "latin-1"), '184eecbbe9991b44aad3b435b51404ee'), 748 ((u("\xC6"), "utf-8"), '00dd240fcfab20b8aad3b435b51404ee'), 749 ] 750 751 known_unidentified_hashes = [ 752 # bad char in otherwise correct hash 753 '855c3697d9979e78ac404c4ba2c6653X', 754 ] 755 756 def test_90_raw(self): 757 """test lmhash.raw() method""" 758 from binascii import unhexlify 759 from passlib.utils.compat import str_to_bascii 760 lmhash = self.handler 761 for secret, hash in self.known_correct_hashes: 762 kwds = {} 763 secret = self.populate_context(secret, kwds) 764 data = unhexlify(str_to_bascii(hash)) 765 self.assertEqual(lmhash.raw(secret, **kwds), data) 766 self.assertRaises(TypeError, lmhash.raw, 1) 767 768#============================================================================= 769# md5 crypt 770#============================================================================= 771class _md5_crypt_test(HandlerCase): 772 handler = hash.md5_crypt 773 774 known_correct_hashes = [ 775 # 776 # from JTR 1.7.9 777 # 778 ('U*U*U*U*', '$1$dXc3I7Rw$ctlgjDdWJLMT.qwHsWhXR1'), 779 ('U*U***U', '$1$dXc3I7Rw$94JPyQc/eAgQ3MFMCoMF.0'), 780 ('U*U***U*', '$1$dXc3I7Rw$is1mVIAEtAhIzSdfn5JOO0'), 781 ('*U*U*U*U', '$1$eQT9Hwbt$XtuElNJD.eW5MN5UCWyTQ0'), 782 ('', '$1$Eu.GHtia$CFkL/nE1BYTlEPiVx1VWX0'), 783 784 # 785 # custom 786 # 787 788 # NOTE: would need to patch HandlerCase to coerce hashes 789 # to native str for this first one to work under py3. 790## ('', b('$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o.')), 791 ('', '$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o.'), 792 (' ', '$1$m/5ee7ol$bZn0kIBFipq39e.KDXX8I0'), 793 ('test', '$1$ec6XvcoW$ghEtNK2U1MC5l.Dwgi3020'), 794 ('Compl3X AlphaNu3meric', '$1$nX1e7EeI$ljQn72ZUgt6Wxd9hfvHdV0'), 795 ('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', '$1$jQS7o98J$V6iTcr71CGgwW2laf17pi1'), 796 ('test', '$1$SuMrG47N$ymvzYjr7QcEQjaK5m1PGx1'), 797 (b'test', '$1$SuMrG47N$ymvzYjr7QcEQjaK5m1PGx1'), 798 (u('s'), '$1$ssssssss$YgmLTApYTv12qgTwBoj8i/'), 799 800 # ensures utf-8 used for unicode 801 (UPASS_TABLE, '$1$d6/Ky1lU$/xpf8m7ftmWLF.TjHCqel0'), 802 ] 803 804 known_malformed_hashes = [ 805 # bad char in otherwise correct hash \/ 806 '$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o!', 807 808 # too many fields 809 '$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o.$', 810 ] 811 812 platform_crypt_support = [ 813 # openbsd 5.8 dropped everything except bcrypt 814 ("openbsd[6789]", False), 815 ("openbsd5", None), 816 ("openbsd", True), 817 818 ("freebsd|netbsd|linux|solaris", True), 819 ("darwin", False), 820 ] 821 822# create test cases for specific backends 823md5_crypt_os_crypt_test = _md5_crypt_test.create_backend_case("os_crypt") 824md5_crypt_builtin_test = _md5_crypt_test.create_backend_case("builtin") 825 826#============================================================================= 827# msdcc 1 & 2 828#============================================================================= 829class msdcc_test(UserHandlerMixin, HandlerCase): 830 handler = hash.msdcc 831 user_case_insensitive = True 832 833 known_correct_hashes = [ 834 835 # 836 # http://www.jedge.com/wordpress/windows-password-cache/ 837 # 838 (("Asdf999", "sevans"), "b1176c2587478785ec1037e5abc916d0"), 839 840 # 841 # http://infosecisland.com/blogview/12156-Cachedump-for-Meterpreter-in-Action.html 842 # 843 (("ASDqwe123", "jdoe"), "592cdfbc3f1ef77ae95c75f851e37166"), 844 845 # 846 # http://comments.gmane.org/gmane.comp.security.openwall.john.user/1917 847 # 848 (("test1", "test1"), "64cd29e36a8431a2b111378564a10631"), 849 (("test2", "test2"), "ab60bdb4493822b175486810ac2abe63"), 850 (("test3", "test3"), "14dd041848e12fc48c0aa7a416a4a00c"), 851 (("test4", "test4"), "b945d24866af4b01a6d89b9d932a153c"), 852 853 # 854 # http://ciscoit.wordpress.com/2011/04/13/metasploit-hashdump-vs-cachedump/ 855 # 856 (("1234qwer!@#$", "Administrator"), "7b69d06ef494621e3f47b9802fe7776d"), 857 858 # 859 # http://www.securiteam.com/tools/5JP0I2KFPA.html 860 # 861 (("password", "user"), "2d9f0b052932ad18b87f315641921cda"), 862 863 # 864 # from JTR 1.7.9 865 # 866 (("", "root"), "176a4c2bd45ac73687676c2f09045353"), 867 (("test1", "TEST1"), "64cd29e36a8431a2b111378564a10631"), 868 (("okolada", "nineteen_characters"), "290efa10307e36a79b3eebf2a6b29455"), 869 ((u("\u00FC"), u("\u00FC")), "48f84e6f73d6d5305f6558a33fa2c9bb"), 870 ((u("\u00FC\u00FC"), u("\u00FC\u00FC")), "593246a8335cf0261799bda2a2a9c623"), 871 ((u("\u20AC\u20AC"), "user"), "9121790702dda0fa5d353014c334c2ce"), 872 873 # 874 # custom 875 # 876 877 # ensures utf-8 used for unicode 878 ((UPASS_TABLE, 'bob'), 'fcb82eb4212865c7ac3503156ca3f349'), 879 ] 880 881 known_alternate_hashes = [ 882 # check uppercase accepted. 883 ("B1176C2587478785EC1037E5ABC916D0", ("Asdf999", "sevans"), 884 "b1176c2587478785ec1037e5abc916d0"), 885 ] 886 887class msdcc2_test(UserHandlerMixin, HandlerCase): 888 handler = hash.msdcc2 889 user_case_insensitive = True 890 891 known_correct_hashes = [ 892 # 893 # from JTR 1.7.9 894 # 895 (("test1", "test1"), "607bbe89611e37446e736f7856515bf8"), 896 (("qerwt", "Joe"), "e09b38f84ab0be586b730baf61781e30"), 897 (("12345", "Joe"), "6432f517a900b3fc34ffe57f0f346e16"), 898 (("", "bin"), "c0cbe0313a861062e29f92ede58f9b36"), 899 (("w00t", "nineteen_characters"), "87136ae0a18b2dafe4a41d555425b2ed"), 900 (("w00t", "eighteencharacters"), "fc5df74eca97afd7cd5abb0032496223"), 901 (("longpassword", "twentyXXX_characters"), "cfc6a1e33eb36c3d4f84e4c2606623d2"), 902 (("longpassword", "twentyoneX_characters"), "99ff74cea552799da8769d30b2684bee"), 903 (("longpassword", "twentytwoXX_characters"), "0a721bdc92f27d7fb23b87a445ec562f"), 904 (("test2", "TEST2"), "c6758e5be7fc943d00b97972a8a97620"), 905 (("test3", "test3"), "360e51304a2d383ea33467ab0b639cc4"), 906 (("test4", "test4"), "6f79ee93518306f071c47185998566ae"), 907 ((u("\u00FC"), "joe"), "bdb80f2c4656a8b8591bd27d39064a54"), 908 ((u("\u20AC\u20AC"), "joe"), "1e1e20f482ff748038e47d801d0d1bda"), 909 ((u("\u00FC\u00FC"), "admin"), "0839e4a07c00f18a8c65cf5b985b9e73"), 910 911 # 912 # custom 913 # 914 915 # custom unicode test 916 ((UPASS_TABLE, 'bob'), 'cad511dc9edefcf69201da72efb6bb55'), 917 ] 918 919#============================================================================= 920# mssql 2000 & 2005 921#============================================================================= 922class mssql2000_test(HandlerCase): 923 handler = hash.mssql2000 924 secret_case_insensitive = "verify-only" 925 # FIXME: fix UT framework - this hash is sensitive to password case, but verify() is not 926 927 known_correct_hashes = [ 928 # 929 # http://hkashfi.blogspot.com/2007/08/breaking-sql-server-2005-hashes.html 930 # 931 ('Test', '0x010034767D5C0CFA5FDCA28C4A56085E65E882E71CB0ED2503412FD54D6119FFF04129A1D72E7C3194F7284A7F3A'), 932 ('TEST', '0x010034767D5C2FD54D6119FFF04129A1D72E7C3194F7284A7F3A2FD54D6119FFF04129A1D72E7C3194F7284A7F3A'), 933 934 # 935 # http://www.sqlmag.com/forums/aft/68438 936 # 937 ('x', '0x010086489146C46DD7318D2514D1AC706457CBF6CD3DF8407F071DB4BBC213939D484BF7A766E974F03C96524794'), 938 939 # 940 # http://stackoverflow.com/questions/173329/how-to-decrypt-a-password-from-sql-server 941 # 942 ('AAAA', '0x0100CF465B7B12625EF019E157120D58DD46569AC7BF4118455D12625EF019E157120D58DD46569AC7BF4118455D'), 943 944 # 945 # http://msmvps.com/blogs/gladchenko/archive/2005/04/06/41083.aspx 946 # 947 ('123', '0x01002D60BA07FE612C8DE537DF3BFCFA49CD9968324481C1A8A8FE612C8DE537DF3BFCFA49CD9968324481C1A8A8'), 948 949 # 950 # http://www.simple-talk.com/sql/t-sql-programming/temporarily-changing-an-unknown-password-of-the-sa-account-/ 951 # 952 ('12345', '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3'), 953 954 # 955 # XXX: sample is incomplete, password unknown 956 # https://anthonystechblog.wordpress.com/2011/04/20/password-encryption-in-sql-server-how-to-tell-if-a-user-is-using-a-weak-password/ 957 # (????, '0x0100813F782D66EF15E40B1A3FDF7AB88B322F51401A87D8D3E3A8483C4351A3D96FC38499E6CDD2B6F?????????'), 958 # 959 960 # 961 # from JTR 1.7.9 962 # 963 ('foo', '0x0100A607BA7C54A24D17B565C59F1743776A10250F581D482DA8B6D6261460D3F53B279CC6913CE747006A2E3254'), 964 ('bar', '0x01000508513EADDF6DB7DDD270CCA288BF097F2FF69CC2DB74FBB9644D6901764F999BAB9ECB80DE578D92E3F80D'), 965 ('canard', '0x01008408C523CF06DCB237835D701C165E68F9460580132E28ED8BC558D22CEDF8801F4503468A80F9C52A12C0A3'), 966 ('lapin', '0x0100BF088517935FC9183FE39FDEC77539FD5CB52BA5F5761881E5B9638641A79DBF0F1501647EC941F3355440A2'), 967 968 # 969 # custom 970 # 971 972 # ensures utf-8 used for unicode 973 (UPASS_USD, '0x0100624C0961B28E39FEE13FD0C35F57B4523F0DA1861C11D5A5B28E39FEE13FD0C35F57B4523F0DA1861C11D5A5'), 974 (UPASS_TABLE, '0x010083104228FAD559BE52477F2131E538BE9734E5C4B0ADEFD7F6D784B03C98585DC634FE2B8CA3A6DFFEC729B4'), 975 976 ] 977 978 known_alternate_hashes = [ 979 # lower case hex 980 ('0x01005b20054332752e1bc2e7c5df0f9ebfe486e9bee063e8d3b332752e1bc2e7c5df0f9ebfe486e9bee063e8d3b3', 981 '12345', '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3'), 982 ] 983 984 known_unidentified_hashes = [ 985 # malformed start 986 '0X01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3', 987 988 # wrong magic value 989 '0x02005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3', 990 991 # wrong size 992 '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3', 993 '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3AF', 994 995 # mssql2005 996 '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3', 997 ] 998 999 known_malformed_hashes = [ 1000 # non-hex char -----\/ 1001 b'0x01005B200543327G2E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3', 1002 u('0x01005B200543327G2E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3'), 1003 ] 1004 1005class mssql2005_test(HandlerCase): 1006 handler = hash.mssql2005 1007 1008 known_correct_hashes = [ 1009 # 1010 # http://hkashfi.blogspot.com/2007/08/breaking-sql-server-2005-hashes.html 1011 # 1012 ('TEST', '0x010034767D5C2FD54D6119FFF04129A1D72E7C3194F7284A7F3A'), 1013 1014 # 1015 # http://www.openwall.com/lists/john-users/2009/07/14/2 1016 # 1017 ('toto', '0x01004086CEB6BF932BC4151A1AF1F13CD17301D70816A8886908'), 1018 1019 # 1020 # http://msmvps.com/blogs/gladchenko/archive/2005/04/06/41083.aspx 1021 # 1022 ('123', '0x01004A335DCEDB366D99F564D460B1965B146D6184E4E1025195'), 1023 ('123', '0x0100E11D573F359629B344990DCD3D53DE82CF8AD6BBA7B638B6'), 1024 1025 # 1026 # XXX: password unknown 1027 # http://www.simple-talk.com/sql/t-sql-programming/temporarily-changing-an-unknown-password-of-the-sa-account-/ 1028 # (???, '0x01004086CEB6301EEC0A994E49E30DA235880057410264030797'), 1029 # 1030 1031 # 1032 # http://therelentlessfrontend.com/2010/03/26/encrypting-and-decrypting-passwords-in-sql-server/ 1033 # 1034 ('AAAA', '0x010036D726AE86834E97F20B198ACD219D60B446AC5E48C54F30'), 1035 1036 # 1037 # from JTR 1.7.9 1038 # 1039 ("toto", "0x01004086CEB6BF932BC4151A1AF1F13CD17301D70816A8886908"), 1040 ("titi", "0x01004086CEB60ED526885801C23B366965586A43D3DEAC6DD3FD"), 1041 ("foo", "0x0100A607BA7C54A24D17B565C59F1743776A10250F581D482DA8"), 1042 ("bar", "0x01000508513EADDF6DB7DDD270CCA288BF097F2FF69CC2DB74FB"), 1043 ("canard", "0x01008408C523CF06DCB237835D701C165E68F9460580132E28ED"), 1044 ("lapin", "0x0100BF088517935FC9183FE39FDEC77539FD5CB52BA5F5761881"), 1045 1046 # 1047 # adapted from mssql2000.known_correct_hashes (above) 1048 # 1049 ('Test', '0x010034767D5C0CFA5FDCA28C4A56085E65E882E71CB0ED250341'), 1050 ('Test', '0x0100993BF2315F36CC441485B35C4D84687DC02C78B0E680411F'), 1051 ('x', '0x010086489146C46DD7318D2514D1AC706457CBF6CD3DF8407F07'), 1052 ('AAAA', '0x0100CF465B7B12625EF019E157120D58DD46569AC7BF4118455D'), 1053 ('123', '0x01002D60BA07FE612C8DE537DF3BFCFA49CD9968324481C1A8A8'), 1054 ('12345', '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3'), 1055 1056 # 1057 # custom 1058 # 1059 1060 # ensures utf-8 used for unicode 1061 (UPASS_USD, '0x0100624C0961B28E39FEE13FD0C35F57B4523F0DA1861C11D5A5'), 1062 (UPASS_TABLE, '0x010083104228FAD559BE52477F2131E538BE9734E5C4B0ADEFD7'), 1063 ] 1064 1065 known_alternate_hashes = [ 1066 # lower case hex 1067 ('0x01005b20054332752e1bc2e7c5df0f9ebfe486e9bee063e8d3b3', 1068 '12345', '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3'), 1069 ] 1070 1071 known_unidentified_hashes = [ 1072 # malformed start 1073 '0X010036D726AE86834E97F20B198ACD219D60B446AC5E48C54F30', 1074 1075 # wrong magic value 1076 '0x020036D726AE86834E97F20B198ACD219D60B446AC5E48C54F30', 1077 1078 # wrong size 1079 '0x010036D726AE86834E97F20B198ACD219D60B446AC5E48C54F', 1080 '0x010036D726AE86834E97F20B198ACD219D60B446AC5E48C54F3012', 1081 1082 # mssql2000 1083 '0x01005B20054332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3', 1084 ] 1085 1086 known_malformed_hashes = [ 1087 # non-hex char --\/ 1088 '0x010036D726AE86G34E97F20B198ACD219D60B446AC5E48C54F30', 1089 ] 1090 1091#============================================================================= 1092# mysql 323 & 41 1093#============================================================================= 1094class mysql323_test(HandlerCase): 1095 handler = hash.mysql323 1096 1097 known_correct_hashes = [ 1098 # 1099 # from JTR 1.7.9 1100 # 1101 ('drew', '697a7de87c5390b2'), 1102 ('password', "5d2e19393cc5ef67"), 1103 1104 # 1105 # custom 1106 # 1107 ('mypass', '6f8c114b58f2ce9e'), 1108 1109 # ensures utf-8 used for unicode 1110 (UPASS_TABLE, '4ef327ca5491c8d7'), 1111 ] 1112 1113 known_unidentified_hashes = [ 1114 # bad char in otherwise correct hash 1115 '6z8c114b58f2ce9e', 1116 ] 1117 1118 def test_90_whitespace(self): 1119 """check whitespace is ignored per spec""" 1120 h = self.do_encrypt("mypass") 1121 h2 = self.do_encrypt("my pass") 1122 self.assertEqual(h, h2) 1123 1124 class FuzzHashGenerator(HandlerCase.FuzzHashGenerator): 1125 1126 def accept_password_pair(self, secret, other): 1127 # override to handle whitespace 1128 return secret.replace(" ","") != other.replace(" ","") 1129 1130class mysql41_test(HandlerCase): 1131 handler = hash.mysql41 1132 known_correct_hashes = [ 1133 # 1134 # from JTR 1.7.9 1135 # 1136 ('verysecretpassword', '*2C905879F74F28F8570989947D06A8429FB943E6'), 1137 ('12345678123456781234567812345678', '*F9F1470004E888963FB466A5452C9CBD9DF6239C'), 1138 ("' OR 1 /*'", '*97CF7A3ACBE0CA58D5391AC8377B5D9AC11D46D9'), 1139 1140 # 1141 # custom 1142 # 1143 ('mypass', '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'), 1144 1145 # ensures utf-8 used for unicode 1146 (UPASS_TABLE, '*E7AFE21A9CFA2FC9D15D942AE8FB5C240FE5837B'), 1147 ] 1148 known_unidentified_hashes = [ 1149 # bad char in otherwise correct hash 1150 '*6Z8989366EAF75BB670AD8EA7A7FC1176A95CEF4', 1151 ] 1152 1153#============================================================================= 1154# NTHASH 1155#============================================================================= 1156class nthash_test(HandlerCase): 1157 handler = hash.nthash 1158 1159 known_correct_hashes = [ 1160 # 1161 # http://msdn.microsoft.com/en-us/library/cc245828(v=prot.10).aspx 1162 # 1163 ("OLDPASSWORD", u("6677b2c394311355b54f25eec5bfacf5")), 1164 ("NEWPASSWORD", u("256781a62031289d3c2c98c14f1efc8c")), 1165 1166 # 1167 # from JTR 1.7.9 1168 # 1169 1170 # ascii 1171 ('', '31d6cfe0d16ae931b73c59d7e0c089c0'), 1172 ('tigger', 'b7e0ea9fbffcf6dd83086e905089effd'), 1173 1174 # utf-8 1175 (b'\xC3\xBC', '8bd6e4fb88e01009818749c5443ea712'), 1176 (b'\xC3\xBC\xC3\xBC', 'cc1260adb6985ca749f150c7e0b22063'), 1177 (b'\xE2\x82\xAC', '030926b781938db4365d46adc7cfbcb8'), 1178 (b'\xE2\x82\xAC\xE2\x82\xAC','682467b963bb4e61943e170a04f7db46'), 1179 1180 # 1181 # custom 1182 # 1183 ('passphrase', '7f8fe03093cc84b267b109625f6bbf4b'), 1184 ] 1185 1186 known_unidentified_hashes = [ 1187 # bad char in otherwise correct hash 1188 '7f8fe03093cc84b267b109625f6bbfxb', 1189 ] 1190 1191class bsd_nthash_test(HandlerCase): 1192 handler = hash.bsd_nthash 1193 1194 known_correct_hashes = [ 1195 ('passphrase', '$3$$7f8fe03093cc84b267b109625f6bbf4b'), 1196 (b'\xC3\xBC', '$3$$8bd6e4fb88e01009818749c5443ea712'), 1197 ] 1198 1199 known_unidentified_hashes = [ 1200 # bad char in otherwise correct hash --\/ 1201 '$3$$7f8fe03093cc84b267b109625f6bbfxb', 1202 ] 1203 1204#============================================================================= 1205# oracle 10 & 11 1206#============================================================================= 1207class oracle10_test(UserHandlerMixin, HandlerCase): 1208 handler = hash.oracle10 1209 secret_case_insensitive = True 1210 user_case_insensitive = True 1211 1212 # TODO: get more test vectors (especially ones which properly test unicode) 1213 known_correct_hashes = [ 1214 # ((secret,user),hash) 1215 1216 # 1217 # http://www.petefinnigan.com/default/default_password_list.htm 1218 # 1219 (('tiger', 'scott'), 'F894844C34402B67'), 1220 ((u('ttTiGGeR'), u('ScO')), '7AA1A84E31ED7771'), 1221 (("d_syspw", "SYSTEM"), '1B9F1F9A5CB9EB31'), 1222 (("strat_passwd", "strat_user"), 'AEBEDBB4EFB5225B'), 1223 1224 # 1225 # http://openwall.info/wiki/john/sample-hashes 1226 # 1227 (('#95LWEIGHTS', 'USER'), '000EA4D72A142E29'), 1228 (('CIAO2010', 'ALFREDO'), 'EB026A76F0650F7B'), 1229 1230 # 1231 # from JTR 1.7.9 1232 # 1233 (('GLOUGlou', 'Bob'), 'CDC6B483874B875B'), 1234 (('GLOUGLOUTER', 'bOB'), 'EF1F9139DB2D5279'), 1235 (('LONG_MOT_DE_PASSE_OUI', 'BOB'), 'EC8147ABB3373D53'), 1236 1237 # 1238 # custom 1239 # 1240 ((UPASS_TABLE, 'System'), 'B915A853F297B281'), 1241 ] 1242 1243 known_unidentified_hashes = [ 1244 # bad char in hash --\ 1245 'F894844C34402B6Z', 1246 ] 1247 1248class oracle11_test(HandlerCase): 1249 handler = hash.oracle11 1250 # TODO: find more test vectors (especially ones which properly test unicode) 1251 known_correct_hashes = [ 1252 # 1253 # from JTR 1.7.9 1254 # 1255 ("abc123", "S:5FDAB69F543563582BA57894FE1C1361FB8ED57B903603F2C52ED1B4D642"), 1256 ("SyStEm123!@#", "S:450F957ECBE075D2FA009BA822A9E28709FBC3DA82B44D284DDABEC14C42"), 1257 ("oracle", "S:3437FF72BD69E3FB4D10C750B92B8FB90B155E26227B9AB62D94F54E5951"), 1258 ("11g", "S:61CE616647A4F7980AFD7C7245261AF25E0AFE9C9763FCF0D54DA667D4E6"), 1259 ("11g", "S:B9E7556F53500C8C78A58F50F24439D79962DE68117654B6700CE7CC71CF"), 1260 1261 # 1262 # source? 1263 # 1264 ("SHAlala", "S:2BFCFDF5895014EE9BB2B9BA067B01E0389BB5711B7B5F82B7235E9E182C"), 1265 1266 # 1267 # custom 1268 # 1269 (UPASS_TABLE, 'S:51586343E429A6DF024B8F242F2E9F8507B1096FACD422E29142AA4974B0'), 1270 ] 1271 1272#============================================================================= 1273# PHPass Portable Crypt 1274#============================================================================= 1275class phpass_test(HandlerCase): 1276 handler = hash.phpass 1277 1278 known_correct_hashes = [ 1279 # 1280 # from official 0.3 implementation 1281 # http://www.openwall.com/phpass/ 1282 # 1283 ('test12345', '$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0'), # from the source 1284 1285 # 1286 # from JTR 1.7.9 1287 # 1288 ('test1', '$H$9aaaaaSXBjgypwqm.JsMssPLiS8YQ00'), 1289 ('123456', '$H$9PE8jEklgZhgLmZl5.HYJAzfGCQtzi1'), 1290 ('123456', '$H$9pdx7dbOW3Nnt32sikrjAxYFjX8XoK1'), 1291 ('thisisalongertestPW', '$P$912345678LIjjb6PhecupozNBmDndU0'), 1292 ('JohnRipper', '$P$612345678si5M0DDyPpmRCmcltU/YW/'), 1293 ('JohnRipper', '$H$712345678WhEyvy1YWzT4647jzeOmo0'), 1294 ('JohnRipper', '$P$B12345678L6Lpt4BxNotVIMILOa9u81'), 1295 1296 # 1297 # custom 1298 # 1299 ('', '$P$7JaFQsPzJSuenezefD/3jHgt5hVfNH0'), 1300 ('compL3X!', '$P$FiS0N5L672xzQx1rt1vgdJQRYKnQM9/'), 1301 1302 # ensures utf-8 used for unicode 1303 (UPASS_TABLE, '$P$7SMy8VxnfsIy2Sxm7fJxDSdil.h7TW.'), 1304 ] 1305 1306 known_malformed_hashes = [ 1307 # bad char in otherwise correct hash 1308 # ---\/ 1309 '$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r!L0', 1310 ] 1311 1312#============================================================================= 1313# plaintext 1314#============================================================================= 1315class plaintext_test(HandlerCase): 1316 # TODO: integrate EncodingHandlerMixin 1317 handler = hash.plaintext 1318 accepts_all_hashes = True 1319 1320 known_correct_hashes = [ 1321 ('',''), 1322 ('password', 'password'), 1323 1324 # ensure unicode uses utf-8 1325 (UPASS_TABLE, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), 1326 (PASS_TABLE_UTF8, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), 1327 ] 1328 1329#============================================================================= 1330# postgres_md5 1331#============================================================================= 1332class postgres_md5_test(UserHandlerMixin, HandlerCase): 1333 handler = hash.postgres_md5 1334 known_correct_hashes = [ 1335 # ((secret,user),hash) 1336 1337 # 1338 # generated using postgres 8.1 1339 # 1340 (('mypass', 'postgres'), 'md55fba2ea04fd36069d2574ea71c8efe9d'), 1341 (('mypass', 'root'), 'md540c31989b20437833f697e485811254b'), 1342 (("testpassword",'testuser'), 'md5d4fc5129cc2c25465a5370113ae9835f'), 1343 1344 # 1345 # custom 1346 # 1347 1348 # verify unicode->utf8 1349 ((UPASS_TABLE, 'postgres'), 'md5cb9f11283265811ce076db86d18a22d2'), 1350 ] 1351 known_unidentified_hashes = [ 1352 # bad 'z' char in otherwise correct hash 1353 'md54zc31989b20437833f697e485811254b', 1354 ] 1355 1356#============================================================================= 1357# (netbsd's) sha1 crypt 1358#============================================================================= 1359class _sha1_crypt_test(HandlerCase): 1360 handler = hash.sha1_crypt 1361 1362 known_correct_hashes = [ 1363 # 1364 # custom 1365 # 1366 ("password", "$sha1$19703$iVdJqfSE$v4qYKl1zqYThwpjJAoKX6UvlHq/a"), 1367 ("password", "$sha1$21773$uV7PTeux$I9oHnvwPZHMO0Nq6/WgyGV/tDJIH"), 1368 (UPASS_TABLE, '$sha1$40000$uJ3Sp7LE$.VEmLO5xntyRFYihC7ggd3297T/D'), 1369 ] 1370 1371 known_malformed_hashes = [ 1372 # bad char in otherwise correct hash 1373 '$sha1$21773$u!7PTeux$I9oHnvwPZHMO0Nq6/WgyGV/tDJIH', 1374 1375 # zero padded rounds 1376 '$sha1$01773$uV7PTeux$I9oHnvwPZHMO0Nq6/WgyGV/tDJIH', 1377 1378 # too many fields 1379 '$sha1$21773$uV7PTeux$I9oHnvwPZHMO0Nq6/WgyGV/tDJIH$', 1380 1381 # empty rounds field 1382 '$sha1$$uV7PTeux$I9oHnvwPZHMO0Nq6/WgyGV/tDJIH$', 1383 ] 1384 1385 platform_crypt_support = [ 1386 ("netbsd", True), 1387 ("freebsd|openbsd|solaris|darwin", False), 1388 ("linux", None), # may be present if libxcrypt is in use 1389 ] 1390 1391# create test cases for specific backends 1392sha1_crypt_os_crypt_test = _sha1_crypt_test.create_backend_case("os_crypt") 1393sha1_crypt_builtin_test = _sha1_crypt_test.create_backend_case("builtin") 1394 1395#============================================================================= 1396# roundup 1397#============================================================================= 1398 1399# NOTE: all roundup hashes use PrefixWrapper, 1400# so there's nothing natively to test. 1401# so we just have a few quick cases... 1402 1403class RoundupTest(TestCase): 1404 1405 def _test_pair(self, h, secret, hash): 1406 self.assertTrue(h.verify(secret, hash)) 1407 self.assertFalse(h.verify('x'+secret, hash)) 1408 1409 def test_pairs(self): 1410 self._test_pair( 1411 hash.ldap_hex_sha1, 1412 "sekrit", 1413 '{SHA}8d42e738c7adee551324955458b5e2c0b49ee655') 1414 1415 self._test_pair( 1416 hash.ldap_hex_md5, 1417 "sekrit", 1418 '{MD5}ccbc53f4464604e714f69dd11138d8b5') 1419 1420 self._test_pair( 1421 hash.ldap_des_crypt, 1422 "sekrit", 1423 '{CRYPT}nFia0rj2TT59A') 1424 1425 self._test_pair( 1426 hash.roundup_plaintext, 1427 "sekrit", 1428 '{plaintext}sekrit') 1429 1430 self._test_pair( 1431 hash.ldap_pbkdf2_sha1, 1432 "sekrit", 1433 '{PBKDF2}5000$7BvbBq.EZzz/O0HuwX3iP.nAG3s$g3oPnFFaga2BJaX5PoPRljl4XIE') 1434 1435#============================================================================= 1436# sha256-crypt 1437#============================================================================= 1438class _sha256_crypt_test(HandlerCase): 1439 handler = hash.sha256_crypt 1440 1441 known_correct_hashes = [ 1442 # 1443 # from JTR 1.7.9 1444 # 1445 ('U*U*U*U*', '$5$LKO/Ute40T3FNF95$U0prpBQd4PloSGU0pnpM4z9wKn4vZ1.jsrzQfPqxph9'), 1446 ('U*U***U', '$5$LKO/Ute40T3FNF95$fdgfoJEBoMajNxCv3Ru9LyQ0xZgv0OBMQoq80LQ/Qd.'), 1447 ('U*U***U*', '$5$LKO/Ute40T3FNF95$8Ry82xGnnPI/6HtFYnvPBTYgOL23sdMXn8C29aO.x/A'), 1448 ('*U*U*U*U', '$5$9mx1HkCz7G1xho50$O7V7YgleJKLUhcfk9pgzdh3RapEaWqMtEp9UUBAKIPA'), 1449 ('', '$5$kc7lRD1fpYg0g.IP$d7CMTcEqJyTXyeq8hTdu/jB/I6DGkoo62NXbHIR7S43'), 1450 1451 # 1452 # custom tests 1453 # 1454 ('', '$5$rounds=10428$uy/jIAhCetNCTtb0$YWvUOXbkqlqhyoPMpN8BMe.ZGsGx2aBvxTvDFI613c3'), 1455 (' ', '$5$rounds=10376$I5lNtXtRmf.OoMd8$Ko3AI1VvTANdyKhBPavaRjJzNpSatKU6QVN9uwS9MH.'), 1456 ('test', '$5$rounds=11858$WH1ABM5sKhxbkgCK$aTQsjPkz0rBsH3lQlJxw9HDTDXPKBxC0LlVeV69P.t1'), 1457 ('Compl3X AlphaNu3meric', '$5$rounds=10350$o.pwkySLCzwTdmQX$nCMVsnF3TXWcBPOympBUUSQi6LGGloZoOsVJMGJ09UB'), 1458 ('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', '$5$rounds=11944$9dhlu07dQMRWvTId$LyUI5VWkGFwASlzntk1RLurxX54LUhgAcJZIt0pYGT7'), 1459 (u('with unic\u00D6de'), '$5$rounds=1000$IbG0EuGQXw5EkMdP$LQ5AfPf13KufFsKtmazqnzSGZ4pxtUNw3woQ.ELRDF4'), 1460 ] 1461 1462 if TEST_MODE("full"): 1463 # builtin alg was changed in 1.6, and had possibility of fencepost 1464 # errors near rounds that are multiples of 42. these hashes test rounds 1465 # 1004..1012 (42*24=1008 +/- 4) to ensure no mistakes were made. 1466 # (also relying on fuzz testing against os_crypt backend). 1467 known_correct_hashes.extend([ 1468 ("secret", '$5$rounds=1004$nacl$oiWPbm.kQ7.jTCZoOtdv7/tO5mWv/vxw5yTqlBagVR7'), 1469 ("secret", '$5$rounds=1005$nacl$6Mo/TmGDrXxg.bMK9isRzyWH3a..6HnSVVsJMEX7ud/'), 1470 ("secret", '$5$rounds=1006$nacl$I46VwuAiUBwmVkfPFakCtjVxYYaOJscsuIeuZLbfKID'), 1471 ("secret", '$5$rounds=1007$nacl$9fY4j1AV3N/dV/YMUn1enRHKH.7nEL4xf1wWB6wfDD4'), 1472 ("secret", '$5$rounds=1008$nacl$CiFWCfn8ODmWs0I1xAdXFo09tM8jr075CyP64bu3by9'), 1473 ("secret", '$5$rounds=1009$nacl$QtpFX.CJHgVQ9oAjVYStxAeiU38OmFILWm684c6FyED'), 1474 ("secret", '$5$rounds=1010$nacl$ktAwXuT5WbjBW/0ZU1eNMpqIWY1Sm4twfRE1zbZyo.B'), 1475 ("secret", '$5$rounds=1011$nacl$QJWLBEhO9qQHyMx4IJojSN9sS41P1Yuz9REddxdO721'), 1476 ("secret", '$5$rounds=1012$nacl$mmf/k2PkbBF4VCtERgky3bEVavmLZKFwAcvxD1p3kV2'), 1477 ]) 1478 1479 known_malformed_hashes = [ 1480 # bad char in otherwise correct hash 1481 '$5$rounds=10428$uy/:jIAhCetNCTtb0$YWvUOXbkqlqhyoPMpN8BMeZGsGx2aBvxTvDFI613c3', 1482 1483 # zero-padded rounds 1484 '$5$rounds=010428$uy/jIAhCetNCTtb0$YWvUOXbkqlqhyoPMpN8BMe.ZGsGx2aBvxTvDFI613c3', 1485 1486 # extra "$" 1487 '$5$rounds=10428$uy/jIAhCetNCTtb0$YWvUOXbkqlqhyoPMpN8BMe.ZGsGx2aBvxTvDFI613c3$', 1488 ] 1489 1490 known_correct_configs = [ 1491 # config, secret, result 1492 1493 # 1494 # taken from official specification at http://www.akkadia.org/drepper/SHA-crypt.txt 1495 # 1496 ( "$5$saltstring", "Hello world!", 1497 "$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5" ), 1498 ( "$5$rounds=10000$saltstringsaltstring", "Hello world!", 1499 "$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2." 1500 "opqey6IcA" ), 1501 ( "$5$rounds=5000$toolongsaltstring", "This is just a test", 1502 "$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8" 1503 "mGRcvxa5" ), 1504 ( "$5$rounds=1400$anotherlongsaltstring", 1505 "a very much longer text to encrypt. This one even stretches over more" 1506 "than one line.", 1507 "$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12" 1508 "oP84Bnq1" ), 1509 ( "$5$rounds=77777$short", 1510 "we have a short salt string but not a short password", 1511 "$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/" ), 1512 ( "$5$rounds=123456$asaltof16chars..", "a short string", 1513 "$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/" 1514 "cZKmF/wJvD" ), 1515 ( "$5$rounds=10$roundstoolow", "the minimum number is still observed", 1516 "$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL97" 1517 "2bIC" ), 1518 ] 1519 1520 filter_config_warnings = True # rounds too low, salt too small 1521 1522 platform_crypt_support = [ 1523 ("freebsd(9|1\d)|linux", True), 1524 ("freebsd8", None), # added in freebsd 8.3 1525 ("freebsd|openbsd|netbsd|darwin", False), 1526 ("solaris", None), # depends on policy 1527 ] 1528 1529# create test cases for specific backends 1530sha256_crypt_os_crypt_test = _sha256_crypt_test.create_backend_case("os_crypt") 1531sha256_crypt_builtin_test = _sha256_crypt_test.create_backend_case("builtin") 1532 1533#============================================================================= 1534# test sha512-crypt 1535#============================================================================= 1536class _sha512_crypt_test(HandlerCase): 1537 handler = hash.sha512_crypt 1538 1539 known_correct_hashes = [ 1540 # 1541 # from JTR 1.7.9 1542 # 1543 ('U*U*U*U*', "$6$LKO/Ute40T3FNF95$6S/6T2YuOIHY0N3XpLKABJ3soYcXD9mB7uVbtEZDj/LNscVhZoZ9DEH.sBciDrMsHOWOoASbNLTypH/5X26gN0"), 1544 ('U*U***U', "$6$LKO/Ute40T3FNF95$wK80cNqkiAUzFuVGxW6eFe8J.fSVI65MD5yEm8EjYMaJuDrhwe5XXpHDJpwF/kY.afsUs1LlgQAaOapVNbggZ1"), 1545 ('U*U***U*', "$6$LKO/Ute40T3FNF95$YS81pp1uhOHTgKLhSMtQCr2cDiUiN03Ud3gyD4ameviK1Zqz.w3oXsMgO6LrqmIEcG3hiqaUqHi/WEE2zrZqa/"), 1546 ('*U*U*U*U', "$6$OmBOuxFYBZCYAadG$WCckkSZok9xhp4U1shIZEV7CCVwQUwMVea7L3A77th6SaE9jOPupEMJB.z0vIWCDiN9WLh2m9Oszrj5G.gt330"), 1547 ('', "$6$ojWH1AiTee9x1peC$QVEnTvRVlPRhcLQCk/HnHaZmlGAAjCfrAN0FtOsOnUk5K5Bn/9eLHHiRzrTzaIKjW9NTLNIBUCtNVOowWS2mN."), 1548 1549 # 1550 # custom tests 1551 # 1552 ('', '$6$rounds=11021$KsvQipYPWpr93wWP$v7xjI4X6vyVptJjB1Y02vZC5SaSijBkGmq1uJhPr3cvqvvkd42Xvo48yLVPFt8dvhCsnlUgpX.//Cxn91H4qy1'), 1553 (' ', '$6$rounds=11104$ED9SA4qGmd57Fq2m$q/.PqACDM/JpAHKmr86nkPzzuR5.YpYa8ZJJvI8Zd89ZPUYTJExsFEIuTYbM7gAGcQtTkCEhBKmp1S1QZwaXx0'), 1554 ('test', '$6$rounds=11531$G/gkPn17kHYo0gTF$Kq.uZBHlSBXyzsOJXtxJruOOH4yc0Is13uY7yK0PvAvXxbvc1w8DO1RzREMhKsc82K/Jh8OquV8FZUlreYPJk1'), 1555 ('Compl3X AlphaNu3meric', '$6$rounds=10787$wakX8nGKEzgJ4Scy$X78uqaX1wYXcSCtS4BVYw2trWkvpa8p7lkAtS9O/6045fK4UB2/Jia0Uy/KzCpODlfVxVNZzCCoV9s2hoLfDs/'), 1556 ('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', '$6$rounds=11065$5KXQoE1bztkY5IZr$Jf6krQSUKKOlKca4hSW07MSerFFzVIZt/N3rOTsUgKqp7cUdHrwV8MoIVNCk9q9WL3ZRMsdbwNXpVk0gVxKtz1'), 1557 1558 # ensures utf-8 used for unicode 1559 (UPASS_TABLE, '$6$rounds=40000$PEZTJDiyzV28M3.m$GTlnzfzGB44DGd1XqlmC4erAJKCP.rhvLvrYxiT38htrNzVGBnplFOHjejUGVrCfusGWxLQCc3pFO0A/1jYYr0'), 1560 ] 1561 1562 known_malformed_hashes = [ 1563 # zero-padded rounds 1564 '$6$rounds=011021$KsvQipYPWpr93wWP$v7xjI4X6vyVptJjB1Y02vZC5SaSijBkGmq1uJhPr3cvqvvkd42Xvo48yLVPFt8dvhCsnlUgpX.//Cxn91H4qy1', 1565 # bad char in otherwise correct hash 1566 '$6$rounds=11021$KsvQipYPWpr9:wWP$v7xjI4X6vyVptJjB1Y02vZC5SaSijBkGmq1uJhPr3cvqvvkd42Xvo48yLVPFt8dvhCsnlUgpX.//Cxn91H4qy1', 1567 ] 1568 1569 known_correct_configs = [ 1570 # config, secret, result 1571 1572 # 1573 # taken from official specification at http://www.akkadia.org/drepper/SHA-crypt.txt 1574 # 1575 ("$6$saltstring", "Hello world!", 1576 "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu" 1577 "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1" ), 1578 1579 ( "$6$rounds=10000$saltstringsaltstring", "Hello world!", 1580 "$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb" 1581 "HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." ), 1582 1583 ( "$6$rounds=5000$toolongsaltstring", "This is just a test", 1584 "$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ" 1585 "zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" ), 1586 1587 ( "$6$rounds=1400$anotherlongsaltstring", 1588 "a very much longer text to encrypt. This one even stretches over more" 1589 "than one line.", 1590 "$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP" 1591 "vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" ), 1592 1593 ( "$6$rounds=77777$short", 1594 "we have a short salt string but not a short password", 1595 "$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g" 1596 "ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0" ), 1597 1598 ( "$6$rounds=123456$asaltof16chars..", "a short string", 1599 "$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc" 1600 "elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" ), 1601 1602 ( "$6$rounds=10$roundstoolow", "the minimum number is still observed", 1603 "$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x" 1604 "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." ), 1605 ] 1606 1607 filter_config_warnings = True # rounds too low, salt too small 1608 1609 platform_crypt_support = _sha256_crypt_test.platform_crypt_support 1610 1611# create test cases for specific backends 1612sha512_crypt_os_crypt_test = _sha512_crypt_test.create_backend_case("os_crypt") 1613sha512_crypt_builtin_test = _sha512_crypt_test.create_backend_case("builtin") 1614 1615#============================================================================= 1616# sun md5 crypt 1617#============================================================================= 1618class sun_md5_crypt_test(HandlerCase): 1619 handler = hash.sun_md5_crypt 1620 1621 # TODO: this scheme needs some real test vectors, especially due to 1622 # the "bare salt" issue which plagued the official parser. 1623 known_correct_hashes = [ 1624 # 1625 # http://forums.halcyoninc.com/showthread.php?t=258 1626 # 1627 ("Gpcs3_adm", "$md5$zrdhpMlZ$$wBvMOEqbSjU.hu5T2VEP01"), 1628 1629 # 1630 # http://www.c0t0d0s0.org/archives/4453-Less-known-Solaris-features-On-passwords-Part-2-Using-stronger-password-hashing.html 1631 # 1632 ("aa12345678", "$md5$vyy8.OVF$$FY4TWzuauRl4.VQNobqMY."), 1633 1634 # 1635 # http://www.cuddletech.com/blog/pivot/entry.php?id=778 1636 # 1637 ("this", "$md5$3UqYqndY$$6P.aaWOoucxxq.l00SS9k0"), 1638 1639 # 1640 # http://compgroups.net/comp.unix.solaris/password-file-in-linux-and-solaris-8-9 1641 # 1642 ("passwd", "$md5$RPgLF6IJ$WTvAlUJ7MqH5xak2FMEwS/"), 1643 1644 # 1645 # source: http://solaris-training.com/301_HTML/docs/deepdiv.pdf page 27 1646 # FIXME: password unknown 1647 # "$md5,rounds=8000$kS9FT1JC$$mnUrRO618lLah5iazwJ9m1" 1648 1649 # 1650 # source: http://www.visualexams.com/310-303.htm 1651 # XXX: this has 9 salt chars unlike all other hashes. is that valid? 1652 # FIXME: password unknown 1653 # "$md5,rounds=2006$2amXesSj5$$kCF48vfPsHDjlKNXeEw7V." 1654 # 1655 1656 # 1657 # custom 1658 # 1659 1660 # ensures utf-8 used for unicode 1661 (UPASS_TABLE, '$md5,rounds=5000$10VYDzAA$$1arAVtMA3trgE1qJ2V0Ez1'), 1662 ] 1663 1664 known_correct_configs = [ 1665 # (config, secret, hash) 1666 1667 #--------------------------- 1668 # test salt string handling 1669 # 1670 # these tests attempt to verify that passlib is handling 1671 # the "bare salt" issue (see sun md5 crypt docs) 1672 # in a sane manner 1673 #--------------------------- 1674 1675 # config with "$" suffix, hash strings with "$$" suffix, 1676 # should all be treated the same, with one "$" added to salt digest. 1677 ("$md5$3UqYqndY$", 1678 "this", "$md5$3UqYqndY$$6P.aaWOoucxxq.l00SS9k0"), 1679 ("$md5$3UqYqndY$$.................DUMMY", 1680 "this", "$md5$3UqYqndY$$6P.aaWOoucxxq.l00SS9k0"), 1681 1682 # config with no suffix, hash strings with "$" suffix, 1683 # should all be treated the same, and no suffix added to salt digest. 1684 # NOTE: this is just a guess re: config w/ no suffix, 1685 # but otherwise there's no sane way to encode bare_salt=False 1686 # within config string. 1687 ("$md5$3UqYqndY", 1688 "this", "$md5$3UqYqndY$HIZVnfJNGCPbDZ9nIRSgP1"), 1689 ("$md5$3UqYqndY$.................DUMMY", 1690 "this", "$md5$3UqYqndY$HIZVnfJNGCPbDZ9nIRSgP1"), 1691 ] 1692 1693 known_malformed_hashes = [ 1694 # unexpected end of hash 1695 "$md5,rounds=5000", 1696 1697 # bad rounds 1698 "$md5,rounds=500A$xxxx", 1699 "$md5,rounds=0500$xxxx", 1700 "$md5,rounds=0$xxxx", 1701 1702 # bad char in otherwise correct hash 1703 "$md5$RPgL!6IJ$WTvAlUJ7MqH5xak2FMEwS/", 1704 1705 # digest too short 1706 "$md5$RPgLa6IJ$WTvAlUJ7MqH5xak2FMEwS", 1707 1708 # digest too long 1709 "$md5$RPgLa6IJ$WTvAlUJ7MqH5xak2FMEwS/.", 1710 1711 # 2+ "$" at end of salt in config 1712 # NOTE: not sure what correct behavior is, so forbidding format for now. 1713 "$md5$3UqYqndY$$", 1714 1715 # 3+ "$" at end of salt in hash 1716 # NOTE: not sure what correct behavior is, so forbidding format for now. 1717 "$md5$RPgLa6IJ$$$WTvAlUJ7MqH5xak2FMEwS/", 1718 1719 ] 1720 1721 platform_crypt_support = [ 1722 ("solaris", True), 1723 ("freebsd|openbsd|netbsd|linux|darwin", False), 1724 ] 1725 def do_verify(self, secret, hash): 1726 # Override to fake error for "$..." hash string listed in known_correct_configs (above) 1727 # These have to be hash strings, in order to test bare salt issue. 1728 if isinstance(hash, str) and hash.endswith("$.................DUMMY"): 1729 raise ValueError("pretending '$...' stub hash is config string") 1730 return self.handler.verify(secret, hash) 1731 1732#============================================================================= 1733# unix disabled / fallback 1734#============================================================================= 1735class unix_disabled_test(HandlerCase): 1736 handler = hash.unix_disabled 1737# accepts_all_hashes = True # TODO: turn this off. 1738 1739 known_correct_hashes = [ 1740 # everything should hash to "!" (or "*" on BSD), 1741 # and nothing should verify against either string 1742 ("password", "!"), 1743 (UPASS_TABLE, "*"), 1744 ] 1745 1746 known_unidentified_hashes = [ 1747 # should never identify anything crypt() could return... 1748 "$1$xxx", 1749 "abc", 1750 "./az", 1751 "{SHA}xxx", 1752 ] 1753 1754 def test_76_hash_border(self): 1755 # so empty strings pass 1756 self.accepts_all_hashes = True 1757 super(unix_disabled_test, self).test_76_hash_border() 1758 1759 def test_90_special(self): 1760 """test marker option & special behavior""" 1761 warnings.filterwarnings("ignore", "passing settings to .*.hash\(\) is deprecated") 1762 handler = self.handler 1763 1764 # preserve hash if provided 1765 self.assertEqual(handler.genhash("stub", "!asd"), "!asd") 1766 1767 # use marker if no hash 1768 self.assertEqual(handler.genhash("stub", ""), handler.default_marker) 1769 self.assertEqual(handler.hash("stub"), handler.default_marker) 1770 self.assertEqual(handler.using().default_marker, handler.default_marker) 1771 1772 # custom marker 1773 self.assertEqual(handler.genhash("stub", "", marker="*xxx"), "*xxx") 1774 self.assertEqual(handler.hash("stub", marker="*xxx"), "*xxx") 1775 self.assertEqual(handler.using(marker="*xxx").hash("stub"), "*xxx") 1776 1777 # reject invalid marker 1778 self.assertRaises(ValueError, handler.genhash, 'stub', "", marker='abc') 1779 self.assertRaises(ValueError, handler.hash, 'stub', marker='abc') 1780 self.assertRaises(ValueError, handler.using, marker='abc') 1781 1782class unix_fallback_test(HandlerCase): 1783 handler = hash.unix_fallback 1784 accepts_all_hashes = True 1785 1786 known_correct_hashes = [ 1787 # *everything* should hash to "!", and nothing should verify 1788 ("password", "!"), 1789 (UPASS_TABLE, "!"), 1790 ] 1791 1792 # silence annoying deprecation warning 1793 def setUp(self): 1794 super(unix_fallback_test, self).setUp() 1795 warnings.filterwarnings("ignore", "'unix_fallback' is deprecated") 1796 1797 def test_90_wildcard(self): 1798 """test enable_wildcard flag""" 1799 h = self.handler 1800 self.assertTrue(h.verify('password','', enable_wildcard=True)) 1801 self.assertFalse(h.verify('password','')) 1802 for c in "!*x": 1803 self.assertFalse(h.verify('password',c, enable_wildcard=True)) 1804 self.assertFalse(h.verify('password',c)) 1805 1806 def test_91_preserves_existing(self): 1807 """test preserves existing disabled hash""" 1808 handler = self.handler 1809 1810 # use marker if no hash 1811 self.assertEqual(handler.genhash("stub", ""), "!") 1812 self.assertEqual(handler.hash("stub"), "!") 1813 1814 # use hash if provided and valid 1815 self.assertEqual(handler.genhash("stub", "!asd"), "!asd") 1816 1817#============================================================================= 1818# eof 1819#============================================================================= 1820