Package Peach :: Package Transformers :: Module md5crypt
[hide private]

Source Code for Module Peach.Transformers.md5crypt

  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$'                   # Magic string 
 42  ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 
 43   
 44  import md5 
 45   
46 -def to64 (v, n):
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
55 -def apache_md5_crypt (pw, salt):
56 # change the Magic string to match the one used by Apache 57 return unix_md5_crypt(pw, salt, '$apr1$')
58 59
60 -def unix_md5_crypt(pw, salt, magic=None):
61 62 if magic==None: 63 magic = MAGIC 64 65 # Take care of the magic string if present 66 if salt[:len(magic)] == magic: 67 salt = salt[len(magic):] 68 69 70 # salt can have up to 8 characters: 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 # Now the 'weird' xform (??) 87 88 i = len(pw) 89 while i: 90 if i & 1: 91 ctx = ctx + chr(0) #if ($i & 1) { $ctx->add(pack("C", 0)); } 92 else: 93 ctx = ctx + pw[0] 94 i = i >> 1 95 96 final = md5.md5(ctx).digest() 97 98 # The following is supposed to make 99 # things run slower. 100 101 # my question: WTF??? 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 # Final xform 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 ## assign a wrapper function: 156 md5crypt = unix_md5_crypt 157 158 if __name__ == "__main__": 159 print unix_md5_crypt("cat", "hat") 160 161 # end 162