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 time 
 17  import os 
 18  import logging 
 19   
 20  logger = logging.getLogger("web2py") 
 21   
22 -def md5_hash(text):
23 """ Generate a md5 hash with the given text """ 24 return hashlib.md5(text).hexdigest()
25
26 -def simple_hash(text, digest_alg = 'md5'):
27 """ 28 Generates hash with the given text using the specified 29 digest hashing algorithm 30 """ 31 if not digest_alg: 32 raise RuntimeError, "simple_hash with digest_alg=None" 33 elif not isinstance(digest_alg,str): 34 h = digest_alg(text) 35 else: 36 h = hashlib.new(digest_alg) 37 h.update(text) 38 return h.hexdigest()
39
40 -def get_digest(value):
41 """ 42 Returns a hashlib digest algorithm from a string 43 """ 44 if not isinstance(value,str): 45 return value 46 value = value.lower() 47 if value == "md5": 48 return hashlib.md5 49 elif value == "sha1": 50 return hashlib.sha1 51 elif value == "sha224": 52 return hashlib.sha224 53 elif value == "sha256": 54 return hashlib.sha256 55 elif value == "sha384": 56 return hashlib.sha384 57 elif value == "sha512": 58 return hashlib.sha512 59 else: 60 raise ValueError("Invalid digest algorithm")
61
62 -def hmac_hash(value, key, digest_alg='md5', salt=None):
63 if ':' in key: 64 digest_alg, key = key.split(':') 65 digest_alg = get_digest(digest_alg) 66 d = hmac.new(key,value,digest_alg) 67 if salt: 68 d.update(str(salt)) 69 return d.hexdigest()
70 71 72 ### compute constant ctokens
73 -def initialize_urandom():
74 """ 75 This function and the web2py_uuid follow from the following discussion: 76 http://groups.google.com/group/web2py-developers/browse_thread/thread/7fd5789a7da3f09 77 78 At startup web2py compute a unique ID that identifies the machine by adding 79 uuid.getnode() + int(time.time() * 1e3) 80 81 This is a 48-bit number. It converts the number into 16 8-bit tokens. 82 It uses this value to initialize the entropy source ('/dev/urandom') and to seed random. 83 84 If os.random() is not supported, it falls back to using random and issues a warning. 85 """ 86 node_id = uuid.getnode() 87 microseconds = int(time.time() * 1e6) 88 ctokens = [((node_id + microseconds) >> ((i%6)*8)) % 256 for i in range(16)] 89 random.seed(node_id + microseconds) 90 try: 91 os.urandom(1) 92 try: 93 # try to add process-specific entropy 94 frandom = open('/dev/urandom','wb') 95 try: 96 frandom.write(''.join(chr(t) for t in ctokens)) 97 finally: 98 frandom.close() 99 except IOError: 100 # works anyway 101 pass 102 except NotImplementedError: 103 logger.warning( 104 """Cryptographically secure session management is not possible on your system because 105 your system does not provide a cryptographically secure entropy source. 106 This is not specific to web2py; consider deploying on a different operating system.""") 107 return ctokens
108 ctokens = initialize_urandom() 109
110 -def web2py_uuid():
111 """ 112 This function follows from the following discussion: 113 http://groups.google.com/group/web2py-developers/browse_thread/thread/7fd5789a7da3f09 114 115 It works like uuid.uuid4 except that tries to use os.urandom() if possible 116 and it XORs the output with the tokens uniquely associated with this machine. 117 """ 118 bytes = [random.randrange(256) for i in range(16)] 119 try: 120 ubytes = [ord(c) for c in os.urandom(16)] # use /dev/urandom if possible 121 bytes = [bytes[i] ^ ubytes[i] for i in range(16)] 122 except NotImplementedError: 123 pass 124 ## xor bytes with constant ctokens 125 bytes = ''.join(chr(c ^ ctokens[i]) for i,c in enumerate(bytes)) 126 return str(uuid.UUID(bytes=bytes, version=4))
127