Package web2py :: Package gluon :: Module utils
[hide private]
[frames] | no frames]

Source Code for Module web2py.gluon.utils

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  """ 
  5  This file is part of the web2py Web Framework 
  6  Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu> 
  7  License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html) 
  8   
  9  This file specifically includes utilities for security. 
 10  """ 
 11   
 12  import hashlib 
 13  import hmac 
 14  import uuid 
 15  import random 
 16  import thread 
 17  import time 
 18  import os 
 19   
20 -def md5_hash(text):
21 """ Generate a md5 hash with the given text """ 22 return hashlib.md5(text).hexdigest()
23
24 -def simple_hash(text, digest_alg = 'md5'):
25 """ 26 Generates hash with the given text using the specified 27 digest hashing algorithm 28 """ 29 if not digest_alg: 30 raise RuntimeError, "simple_hash with digest_alg=None" 31 elif not isinstance(digest_alg,str): 32 h = digest_alg(text) 33 else: 34 h = hashlib.new(digest_alg) 35 h.update(text) 36 return h.hexdigest()
37
38 -def get_digest(value):
39 """ 40 Returns a hashlib digest algorithm from a string 41 """ 42 if not isinstance(value,str): 43 return value 44 value = value.lower() 45 if value == "md5": 46 return hashlib.md5 47 elif value == "sha1": 48 return hashlib.sha1 49 elif value == "sha224": 50 return hashlib.sha224 51 elif value == "sha256": 52 return hashlib.sha256 53 elif value == "sha384": 54 return hashlib.sha384 55 elif value == "sha512": 56 return hashlib.sha512 57 else: 58 raise ValueError("Invalid digest algorithm")
59
60 -def hmac_hash(value, key, digest_alg='md5', salt=None):
61 if ':' in key: 62 digest_alg, key = key.split(':') 63 digest_alg = get_digest(digest_alg) 64 d = hmac.new(key,value,digest_alg) 65 if salt: 66 d.update(str(salt)) 67 return d.hexdigest()
68 69 70 ### compute constent ctokens
71 -def initialize_urandom():
72 """ 73 This function and the web2py_uuid follow from the following discussion: 74 http://groups.google.com/group/web2py-developers/browse_thread/thread/7fd5789a7da3f09 75 76 At startup web2py compute a unique ID that identifies the machine by adding 77 uuid.getnode() + int(time.time() * 1e3) 78 79 This is a 48bits number. It converts the number into 16x8bits tokens. 80 It uses thie unique if to initilize the entropy source ('/dev/urandom') or to seed random. 81 82 If os.random() is not supported, it falls back to using random and issues a warning. 83 """ 84 node_id = uuid.getnode() 85 milliseconds = int(time.time() * 1e3) 86 ctokens = [((node_id + milliseconds) >> ((i%6)*8)) % 256 for i in range(16)] 87 try: 88 os.urandom(1) 89 if os.path.exists('/dev/urandom'): 90 open('/dev/urandom','wb').write(''.join(chr(t) for t in ctokens)) 91 except NotImplementedError: 92 random.seed(node_id + milliseconds) 93 logging.warn( 94 """Cryptographycally secure session management is not possible on your system because 95 your system does not provide a cryptographically secure entropy source. 96 This is not specific to web2py. Consider deploying on a different Operating System.""") 97 return ctokens
98 ctokens = initialize_urandom() 99
100 -def web2py_uuid():
101 """ 102 This function follows from the following discussion: 103 http://groups.google.com/group/web2py-developers/browse_thread/thread/7fd5789a7da3f09 104 105 It works like uuid.uuid4 exxcept that tries to use os.urandom() if possible 106 And it XORs the output with the tokens uniquely associated to this machine. 107 """ 108 try: 109 bytes = os.urandom(16) # use /dev/urandom if possible 110 except NotImplementedError: 111 bytes = [chr(random.randrange(256)) for i in range(16)] 112 ## xor bytes with contant ctokens 113 bytes = ''.join(chr(ord(c) ^ ctokens[i]) for i,c in enumerate(bytes)) 114 return str(uuid.UUID(bytes=bytes, version=4))
115