yet faster web2py_uuid by caching urandom results
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.0.9 (2012-09-29 17:16:28) dev
|
Version 2.0.9 (2012-09-29 17:56:36) dev
|
||||||
|
|||||||
+26
-6
@@ -10,6 +10,7 @@ This file specifically includes utilities for security.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import string
|
import string
|
||||||
|
import threading
|
||||||
import struct
|
import struct
|
||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
@@ -110,6 +111,7 @@ def initialize_urandom():
|
|||||||
random.seed(node_id + microseconds)
|
random.seed(node_id + microseconds)
|
||||||
try:
|
try:
|
||||||
os.urandom(1)
|
os.urandom(1)
|
||||||
|
have_urandom = True
|
||||||
try:
|
try:
|
||||||
# try to add process-specific entropy
|
# try to add process-specific entropy
|
||||||
frandom = open('/dev/urandom','wb')
|
frandom = open('/dev/urandom','wb')
|
||||||
@@ -121,13 +123,31 @@ def initialize_urandom():
|
|||||||
# works anyway
|
# works anyway
|
||||||
pass
|
pass
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
|
have_urandom = False
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"""Cryptographically secure session management is not possible on your system because
|
"""Cryptographically secure session management is not possible on your system because
|
||||||
your system does not provide a cryptographically secure entropy source.
|
your system does not provide a cryptographically secure entropy source.
|
||||||
This is not specific to web2py; consider deploying on a different operating system.""")
|
This is not specific to web2py; consider deploying on a different operating system.""")
|
||||||
return ctokens
|
unpacked_ctokens = struct.unpack('=QQ',string.join(
|
||||||
CTOKENS = initialize_urandom()
|
(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):
|
def web2py_uuid(ctokens=UNPACKED_CTOKENS):
|
||||||
"""
|
"""
|
||||||
@@ -139,12 +159,12 @@ def web2py_uuid(ctokens=UNPACKED_CTOKENS):
|
|||||||
"""
|
"""
|
||||||
rand_longs = struct.unpack('=QQ', bytes(bytearray(
|
rand_longs = struct.unpack('=QQ', bytes(bytearray(
|
||||||
random.randrange(256) for i in xrange(16))))
|
random.randrange(256) for i in xrange(16))))
|
||||||
try:
|
if HAVE_URANDOM:
|
||||||
urand_longs = struct.unpack('=QQ', os.urandom(16))
|
urand_longs = struct.unpack('=QQ', fast_urandom16())
|
||||||
byte_s = struct.pack('=QQ',
|
byte_s = struct.pack('=QQ',
|
||||||
rand_longs[0]^urand_longs[0]^ctokens[0],
|
rand_longs[0]^urand_longs[0]^ctokens[0],
|
||||||
rand_longs[1]^urand_longs[1]^ctokens[1])
|
rand_longs[1]^urand_longs[1]^ctokens[1])
|
||||||
except NotImplementedError:
|
else:
|
||||||
byte_s = struct.pack('=QQ',
|
byte_s = struct.pack('=QQ',
|
||||||
rand_longs[0]^ctokens[0],
|
rand_longs[0]^ctokens[0],
|
||||||
rand_longs[1]^ctokens[1])
|
rand_longs[1]^ctokens[1])
|
||||||
|
|||||||
Reference in New Issue
Block a user