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

Source Code for Module Peach.Transformers.crypto

  1   
  2  ''' 
  3  Crypto transforms (encrypting, hashing, etc), and misc auth crap. 
  4   
  5  @author: Michael Eddington 
  6  @version: $Id: Peach.Transformers.crypto-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
  7  ''' 
  8   
  9  # 
 10  # Copyright (c) 2005-2006 Michael Eddington 
 11  # Copyright (c) 2004-2005 IOActive Inc. 
 12  # 
 13  # Permission is hereby granted, free of charge, to any person obtaining a copy  
 14  # of this software and associated documentation files (the "Software"), to deal 
 15  # in the Software without restriction, including without limitation the rights  
 16  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
 17  # copies of the Software, and to permit persons to whom the Software is  
 18  # furnished to do so, subject to the following conditions: 
 19  # 
 20  # The above copyright notice and this permission notice shall be included in     
 21  # all copies or substantial portions of the Software. 
 22  # 
 23  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 24  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 25  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 26  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 27  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 28  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 29  # SOFTWARE. 
 30  # 
 31   
 32  # Authors: 
 33  #   Michael Eddington (mike@phed.org) 
 34   
 35  # $Id: Peach.Transformers.crypto-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
 36   
 37   
 38  import md5, sha, fcrypt, md5crypt, hmac 
 39   
 40  #__all__ = ['Crypt', 'UnixMd5Crypt', 'ApacheMd5Crypt', 'CvsScramble', 
 41  #                  'Md5', 'Sha1', 'Hmac'] 
 42   
 43  from Peach.transformer import Transformer 
 44  from Peach.Generators import static 
 45   
