Merge pull request #136 from michele-comitini/speed_triks1
optimizations. Switch to PyCrypto support in pbkdf2 when possible.
This commit is contained in:
+26
-9
@@ -40,15 +40,32 @@
|
|||||||
:copyright: (c) Copyright 2011 by Armin Ronacher.
|
:copyright: (c) Copyright 2011 by Armin Ronacher.
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
import hmac
|
#import hmac
|
||||||
import hashlib
|
#import hashlib
|
||||||
|
try:
|
||||||
|
# Use PyCrypto (if available).
|
||||||
|
from Crypto.Hash import HMAC as hmac, SHA as sha1
|
||||||
|
except ImportError:
|
||||||
|
# PyCrypto not available. Use the Python standard library.
|
||||||
|
import hmac
|
||||||
|
try:
|
||||||
|
from hashlib import sha1
|
||||||
|
except ImportError:
|
||||||
|
# hashlib not available. Use the old sha module.
|
||||||
|
import sha as sha1
|
||||||
|
|
||||||
from struct import Struct
|
from struct import Struct
|
||||||
from operator import xor
|
from operator import xor
|
||||||
from itertools import izip, starmap
|
from itertools import izip, starmap
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
_pack_int = Struct('>I').pack
|
_pack_int = Struct('>I').pack
|
||||||
|
|
||||||
|
try:
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
except ImportError:
|
||||||
|
def strxor(a, b):
|
||||||
|
return ''.join(chr(xor(ord(x), ord(y))) for x,y in izip(a, b))
|
||||||
|
|
||||||
def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None):
|
def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None):
|
||||||
"""Like :func:`pbkdf2_bin` but returns a hex encoded string."""
|
"""Like :func:`pbkdf2_bin` but returns a hex encoded string."""
|
||||||
@@ -61,20 +78,20 @@ def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None):
|
|||||||
key of `keylen` bytes. By default SHA-1 is used as hash function,
|
key of `keylen` bytes. By default SHA-1 is used as hash function,
|
||||||
a different hashlib `hashfunc` can be provided.
|
a different hashlib `hashfunc` can be provided.
|
||||||
"""
|
"""
|
||||||
hashfunc = hashfunc or hashlib.sha1
|
hashfunc = hashfunc or sha1
|
||||||
mac = hmac.new(data, None, hashfunc)
|
mac = hmac.new(data, None, hashfunc)
|
||||||
def _pseudorandom(x, mac=mac):
|
def _pseudorandom(x, mac=mac):
|
||||||
h = mac.copy()
|
h = mac.copy()
|
||||||
h.update(x)
|
h.update(x)
|
||||||
return map(ord, h.digest())
|
return h.digest()
|
||||||
buf = []
|
buf = deque()
|
||||||
for block in xrange(1, -(-keylen // mac.digest_size) + 1):
|
for block in xrange(1, -(-keylen // mac.digest_size) + 1):
|
||||||
rv = u = _pseudorandom(salt + _pack_int(block))
|
rv = u = _pseudorandom(salt + _pack_int(block))
|
||||||
for i in xrange(iterations - 1):
|
for i in xrange(iterations - 1):
|
||||||
u = _pseudorandom(''.join(map(chr, u)))
|
u = _pseudorandom(u)
|
||||||
rv = starmap(xor, izip(rv, u))
|
rv = strxor(rv, u)
|
||||||
buf.extend(rv)
|
buf.extend(rv)
|
||||||
return ''.join(map(chr, buf))[:keylen]
|
return ''.join(buf)[:keylen]
|
||||||
|
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1):
|
|||||||
# if not relative and not from applications:
|
# if not relative and not from applications:
|
||||||
if hasattr(current, 'request') \
|
if hasattr(current, 'request') \
|
||||||
and level <= 0 \
|
and level <= 0 \
|
||||||
and not name.split('.')[0] in INVALID_MODULES \
|
and not name.partition('.')[0] in INVALID_MODULES \
|
||||||
and isinstance(globals, dict):
|
and isinstance(globals, dict):
|
||||||
import_tb = None
|
import_tb = None
|
||||||
try:
|
try:
|
||||||
|
|||||||
+24
-15
@@ -24,6 +24,8 @@ import socket
|
|||||||
import base64
|
import base64
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
|
_struct_2_long_long = struct.Struct('=QQ')
|
||||||
|
|
||||||
python_version = sys.version_info[0]
|
python_version = sys.version_info[0]
|
||||||
|
|
||||||
if python_version == 2:
|
if python_version == 2:
|
||||||
@@ -31,6 +33,15 @@ if python_version == 2:
|
|||||||
else:
|
else:
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
|
try:
|
||||||
|
from Crypto.Hash import MD5 as md5, \
|
||||||
|
SHA as sha1, \
|
||||||
|
SHA224 as sha224, \
|
||||||
|
SHA256 as sha256, \
|
||||||
|
SHA384 as sha384, \
|
||||||
|
SHA512 as sha512
|
||||||
|
except ImportError:
|
||||||
|
from hashlib import md5, sha1, sha224, sha256, sha384, sha512
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
@@ -69,7 +80,7 @@ def compare(a, b):
|
|||||||
|
|
||||||
def md5_hash(text):
|
def md5_hash(text):
|
||||||
""" Generate a md5 hash with the given text """
|
""" Generate a md5 hash with the given text """
|
||||||
return hashlib.md5(text).hexdigest()
|
return md5(text).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def simple_hash(text, key='', salt='', digest_alg='md5'):
|
def simple_hash(text, key='', salt='', digest_alg='md5'):
|
||||||
@@ -102,17 +113,17 @@ def get_digest(value):
|
|||||||
return value
|
return value
|
||||||
value = value.lower()
|
value = value.lower()
|
||||||
if value == "md5":
|
if value == "md5":
|
||||||
return hashlib.md5
|
return md5
|
||||||
elif value == "sha1":
|
elif value == "sha1":
|
||||||
return hashlib.sha1
|
return sha1
|
||||||
elif value == "sha224":
|
elif value == "sha224":
|
||||||
return hashlib.sha224
|
return sha224
|
||||||
elif value == "sha256":
|
elif value == "sha256":
|
||||||
return hashlib.sha256
|
return sha256
|
||||||
elif value == "sha384":
|
elif value == "sha384":
|
||||||
return hashlib.sha384
|
return sha384
|
||||||
elif value == "sha512":
|
elif value == "sha512":
|
||||||
return hashlib.sha512
|
return sha512
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid digest algorithm: %s" % value)
|
raise ValueError("Invalid digest algorithm: %s" % value)
|
||||||
|
|
||||||
@@ -212,7 +223,7 @@ This is not specific to web2py; consider deploying on a different operating syst
|
|||||||
packed = ''.join(chr(x) for x in ctokens) # python 2
|
packed = ''.join(chr(x) for x in ctokens) # python 2
|
||||||
else:
|
else:
|
||||||
packed = bytes([]).join(bytes([x]) for x in ctokens) # python 3
|
packed = bytes([]).join(bytes([x]) for x in ctokens) # python 3
|
||||||
unpacked_ctokens = struct.unpack('=QQ', packed)
|
unpacked_ctokens = _struct_2_long_long.unpack(packed)
|
||||||
return unpacked_ctokens, have_urandom
|
return unpacked_ctokens, have_urandom
|
||||||
UNPACKED_CTOKENS, HAVE_URANDOM = initialize_urandom()
|
UNPACKED_CTOKENS, HAVE_URANDOM = initialize_urandom()
|
||||||
|
|
||||||
@@ -244,14 +255,12 @@ def web2py_uuid(ctokens=UNPACKED_CTOKENS):
|
|||||||
"""
|
"""
|
||||||
rand_longs = (random.getrandbits(64), random.getrandbits(64))
|
rand_longs = (random.getrandbits(64), random.getrandbits(64))
|
||||||
if HAVE_URANDOM:
|
if HAVE_URANDOM:
|
||||||
urand_longs = struct.unpack('=QQ', fast_urandom16())
|
urand_longs = _struct_2_long_long.unpack(fast_urandom16())
|
||||||
byte_s = struct.pack('=QQ',
|
byte_s = _struct_2_long_long.pack(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])
|
|
||||||
else:
|
else:
|
||||||
byte_s = struct.pack('=QQ',
|
byte_s = _struct_2_long_long.pack(rand_longs[0] ^ ctokens[0],
|
||||||
rand_longs[0] ^ ctokens[0],
|
rand_longs[1] ^ ctokens[1])
|
||||||
rand_longs[1] ^ ctokens[1])
|
|
||||||
return str(uuid.UUID(bytes=byte_s, version=4))
|
return str(uuid.UUID(bytes=byte_s, version=4))
|
||||||
|
|
||||||
REGEX_IPv4 = re.compile('(\d+)\.(\d+)\.(\d+)\.(\d+)')
|
REGEX_IPv4 = re.compile('(\d+)\.(\d+)\.(\d+)\.(\d+)')
|
||||||
|
|||||||
Reference in New Issue
Block a user