1 """md5crypt.py - Provides interoperable MD5-based crypt() function
2
3 SYNOPSIS
4
5 import md5crypt.py
6
7 cryptedpassword = md5crypt.md5crypt(password, salt);
8
9 DESCRIPTION
10
11 unix_md5_crypt() provides a crypt()-compatible interface to the
12 rather new MD5-based crypt() function found in modern operating systems.
13 It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE and
14 contains the following license in it:
15
16 "THE BEER-WARE LICENSE" (Revision 42):
17 <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
18 can do whatever you want with this stuff. If we meet some day, and you think
19 this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
20
21 apache_md5_crypt() provides a function compatible with Apache's
22 .htpasswd files. This was contributed by Bryan Hart <bryan@eai.com>.
23
24 #########################################################
25 # md5crypt.py
26 #
27 # 0423.2000 by michal wallace http://www.sabren.com/
28 # based on perl's Crypt::PasswdMD5 by Luis Munoz (lem@cantv.net)
29 # based on /usr/src/libcrypt/crypt.c from FreeBSD 2.2.5-RELEASE
30 #
31 # MANY THANKS TO
32 #
33 # Carey Evans - http://home.clear.net.nz/pages/c.evans/
34 # Dennis Marti - http://users.starpower.net/marti1/
35 #
36 # For the patches that got this thing working!
37 #
38 #########################################################
39 """
40
41 MAGIC = '$1$'
42 ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
43
44 import md5
45
47 ret = ''
48 while (n - 1 >= 0):
49 n = n - 1
50 ret = ret + ITOA64[v & 0x3f]
51 v = v >> 6
52 return ret
53
54
58
59
61
62 if magic==None:
63 magic = MAGIC
64
65
66 if salt[:len(magic)] == magic:
67 salt = salt[len(magic):]
68
69
70
71 import string
72 salt = string.split(salt, '$', 1)[0]
73 salt = salt[:8]
74
75 ctx = pw + magic + salt
76
77 final = md5.md5(pw + salt + pw).digest()
78
79 for pl in range(len(pw),0,-16):
80 if pl > 16:
81 ctx = ctx + final[:16]
82 else:
83 ctx = ctx + final[:pl]
84
85
86
87
88 i = len(pw)
89 while i:
90 if i & 1:
91 ctx = ctx + chr(0)
92 else:
93 ctx = ctx + pw[0]
94 i = i >> 1
95
96 final = md5.md5(ctx).digest()
97
98
99
100
101
102
103 for i in range(1000):
104 ctx1 = ''
105 if i & 1:
106 ctx1 = ctx1 + pw
107 else:
108 ctx1 = ctx1 + final[:16]
109
110 if i % 3:
111 ctx1 = ctx1 + salt
112
113 if i % 7:
114 ctx1 = ctx1 + pw
115
116 if i & 1:
117 ctx1 = ctx1 + final[:16]
118 else:
119 ctx1 = ctx1 + pw
120
121
122 final = md5.md5(ctx1).digest()
123
124
125
126
127 passwd = ''
128
129 passwd = passwd + to64((int(ord(final[0])) << 16)
130 |(int(ord(final[6])) << 8)
131 |(int(ord(final[12]))),4)
132
133 passwd = passwd + to64((int(ord(final[1])) << 16)
134 |(int(ord(final[7])) << 8)
135 |(int(ord(final[13]))), 4)
136
137 passwd = passwd + to64((int(ord(final[2])) << 16)
138 |(int(ord(final[8])) << 8)
139 |(int(ord(final[14]))), 4)
140
141 passwd = passwd + to64((int(ord(final[3])) << 16)
142 |(int(ord(final[9])) << 8)
143 |(int(ord(final[15]))), 4)
144
145 passwd = passwd + to64((int(ord(final[4])) << 16)
146 |(int(ord(final[10])) << 8)
147 |(int(ord(final[5]))), 4)
148
149 passwd = passwd + to64((int(ord(final[11]))), 2)
150
151
152 return magic + salt + '$' + passwd
153
154
155
156 md5crypt = unix_md5_crypt
157
158 if __name__ == "__main__":
159 print unix_md5_crypt("cat", "hat")
160
161
162