root/accountmanagerplugin/0.10/acct_mgr/md5crypt.py

Revision 1068, 3.0 kB (checked in by mgood, 2 years ago)

AccountManagerPlugin:

change source coding to "utf-8" and fix the URL in setup.py

Line 
1 # -*- coding: utf-8 -*-
2 #
3 # Based on FreeBSD src/lib/libcrypt/crypt.c 1.2
4 # http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libcrypt/crypt.c?rev=1.2&content-type=text/plain
5
6 # Original license:
7 # * "THE BEER-WARE LICENSE" (Revision 42):
8 # * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
9 # * can do whatever you want with this stuff. If we meet some day, and you think
10 # * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
11
12 # This port adds no further stipulations.  I forfeit any copyright interest.
13
14 import md5
15
16 def md5crypt(password, salt, magic='$1$'):
17     # /* The password first, since that is what is most unknown */ /* Then our magic string */ /* Then the raw salt */
18     m = md5.new()
19     m.update(password + magic + salt)
20
21     # /* Then just as many characters of the MD5(pw,salt,pw) */
22     mixin = md5.md5(password + salt + password).digest()
23     for i in range(0, len(password)):
24         m.update(mixin[i % 16])
25
26     # /* Then something really weird... */
27     # Also really broken, as far as I can tell.  -m
28     i = len(password)
29     while i:
30         if i & 1:
31             m.update('\x00')
32         else:
33             m.update(password[0])
34         i >>= 1
35
36     final = m.digest()
37
38     # /* and now, just to make sure things don't run too fast */
39     for i in range(1000):
40         m2 = md5.md5()
41         if i & 1:
42             m2.update(password)
43         else:
44             m2.update(final)
45
46         if i % 3:
47             m2.update(salt)
48
49         if i % 7:
50             m2.update(password)
51
52         if i & 1:
53             m2.update(final)
54         else:
55             m2.update(password)
56
57         final = m2.digest()
58
59     # This is the bit that uses to64() in the original code.
60
61     itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
62
63     rearranged = ''
64     for a, b, c in ((0, 6, 12), (1, 7, 13), (2, 8, 14), (3, 9, 15), (4, 10, 5)):
65         v = ord(final[a]) << 16 | ord(final[b]) << 8 | ord(final[c])
66         for i in range(4):
67             rearranged += itoa64[v & 0x3f]; v >>= 6
68
69     v = ord(final[11])
70     for i in range(2):
71         rearranged += itoa64[v & 0x3f]; v >>= 6
72
73     return magic + salt + '$' + rearranged
74
75 if __name__ == '__main__':
76
77     def test(clear_password, the_hash):
78         magic, salt = the_hash[1:].split('$')[:2]
79         magic = '$' + magic + '$'
80         return md5crypt(clear_password, salt, magic) == the_hash
81
82     test_cases = (
83         (' ', '$1$yiiZbNIH$YiCsHZjcTkYd31wkgW8JF.'),
84         ('pass', '$1$YeNsbWdH$wvOF8JdqsoiLix754LTW90'),
85         ('____fifteen____', '$1$s9lUWACI$Kk1jtIVVdmT01p0z3b/hw1'),
86         ('____sixteen_____', '$1$dL3xbVZI$kkgqhCanLdxODGq14g/tW1'),
87         ('____seventeen____', '$1$NaH5na7J$j7y8Iss0hcRbu3kzoJs5V.'),
88         ('__________thirty-three___________', '$1$HO7Q6vzJ$yGwp2wbL5D7eOVzOmxpsy.'),
89         ('apache', '$apr1$J.w5a/..$IW9y6DR0oO/ADuhlMF5/X1')
90     )
91
92     for clearpw, hashpw in test_cases:
93         if test(clearpw, hashpw):
94             print '%s: pass' % clearpw
95         else:
96             print '%s: FAIL' % clearpw
Note: See TracBrowser for help on using the browser.