<code>
try
:
import _hashlib
new
= __hash_new
__get_hash = __get_openssl_constructor
algorithms_available = algorithms_available.union(
_hashlib.openssl_md_meth_names)
except ImportError:
new
= __py_new
__get_hash = __get_builtin_constructor
for
__func_name in __always_supported:
#
try
them all, some may not work due to the OpenSSL
# version not supporting that algorithm.
try
:
globals()[__func_name] = __get_hash(__func_name)
except ValueError:
import logging
logging.exception(
'code for hash %s was not found.'
, __func_name)
try
:
# OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC
and
SHA
from _hashlib import pbkdf2_hmac
except ImportError:
import binascii
import struct
_trans_5C = b
""
.join(
chr
(x ^ 0x5C)
for
x in range(256))
_trans_36 = b
""
.join(
chr
(x ^ 0x36)
for
x in range(256))
def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None):
""
"Password based key derivation
function
2 (PKCS #5 v2.0)
This Python implementations based on the hmac module about
as
fast
as
OpenSSL's PKCS5_PBKDF2_HMAC
for
short passwords
and
much faster
for
long passwords.
""
"
if
not isinstance(hash_name, str):
raise TypeError(hash_name)
if
not isinstance(password, (bytes, bytearray)):
password = bytes(buffer(password))
if
not isinstance(salt, (bytes, bytearray)):
salt = bytes(buffer(salt))
# Fast inline HMAC implementation
inner =
new
(hash_name)
outer =
new
(hash_name)
blocksize = getattr(inner,
'block_size'
, 64)
if
len(password) > blocksize:
password =
new
(hash_name, password).digest()
password = password + b
'\x00'
* (blocksize - len(password))
inner.update(password.translate(_trans_36))
outer.update(password.translate(_trans_5C))
def prf(msg, inner=inner, outer=outer):
# PBKDF2_HMAC uses the password
as
key. We can re-
use
the same
# digest objects
and
just update copies to skip initialization.
icpy = inner.
copy
()
ocpy = outer.
copy
()
icpy.update(msg)
ocpy.update(icpy.digest())
return
ocpy.digest()
if
iterations < 1:
raise ValueError(iterations)
if
dklen is None:
dklen = outer.digest_size
if
dklen < 1:
raise ValueError(dklen)
hex_format_string =
"%%0%ix"
% (
new
(hash_name).digest_size * 2)
dkey = b
''
loop = 1
while
len(dkey) < dklen:
prev = prf(salt + struct.pack(b
'>I'
, loop))
rkey = int(binascii.hexlify(prev), 16)
for
i in xrange(iterations - 1):
prev = prf(prev)
rkey ^= int(binascii.hexlify(prev), 16)
loop += 1
dkey += binascii.unhexlify(hex_format_string % rkey)
return
dkey[:dklen]
# Cleanup locals()
del __always_supported, __func_name, __get_hash
del __py_new, __hash_new, __get_openssl_constructor
</code>