diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2011-01-25 01:17:40 +0000 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2011-01-25 01:17:40 +0000 |
| commit | 2ba159bb201d3da7fe5fcd533e1a6531a3489062 (patch) | |
| tree | 6f2a3e51150d9c729f3695d36688a7f1637da89d /passlib | |
| parent | 5e9e909043cab4133443c574ef4318bb229e87ec (diff) | |
| download | passlib-2ba159bb201d3da7fe5fcd533e1a6531a3489062.tar.gz | |
work on lanman hash
Diffstat (limited to 'passlib')
| -rw-r--r-- | passlib/lanman.py | 44 | ||||
| -rw-r--r-- | passlib/tests/test_des_crypt.py | 52 | ||||
| -rw-r--r-- | passlib/utils/__init__.py | 23 | ||||
| -rw-r--r-- | passlib/utils/_slow_des_crypt.py | 49 | ||||
| -rw-r--r-- | passlib/utils/md4.py | 1 |
5 files changed, 146 insertions, 23 deletions
diff --git a/passlib/lanman.py b/passlib/lanman.py index 7611cfa..ead8f07 100644 --- a/passlib/lanman.py +++ b/passlib/lanman.py @@ -3,33 +3,35 @@ lanman macintosh -D47F3AF827A48F7DFA4F2C1F12D68CD6 08460EB13C5CA0C4CA9516712F7FED95 +D47F 3AF8 27A4 8F7D FA4F 2C1F 12D6 8CD6 -ntlm - -""" +08460EB13C5CA0C4CA9516712F7FED95 -from passlib.utils._slow_des_crypt import des_encrypt_rounds +ntlm -secret = "macintosh" -s = secret.upper()[:14] + "\x00" * (14-len(secret)) -sa, sb = s[:7], s[7:] +lanman -cc = 0 -for c in reversed("KGS!@#$%"): - cc <<= 8 - cc |= ord(c) +C234 13A8 A1E7 665f +AAD3 B435 B514 04EE +welcome +""" +from binascii import hexlify +from bps.numeric import int_to_base +from passlib.utils._slow_des_crypt import des_encrypt_block -ka = 0 -for c in reversed(sa): - ka <<= 8 - ka |= (ord(c)<<1) +LM_MAGIC = "KGS!@#$%" -ct = des_encrypt_rounds(cc, 0, 25, ka) +def lmhash(secret): + #XXX: encoding should be oem ascii + ns = secret.upper()[:14] + "\x00" * (14-len(secret)) + return hexlify(des_encrypt_block(expand_des_key(ns[:7]), LM_MAGIC) + des_encrypt_block(expand_des_key(ns[7:]), LM_MAGIC)) -out = '' -for i in xrange(8): - out += '%02x' % ((ct>>(8*(7-i))) & 0xFF) +for secret, hash in [ + #hashes from http://msdn.microsoft.com/en-us/library/cc245828(v=prot.10).aspx + ("OLDPASSWORD", "c9b81d939d6fd80cd408e6b105741864"), + ("NEWPASSWORD", '09eeab5aa415d6e4d408e6b105741864'), + ("welcome", "c23413a8a1e7665faad3b435b51404ee"), + ]: -print out + print secret, lmhash(secret), hash == lmhash(secret) diff --git a/passlib/tests/test_des_crypt.py b/passlib/tests/test_des_crypt.py index ea8898a..6553a77 100644 --- a/passlib/tests/test_des_crypt.py +++ b/passlib/tests/test_des_crypt.py @@ -131,6 +131,58 @@ if enable_test("backends"): def get_crypt(self): return mod.crypt + +class DesTest(TestCase): + + #test vectors taken from http://www.skepticfiles.org/faq/testdes.htm + + #(key, plaintext, ciphertext) all as 64 bit + test_des_vectors = [ + (int(line[4:21],16), int(line[21:38],16), int(line[38:],16)) + for line in + """ 0000000000000000 0000000000000000 8CA64DE9C1B123A7 + FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58 + 3000000000000000 1000000000000001 958E6E627A05557B + 1111111111111111 1111111111111111 F40379AB9E0EC533 + 0123456789ABCDEF 1111111111111111 17668DFC7292532D + 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD + 0000000000000000 0000000000000000 8CA64DE9C1B123A7 + FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4 + 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B + 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 + 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A + 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A + 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 + 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B + 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 + 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A + 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F + 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 + 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 + 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A + 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 + 025816164629B007 480D39006EE762F2 A1F9915541020B56 + 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 + 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC + 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A + 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 + 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 + 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100 + 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606 + E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7 + 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451 + FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE + 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D + FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2 + """.split("\n") if line.strip() + ] + + def test_des_encrypt_int_block(self): + from passlib.utils._slow_des_crypt import des_encrypt_int_block + for k,p,c in self.test_des_vectors: + result = des_encrypt_int_block(k,p) + self.assertEqual(result, c, "key=%r p=%r:" % (k,p)) + #========================================================= #EOF #========================================================= diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index dd17d1d..9b8a472 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -73,8 +73,29 @@ Undef = object() #singleton used as default kwd value in some functions #numeric helpers #================================================================================= -#TODO: rename 'bytes' kwd for py30 compat purposes +##def int_to_bytes(value, count=None): +## """encode a integer into a string of bytes""" +## +##def bytes_to_int(value, order="big"): +## """decode a byte string into an integer representation of it's binary value. +## +## :arg value: the string to decode. +## :param order: the byte ordering; "big" (the default), "little", or "native" +## +## :returns: the decoded positive integer. +## """ +## if not value: +## return 0 +## if order == "native": +## order = sys.byteorder +## if order == "little": +## value = reversed(value) +## out = 0 +## for v in value: +## out = (out<<8) | ord(v) +## return out +#TODO: rename 'bytes' kwd for py30 compat purposes def list_to_bytes(value, bytes=None, order="big"): """Returns a multi-character string corresponding to a list of byte values. diff --git a/passlib/utils/_slow_des_crypt.py b/passlib/utils/_slow_des_crypt.py index cc68327..9ebf518 100644 --- a/passlib/utils/_slow_des_crypt.py +++ b/passlib/utils/_slow_des_crypt.py @@ -620,8 +620,55 @@ def permute(c, p): c >>= 4 return out +def bytes_to_int(value): + out = 0 + for v in value: + out = (out<<8) | ord(v) + return out + +def int_to_bytes(value, count): + return ''.join( + chr((value>>s) & 0xff) + for s in xrange(8*count-8,-8,-8) + ) + +def des_encrypt_block(key, input): + "do traditional encryption of a single DES block" + assert len(input) == 8 + assert len(key) == 8 + input = bytes_to_int(input) + key = bytes_to_int(key) + out = des_encrypt_rounds(input, 0, 1, key) + return int_to_bytes(out, 8) + +def expand_des_key(source): + "convert 7 byte des key to 8 byte des key (by adding parity bit every 7 bits)" + #NOTE: could probably do this much more cleverly and efficiently, + # but no need really given it's use + assert len(source) == 7 + + def iter_bits(source): + for c in source: + v = ord(c) + for i in xrange(7,-1,-1): + yield (v>>i) & 1 + + out = 0 + p = 1 + for i, b in enumerate(iter_bits(source)): + out = (out<<1) + b + p ^= b + if i % 7 == 6: + out = (out<<1) + p + p = 1 + + return ''.join( + chr((out>>s) & 0xFF) + for s in xrange(8*7,-8,-8) + ) + def des_encrypt_rounds(input, salt, rounds, key): - """Returns modified DES for single block of input""" + """returns modified DES for single block of input, used by des-crypt algorithm""" global SPE, PCXROT, IE3264, CF6464 #bounds check diff --git a/passlib/utils/md4.py b/passlib/utils/md4.py index fe88f6a..2eb2c95 100644 --- a/passlib/utils/md4.py +++ b/passlib/utils/md4.py @@ -27,6 +27,7 @@ class md4(object): "md4 hash algorithm" #FIXME: make this follow hash object PEP better. #FIXME: this isn't threadsafe + #XXX: should we monkeypatch ourselves into hashlib for general use? probably wouldn't be nice. digest_size = digestsize = 16 |
