Skip to content

passlib.hash.bcrypt_sha256 - BCrypt+SHA256

Note

Added in 1.6.2:

BCrypt was developed to replace md5_crypt for BSD systems. It uses a modified version of the Blowfish stream cipher. It does, however, truncate passwords to 72 bytes, and some other minor quirks (see BCrypt Password Truncation for details). This class works around that issue by first running the password through HMAC-SHA2-256. This class can be used directly as follows:

from passlib.hash import bcrypt_sha256

# generate new salt, hash password
h = bcrypt_sha256.hash("password")
print(h)
# > '$bcrypt-sha256$v=2,t=2b,r=12$n79VH.0Q2TMWmt3Oqt9uku$Kq4Noyk3094Y2QlB8NdRT8SvGiI4ft2'

# the same, but with an explicit number of rounds
print(bcrypt_sha256.using(rounds=13).hash("password"))
# > '$bcrypt-sha256$v=2,t=2b,r=13$AmytCA45b12VeVg0YdDT3.$IZTbbJKgJlD5IJoCWhuDUqYjnJwNPlO'

# verify password
print(bcrypt_sha256.verify("password", h))
# > True
print(bcrypt_sha256.verify("wrong", h))
# > False

Note

It is strongly recommended that you install bcrypt when using this hash. See passlib.hash.bcrypt for more details.

Interface

bcrypt_sha256

bcrypt_sha256(version=None, **kwds)

This class implements a composition of BCrypt + HMAC_SHA256, and follows the :ref:password-hash-api.

It supports a fixed-length salt, and a variable number of rounds.

The :meth:~passlib.ifc.PasswordHash.hash and :meth:~passlib.ifc.PasswordHash.genconfig methods accept all the same optional keywords as the base :class:bcrypt hash.

.. versionadded:: 1.6.2

.. versionchanged:: 1.7

Now defaults to ``"2b"`` bcrypt variant; though supports older hashes
generated using the ``"2a"`` bcrypt variant.

.. versionchanged:: 1.7.3

For increased security, updated to use HMAC-SHA256 instead of plain SHA256.
Now only supports the ``"2b"`` bcrypt variant.  Hash format updated to "v=2".

encrypt classmethod

encrypt(*args, **kwds)

Legacy alias for :meth:hash.

.. deprecated:: 1.7 This method was renamed to :meth:!hash in version 1.7. This alias will be removed in version 2.0, and should only be used for compatibility with Passlib 1.3 - 1.6.

parsehash classmethod

parsehash(hash, checksum=True, sanitize=False)

[experimental method] parse hash into dictionary of settings.

this essentially acts as the inverse of :meth:hash: for most cases, if hash = cls.hash(secret, **opts), then cls.parsehash(hash) will return a dict matching the original options (with the extra keyword checksum).

this method may not work correctly for all hashes, and may not be available on some few. its interface may change in future releases, if it's kept around at all.

Parameters:

  • hash –

    hash to parse

  • checksum –

    include checksum keyword? (defaults to True)

  • sanitize –

    mask data for sensitive fields? (defaults to False)

bitsize classmethod

bitsize(rounds=None, vary_rounds=0.1, **kwds)

[experimental method] return info about bitsizes of hash

default_salt_size

default_salt_size()

default salt size (defaults to max_salt_size)

default_salt_chars

default_salt_chars()

charset used to generate new salt strings (defaults to salt_chars)

get_backend classmethod

get_backend()

Return name of currently active backend. if no backend has been loaded, loads and returns name of default backend.

Returns:

  • –

    name of active backend

Raises:

  • passlib.exc.MissingBackendError –

    if no backends are available.

has_backend classmethod

has_backend(name='any')

Check if support is currently available for specified backend.

Parameters:

  • name –

    name of backend to check for. can be any string accepted by :meth:set_backend.

Returns:

  • –
    • True if backend is available.
    • False if it's available / can't be loaded.
    • None if it's present, but won't load due to a security issue.

Raises:

  • ValueError –

    if backend name is unknown

set_backend classmethod

set_backend(name='any', dryrun=False)

Load specified backend.

Parameters:

  • name –

    name of backend to load, can be any of the following:

    • "any" -- use current backend if one is loaded, otherwise load the first available backend.

    • "default" -- use the first available backend.

    • any string in :attr:backends, loads specified backend.

  • dryrun –

    If True, this perform all setup actions except switching over to the new backend. (this flag is used to implement :meth:has_backend).

    .. versionadded:: 1.7

Raises:

  • ValueError –

    If backend name is unknown.

  • passlib.exc.MissingBackendError –

    If specific backend is missing; or in the case of "any" / "default", if no backends are available.

  • passlib.exc.PasslibSecurityError –

    If "any" or "default" was specified, but the only backend available has a PasslibSecurityError.

normhash classmethod

normhash(hash)

helper to normalize hash, correcting any bcrypt padding bits

Format

Bcrypt-SHA256 is compatible with the modular-crypt-format, and uses $bcrypt-sha256$ as the identifying prefix for all it's strings. An example hash (of password) is:

$bcrypt-sha256$v=2,t=2b,r=12$n79VH.0Q2TMWmt3Oqt9uku$Kq4Noyk3094Y2QlB8NdRT8SvGiI4ft2

Version 1 of this format had the format $bcrypt-sha256${type},{rounds}${salt}${digest}. Passlib 1.7.3 introduced version 2 of this format, which changed the algorithm slightly (see below), and adjusted the format to indicate a version: $bcrypt-sha256$v=2,t={type},r={rounds}${salt}${digest}, where:

  • {type} is the BCrypt variant in use (always 2b under version 2; though 2a was allowed under version 1).
  • {rounds} is a cost parameter, encoded as decimal integer, which determines the number of iterations used via {iterations}=2**{rounds} (rounds is 12 in the example).
  • {salt} is a 22 character salt string, using the characters in the regexp range [./A-Za-z0-9] (n79VH.0Q2TMWmt3Oqt9uku in the example).
  • {digest} is a 31 character digest, using the same characters as the salt (Kq4Noyk3094Y2QlB8NdRT8SvGiI4ft2 in the example).

Algorithm

The algorithm this hash uses is as follows:

  • first the password is encoded to UTF-8 if not already encoded.

  • the next step is to hash the password before handing it off to bcrypt:

    • Under version 2 of this algorithm (the default as of passlib 1.7.3), the password is run through HMAC-SHA2-256, with the HMAC key set to the bcrypt salt (encoded as a 22 character ascii salt string).

    • Under the older version 1 of this algorithm, the password was instead run through plain SHA2-256.

    In either case, this generates a 32 byte digest.

  • this hash is then encoded using base64, resulting in a 44-byte result (including the trailing padding =). For the example "password" and the salt "n79VH.0Q2TMWmt3Oqt9uku", the output from this stage would be b"7CwRr5rxo2JZcVmSDAi/2JPTkvkAdNy20Cz2LwYC0fw=" (for version 2).

  • this base64 string is then passed on to the underlying bcrypt algorithm as the new password to be hashed. See passlib.hash.bcrypt for details on it's operation. For the example in the prior line, the resulting bcrypt digest component would be "Kq4Noyk3094Y2QlB8NdRT8SvGiI4ft2".