1
2
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
21 """ Generate a md5 hash with the given text """
22 return hashlib.md5(text).hexdigest()
23
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
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
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
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)
110 except NotImplementedError:
111 bytes = [chr(random.randrange(256)) for i in range(16)]
112
113 bytes = ''.join(chr(ord(c) ^ ctokens[i]) for i,c in enumerate(bytes))
114 return str(uuid.UUID(bytes=bytes, version=4))
115