yet faster web2py_uuid by caching urandom results

This commit is contained in:
mdipierro
2012-09-29 17:56:43 -05:00
parent 1a43e1671f
commit 60a043479c
2 changed files with 28 additions and 8 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.0.9 (2012-09-29 17:16:28) dev
Version 2.0.9 (2012-09-29 17:56:36) dev
+27 -7
View File
@@ -10,6 +10,7 @@ This file specifically includes utilities for security.
"""
import string
import threading
import struct
import hashlib
import hmac
@@ -110,6 +111,7 @@ def initialize_urandom():
random.seed(node_id + microseconds)
try:
os.urandom(1)
have_urandom = True
try:
# try to add process-specific entropy
frandom = open('/dev/urandom','wb')
@@ -121,13 +123,31 @@ def initialize_urandom():
# works anyway
pass
except NotImplementedError:
have_urandom = False
logger.warning(
"""Cryptographically secure session management is not possible on your system because
your system does not provide a cryptographically secure entropy source.
This is not specific to web2py; consider deploying on a different operating system.""")
return ctokens
CTOKENS = initialize_urandom()
UNPACKED_CTOKENS = struct.unpack('=QQ',string.join((chr(x) for x in CTOKENS),''))
unpacked_ctokens = struct.unpack('=QQ',string.join(
(chr(x) for x in ctokens),''))
return unpacked_ctokens, have_urandom
UNPACKED_CTOKENS, HAVE_URANDOM = initialize_urandom()
def fast_urandom16(urandom=[], locker = threading.RLock()):
"""
this is 4x faster than calling os.urandom(16) and prevents
the "too many files open" issue with concurrent access to os.urandom()
"""
try:
return urandom.pop()
except IndexError:
try:
locker.acquire()
ur = os.urandom(16*1024)
urandom += [ur[i:i+16] for i in xrange(16,1024*16,16)]
return ur[0:16]
finally:
locker.release()
def web2py_uuid(ctokens=UNPACKED_CTOKENS):
"""
@@ -139,12 +159,12 @@ def web2py_uuid(ctokens=UNPACKED_CTOKENS):
"""
rand_longs = struct.unpack('=QQ', bytes(bytearray(
random.randrange(256) for i in xrange(16))))
try:
urand_longs = struct.unpack('=QQ', os.urandom(16))
byte_s = struct.pack('=QQ',
if HAVE_URANDOM:
urand_longs = struct.unpack('=QQ', fast_urandom16())
byte_s = struct.pack('=QQ',
rand_longs[0]^urand_longs[0]^ctokens[0],
rand_longs[1]^urand_longs[1]^ctokens[1])
except NotImplementedError:
else:
byte_s = struct.pack('=QQ',
rand_longs[0]^ctokens[0],
rand_longs[1]^ctokens[1])