46 -class Crypt(Transformer):
47 ''' 48 UNIX style crypt. If no salt is specified will use first 49 two chars of data, ala pwd style. 50 51 This transform uses a pure Python implementation of the crypt 52 function which had been ported from an old C version. See 53 fcrypt.py for licensing differences. 54 55 From underlying docs: 56 57 I{Generate an encrypted hash from the passed password. If the password 58 is longer than eight characters, only the first eight will be used.} 59 60 I{The first two characters of the salt are used to modify the encryption 61 algorithm used to generate in the hash in one of 4096 different ways. 62 The characters for the salt should be upper- and lower-case letters A 63 to Z, digits 0 to 9, '.' and '/'.} 64 65 I{The returned hash begins with the two characters of the salt, and 66 should be passed as the salt to verify the password.} 67 ''' 68 69 _salt = None 70
71 - def __init__(self, salt = None):
72 ''' 73 @type salt: string 74 @param salt: Salt for crypt (optional) 75 ''' 76 Transformer.__init__(self) 77 self._salt = salt
78
79 - def realEncode(self, data):
80 if self._salt == None: 81 return fcrypt.crypt(data, data[:2]) 82 return fcrypt.crypt(data, self._salt)
83
84 - def unittest():
85 crypted = "heD1umJOQHx9A" # 'hello world' salt 'he' 86 t = Crypt() 87 print "Crypt 1: " + t.realEncode("hello world") 88 if crypted != t.realEncode('hello world'): 89 raise Exception("Crypt::unittest(): Failed to match 'hello world' with 'he' salt.") 90 print "Crypt: " + t.realEncode("<script> alert('meow') </script>")
91 unittest = staticmethod(unittest)
92 93
94 -class UnixMd5Crypt(Transformer):
95 ''' 96 UNIX style MD5 crypt. If no salt is specified will use first 97 two chars of data, ala pwd style. 98 99 From underlying docs: 100 101 I{unix_md5_crypt() provides a crypt()-compatible interface to the 102 rather new MD5-based crypt() function found in modern operating systems. 103 It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE and 104 contains the following license in it:} 105 106 I{"THE BEER-WARE LICENSE" (Revision 42): 107 <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 108 can do whatever you want with this stuff. If we meet some day, and you think 109 this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp} 110 ''' 111 112 _salt = None 113 _magic = None 114
115 - def __init__(self, salt = None, magic = None):
116 ''' 117 @type salt: string 118 @param salt: Salt for crypt (optional) 119 @type magic: string 120 @param magic: Magic, usually $1$ on unix (optional) 121 ''' 122 Transformer.__init__(self) 123 self._salt = salt 124 self._magic = magic
125
126 - def realEncode(self, data):
127 if self._salt == None: 128 return md5crypt.unix_md5_crypt(data, data[:2], self._magic) 129 return md5crypt.unix_md5_crypt(data, self._salt, self._magic)
130
131 - def unittest():
132 #crypted = "heD1umJOQHx9A" # 'hello world' salt 'he' 133 t = UnixMd5Crypt() 134 print "UnixMd5Crypt 1: " + t.realEncode("hello world") 135 t = UnixMd5Crypt('ME') 136 print "UnixMd5Crypt 2: " + t.realEncode("hello world")
137 #if crypted != t.realEncode('hello world'): 138 # raise Exception("Crypt::unittest(): Failed to match 'hello world' with 'he' salt.") 139 #print "Crypt: " + t.realEncode("<script> alert('meow') </script>") 140 unittest = staticmethod(unittest)
141 142
143 -class ApacheMd5Crypt(Transformer):
144 ''' 145 Apache style MD5 crypt. If no salt is specified will use first two chars of 146 data, ala pwd style. 147 148 Uses '$apr1$' as magic. 149 150 From underlying docs: 151 152 I{apache_md5_crypt() provides a function compatible with Apache's 153 .htpasswd files. This was contributed by Bryan Hart <bryan@eai.com>.} 154 155 I{"THE BEER-WARE LICENSE" (Revision 42): 156 <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 157 can do whatever you want with this stuff. If we meet some day, and you think 158 this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp} 159 ''' 160 161 _salt = None 162
163 - def __init__(self, salt = None):
164 ''' 165 @type salt: string 166 @param salt: Salt for crypt (optional) 167 ''' 168 Transformer.__init__(self) 169 self._salt = salt
170
171 - def realEncode(self, data):
172 if self._salt == None: 173 return md5crypt.apache_md5_crypt(data, data[:2]) 174 return md5crypt.apache_md5_crypt(data, self._salt)
175
176 - def unittest():
177 #crypted = "heD1umJOQHx9A" # 'hello world' salt 'he' 178 t = ApacheMd5Crypt() 179 print "ApacheMd5Crypt 1: " + t.realEncode("hello world") 180 t = ApacheMd5Crypt('ME') 181 print "ApacheMd5Crypt 2: " + t.realEncode("hello world")
182 #if crypted != t.realEncode('hello world'): 183 # raise Exception("Crypt::unittest(): Failed to match 'hello world' with 'he' salt.") 184 #print "Crypt: " + t.realEncode("<script> alert('meow') </script>") 185 unittest = staticmethod(unittest)
186 187
188 -class CvsScramble(Transformer):
189 ''' 190 CVS pserver password scramble 191 ''' 192 193 _shifts = [ 194 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 195 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 196 114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87, 197 111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105, 198 41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35, 199 125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56, 200 36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48, 201 58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223, 202 225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190, 203 199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193, 204 174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212, 205 207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246, 206 192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176, 207 227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127, 208 182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195, 209 243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 210 ] 211
212 - def realEncode(self, data):
213 s = [] 214 for i in range(len(data)): 215 s.append(data[i]) 216 s.append(None) 217 for i in range(len(data)): 218 s[i+1] = "%c" % self._shifts[ord(data[i])] 219 220 out = '' 221 for i in range(len(s)): 222 out += s[i] 223 224 return out
225
226 - def unittest():
227 t = CvsScramble() 228 print "CvsScramble 1: " + t.realEncode("hello world")
229 unittest = staticmethod(unittest)
230 231
232 -class Md5(Transformer):
233 ''' 234 MD5 transform (hex and binary) 235 ''' 236 237 _asHex = 0 238
239 - def __init__(self, asHex = 0):
240 ''' 241 @type asHex: number 242 @param asHex: 1 is hex, 0 is binary 243 ''' 244 Transformer.__init__(self) 245 self._asHex = asHex
246
247 - def realEncode(self, data):
248 if self._asHex == 0: 249 return md5.new(data).digest() 250 return md5.new(data).hexdigest()
251
252 - def unittest():
253 t = Md5(1) 254 print "Md5 1: " + t.realEncode("hello world")
255 unittest = staticmethod(unittest)
256 257
258 -class Sha1(Transformer):
259 ''' 260 SHA-1 transform (hex and binary) 261 ''' 262 263 _asHex = 0 264
265 - def __init__(self, asHex = 0):
266 ''' 267 @type asHex: number 268 @param asHex: 1 is hex, 0 is binary 269 ''' 270 Transformer.__init__(self) 271 self._asHex = asHex
272
273 - def realEncode(self, data):
274 if self._asHex == 0: 275 return sha.new(data).digest() 276 return sha.new(data).hexdigest()
277
278 - def unittest():
279 t = Sha1(1) 280 print "Sha1 1: " + t.realEncode("hello world")
281 unittest = staticmethod(unittest)
282 283
284 -class Hmac(Transformer):
285 ''' 286 HMAC as described in RFC 2104. Key is a generator. 287 ''' 288 289 _key = None 290 _digestmod = None 291 _asHex = None 292
293 - def __init__(self, key, digestmod = md5, asHex = 0):
294 ''' 295 Key is a generator for HMAC key, digestmod is hash to use (md5 or sha) 296 297 @type key: Generator 298 @param key: HMAC key 299 @type digestmod: md5 or sha 300 @param digestmod: Which digest to use 301 @type asHex: number 302 @param asHex: 1 is hex, 0 is binary 303 ''' 304 Transformer.__init__(self) 305 self._key = key 306 self._digestmod = digestmod 307 self._asHex = asHex
308
309 - def realEncode(self, data):
310 if self._asHex == 0: 311 return hmac.new(self._key.getValue(), data, self._digestmod).digest() 312 return hmac.new(self._key.getValue(), data, self._digestmod).hexdigest()
313
314 - def unittest():
315 t = Hmac(static.Static('hello world'), md5, 1) 316 print "Hmac (md5) 1: " + t.realEncode("hello world") 317 t = Hmac(static.Static('hello world'), sha, 1) 318 print "Hmac (sha1) 1: " + t.realEncode("hello world")
319 unittest = staticmethod(unittest)
320 321 322 323 # end 324