def pbkdf2_hmac(digest, secret, salt, rounds, keylen=None): """pkcs#5 password-based key derivation v2.0 using HMAC + arbitrary digest. :arg digest: digest name or constructor. :arg secret: passphrase to use to generate key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :arg salt: salt string to use when generating key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :param rounds: number of rounds to use to generate key. :arg keylen: number of bytes to generate. if omitted / ``None``, will use digest's native output size. :returns: raw bytes of generated key .. versionchanged:: 1.7 This function will use the first available of the following backends: * `fastpbk2 <https://pypi.python.org/pypi/fastpbkdf2>`_ * :func:`hashlib.pbkdf2_hmac` (only available in py2 >= 2.7.8, and py3 >= 3.4) * builtin pure-python backend See :data:`passlib.crypto.digest.PBKDF2_BACKENDS` to determine which backend(s) are in use. """ # validate secret & salt secret = to_bytes(secret, param="secret") salt = to_bytes(salt, param="salt") # resolve digest digest_info = lookup_hash(digest) digest_size = digest_info.digest_size # validate rounds if not isinstance(rounds, int_types): raise exc.ExpectedTypeError(rounds, "int", "rounds") if rounds < 1: raise ValueError("rounds must be at least 1") # validate keylen if keylen is None: keylen = digest_size elif not isinstance(keylen, int_types): raise exc.ExpectedTypeError(keylen, "int or None", "keylen") elif keylen < 1: # XXX: could allow keylen=0, but want to be compat w/ stdlib raise ValueError("keylen must be at least 1") # find smallest block count s.t. keylen <= block_count * digest_size; # make sure block count won't overflow (per pbkdf2 spec) # this corresponds to throwing error if keylen > digest_size * MAX_UINT32 # NOTE: stdlib will throw error at lower bound (keylen > MAX_SINT32) # NOTE: have do this before other backends checked, since fastpbkdf2 raises wrong error # (InvocationError, not OverflowError) block_count = (keylen + digest_size - 1) // digest_size if block_count > MAX_UINT32: raise OverflowError("keylen too long for digest") # # check for various high-speed backends # # ~3x faster than pure-python backend # NOTE: have to do this after above guards since fastpbkdf2 lacks bounds checks. if digest_info.supported_by_fastpbkdf2: return _fast_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen) # ~1.4x faster than pure-python backend # NOTE: have to do this after fastpbkdf2 since hashlib-ssl is slower, # will support larger number of hashes. if digest_info.supported_by_hashlib_pbkdf2: return _stdlib_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen) # # otherwise use our own implementation # # generated keyed hmac keyed_hmac = compile_hmac(digest, secret) # get helper to calculate pbkdf2 inner loop efficiently calc_block = _get_pbkdf2_looper(digest_size) # assemble & return result return join_bytes( calc_block(keyed_hmac, keyed_hmac(salt + _pack_uint32(i)), rounds) for i in irange(1, block_count + 1))[:keylen]
def pbkdf2(secret, salt, rounds, keylen=None, prf="hmac-sha1"): """pkcs#5 password-based key derivation v2.0 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate. if set to ``None``, will use digest size of selected prf. :param prf: psuedo-random family to use for key strengthening. this can be any string or callable accepted by :func:`get_prf`. this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in the PBKDF2 specification) :returns: raw bytes of generated key """ # validate secret & salt if not isinstance(secret, bytes): raise ExpectedTypeError(secret, "bytes", "secret") if not isinstance(salt, bytes): raise ExpectedTypeError(salt, "bytes", "salt") # validate rounds if not isinstance(rounds, int_types): raise ExpectedTypeError(rounds, "int", "rounds") if rounds < 1: raise ValueError("rounds must be at least 1") # validate keylen if keylen is not None: if not isinstance(keylen, int_types): raise ExpectedTypeError(keylen, "int or None", "keylen") elif keylen < 0: raise ValueError("keylen must be at least 0") # special case for m2crypto + hmac-sha1 if prf == "hmac-sha1" and _EVP: if keylen is None: keylen = 20 # NOTE: doing check here, because M2crypto won't take 'long' instances # (which this is when running under 32bit) if keylen > MAX_HMAC_SHA1_KEYLEN: raise ValueError("key length too long for digest") # NOTE: as of 2012-4-4, m2crypto has buffer overflow issue # which may cause segfaults if keylen > 32 (EVP_MAX_KEY_LENGTH). # therefore we're avoiding m2crypto for large keys until that's fixed. # see https://bugzilla.osafoundation.org/show_bug.cgi?id=13052 if keylen < 32: return _EVP.pbkdf2(secret, salt, rounds, keylen) # resolve prf prf_func, digest_size = get_prf(prf) if keylen is None: keylen = digest_size # figure out how many blocks we'll need block_count = (keylen+digest_size-1)//digest_size if block_count >= MAX_BLOCKS: raise ValueError("key length too long for digest") # build up result from blocks def gen(): for i in irange(block_count): digest = prf_func(secret, salt + pack(">L", i+1)) accum = bytes_to_int(digest) for _ in irange(rounds-1): digest = prf_func(secret, digest) accum ^= bytes_to_int(digest) yield int_to_bytes(accum, digest_size) return join_bytes(gen())[:keylen]
def pbkdf2(secret, salt, rounds, keylen=None, prf="hmac-sha1"): """pkcs#5 password-based key derivation v2.0 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate. if set to ``None``, will use digest size of selected prf. :param prf: psuedo-random family to use for key strengthening. this can be any string or callable accepted by :func:`get_prf`. this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in the PBKDF2 specification) :returns: raw bytes of generated key """ # validate secret & salt if not isinstance(secret, bytes): raise ExpectedTypeError(secret, "bytes", "secret") if not isinstance(salt, bytes): raise ExpectedTypeError(salt, "bytes", "salt") # validate rounds if not isinstance(rounds, int_types): raise ExpectedTypeError(rounds, "int", "rounds") if rounds < 1: raise ValueError("rounds must be at least 1") # generated keyed prf helper keyed_prf, digest_size = get_keyed_prf(prf, secret) # validate keylen if keylen is None: keylen = digest_size elif not isinstance(keylen, int_types): raise ExpectedTypeError(keylen, "int or None", "keylen") elif keylen < 0: raise ValueError("keylen must be at least 0") # m2crypto's pbkdf2-hmac-sha1 is faster than ours, so use it if available. # NOTE: as of 2012-4-4, m2crypto has buffer overflow issue which frequently # causes segfaults if keylen > 32 (EVP_MAX_KEY_LENGTH). # therefore we're avoiding m2crypto for large keys until that's fixed. # (https://bugzilla.osafoundation.org/show_bug.cgi?id=13052) if prf == "hmac-sha1" and _EVP and keylen < 32: return _EVP.pbkdf2(secret, salt, rounds, keylen) # work out min block count s.t. keylen <= block_count * digest_size block_count = (keylen + digest_size - 1) // digest_size if block_count >= _MAX_BLOCKS: raise ValueError("keylen too long for digest") # build up result from blocks def gen(): for i in irange(block_count): digest = keyed_prf(salt + pack(">L", i + 1)) accum = bytes_to_int(digest) # speed-critical loop of pbkdf2 # NOTE: currently converting digests to integers since that XORs faster. for _ in irange(rounds - 1): digest = keyed_prf(digest) accum ^= bytes_to_int(digest) yield int_to_bytes(accum, digest_size) return join_bytes(gen())[:keylen]
def pbkdf2_hmac(digest, secret, salt, rounds, keylen=None): """pkcs#5 password-based key derivation v2.0 using HMAC + arbitrary digest. :arg digest: digest name or constructor. :arg secret: passphrase to use to generate key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :arg salt: salt string to use when generating key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :param rounds: number of rounds to use to generate key. :arg keylen: number of bytes to generate. if omitted / ``None``, will use digest's native output size. :returns: raw bytes of generated key .. versionchanged:: 1.7 This function will use the first available of the following backends: * `fastpbk2 <https://pypi.python.org/pypi/fastpbkdf2>`_ * :func:`hashlib.pbkdf2_hmac` (only available in py2 >= 2.7.8, and py3 >= 3.4) * builtin pure-python backend See :data:`passlib.crypto.digest.PBKDF2_BACKENDS` to determine which backend(s) are in use. """ # validate secret & salt secret = to_bytes(secret, param="secret") salt = to_bytes(salt, param="salt") # resolve digest digest_info = lookup_hash(digest) digest_size = digest_info.digest_size # validate rounds if not isinstance(rounds, int_types): raise exc.ExpectedTypeError(rounds, "int", "rounds") if rounds < 1: raise ValueError("rounds must be at least 1") # validate keylen if keylen is None: keylen = digest_size elif not isinstance(keylen, int_types): raise exc.ExpectedTypeError(keylen, "int or None", "keylen") elif keylen < 1: # XXX: could allow keylen=0, but want to be compat w/ stdlib raise ValueError("keylen must be at least 1") # find smallest block count s.t. keylen <= block_count * digest_size; # make sure block count won't overflow (per pbkdf2 spec) # this corresponds to throwing error if keylen > digest_size * MAX_UINT32 # NOTE: stdlib will throw error at lower bound (keylen > MAX_SINT32) # NOTE: have do this before other backends checked, since fastpbkdf2 raises wrong error # (InvocationError, not OverflowError) block_count = (keylen + digest_size - 1) // digest_size if block_count > MAX_UINT32: raise OverflowError("keylen too long for digest") # # check for various high-speed backends # # ~3x faster than pure-python backend # NOTE: have to do this after above guards since fastpbkdf2 lacks bounds checks. if digest_info.supported_by_fastpbkdf2: return _fast_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen) # ~1.4x faster than pure-python backend # NOTE: have to do this after fastpbkdf2 since hashlib-ssl is slower, # will support larger number of hashes. if digest_info.supported_by_hashlib_pbkdf2: return _stdlib_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen) # # otherwise use our own implementation # # generated keyed hmac keyed_hmac = compile_hmac(digest, secret) # get helper to calculate pbkdf2 inner loop efficiently calc_block = _get_pbkdf2_looper(digest_size) # assemble & return result return join_bytes( calc_block(keyed_hmac, keyed_hmac(salt + _pack_uint32(i)), rounds) for i in irange(1, block_count + 1) )[:keylen]
def pbkdf2(secret, salt, rounds, keylen=None, prf="hmac-sha1"): """pkcs#5 password-based key derivation v2.0 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate. if set to ``None``, will use digest size of selected prf. :param prf: psuedo-random family to use for key strengthening. this can be any string or callable accepted by :func:`get_prf`. this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in the PBKDF2 specification) :returns: raw bytes of generated key """ # validate secret & salt if not isinstance(secret, bytes): raise ExpectedTypeError(secret, "bytes", "secret") if not isinstance(salt, bytes): raise ExpectedTypeError(salt, "bytes", "salt") # validate rounds if not isinstance(rounds, int_types): raise ExpectedTypeError(rounds, "int", "rounds") if rounds < 1: raise ValueError("rounds must be at least 1") # generated keyed prf helper keyed_prf, digest_size = get_keyed_prf(prf, secret) # validate keylen if keylen is None: keylen = digest_size elif not isinstance(keylen, int_types): raise ExpectedTypeError(keylen, "int or None", "keylen") elif keylen < 0: raise ValueError("keylen must be at least 0") # m2crypto's pbkdf2-hmac-sha1 is faster than ours, so use it if available. # NOTE: as of 2012-4-4, m2crypto has buffer overflow issue which frequently # causes segfaults if keylen > 32 (EVP_MAX_KEY_LENGTH). # therefore we're avoiding m2crypto for large keys until that's fixed. # (https://bugzilla.osafoundation.org/show_bug.cgi?id=13052) if prf == "hmac-sha1" and _EVP and keylen < 32: return _EVP.pbkdf2(secret, salt, rounds, keylen) # work out min block count s.t. keylen <= block_count * digest_size block_count = (keylen + digest_size - 1) // digest_size if block_count >= _MAX_BLOCKS: raise ValueError("keylen too long for digest") # build up result from blocks def gen(): for i in irange(block_count): digest = keyed_prf(salt + pack(">L", i+1)) accum = bytes_to_int(digest) # speed-critical loop of pbkdf2 # NOTE: currently converting digests to integers since that XORs faster. for _ in irange(rounds-1): digest = keyed_prf(digest) accum ^= bytes_to_int(digest) yield int_to_bytes(accum, digest_size) return join_bytes(gen())[:keylen]