passlib.hash.sha256_crypt - SHA-256 Crypt¶
SHA-256 Crypt and SHA-512 Crypt were developed in 2008 by Ulrich Drepper 1,
designed as the successor to passlib.hash.md5_crypt.
They include fixes and advancements such as variable rounds, and use of NIST-approved cryptographic primitives.
The design involves repeated composition of the underlying digest algorithm,
using various arbitrary permutations of inputs.
SHA-512 / SHA-256 Crypt are currently the default password hash for many systems
(notably Linux), and have no known weaknesses.
SHA-256 Crypt is one of the four hashes Passlib recommends
for new applications.
This class can be used directly as follows:
from passlib.hash import sha256_crypt
# generate new salt, hash password
hash = sha256_crypt.hash("password")
print(hash)
# > '$5$rounds=80000$wnsT7Yr92oJoP28r$cKhJImk5mfuSKV9b3mumNzlbstFUplKtQXXMo4G6Ep5'
# same, but with explict number of rounds
hashed = sha256_crypt.using(rounds=12345).hash("password")
print(hashed)
# > '$5$rounds=12345$q3hvJE5mn5jKRsW.$BbbYTFiaImz9rTy03GGi.Jf9YY5bmxN0LU3p3uI1iUB'
# verify password
print(sha256_crypt.verify("password", hash))
# > True
print(sha256_crypt.verify("letmein", hash))
# > False
Tip
-
password hash usage-- for more usage examples -
sha512_crypt-- the companion 512-bit version of this hash.
Interface¶
sha256_crypt
¶
sha256_crypt(implicit_rounds=None, **kwds)
This class implements the SHA256-Crypt password hash, and follows the :ref:password-hash-api.
It supports a variable-length salt, and a variable number of rounds.
The :meth:~passlib.ifc.PasswordHash.using method accepts the following optional keywords:
Parameters:
-
salt(str) –Optional salt string. If not specified, one will be autogenerated (this is recommended). If specified, it must be 0-16 characters, drawn from the regexp range
[./0-9A-Za-z]. -
rounds(int) –Optional number of rounds to use. Defaults to 535000, must be between 1000 and 999999999, inclusive.
.. note:: per the official specification, when the rounds parameter is set to 5000, it may be omitted from the hash string.
-
relaxed(bool) –By default, providing an invalid value for one of the other keywords will result in a :exc:
ValueError. Ifrelaxed=True, and the error can be corrected, a :exc:~passlib.exc.PasslibHashWarningwill be issued instead. Correctable errors includeroundsthat are too small or too large, andsaltstrings that are too long... versionadded:: 1.6.. commented out, currently only supported by :meth:
hash, and not via :meth:using::type implicit_rounds: bool :param implicit_rounds: this is an internal option which generally doesn't need to be touched. this flag determines whether the hash should omit the rounds parameter when encoding it to a string; this is only permitted by the spec for rounds=5000, and the flag is ignored otherwise. the spec requires the two different encodings be preserved as they are, instead of normalizing them.
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_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:
-
–
Trueif backend is available.Falseif it's available / can't be loaded.Noneif 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.
Note
This class will use the first available of two possible backends:
- stdlib
crypt(), if the host OS supports SHA256-Crypt (most Linux systems). - a pure python implementation of SHA256-Crypt built into Passlib.
You can see which backend is in use by calling the get_backend() method.
Format & Algorithm¶
An example sha256-crypt hash (of the string password) is:
$5$rounds=80000$wnsT7Yr92oJoP28r$cKhJImk5mfuSKV9b3mumNzlbstFUplKtQXXMo4G6Ep5
An sha256-crypt hash string has the format $5$rounds={rounds}${salt}${checksum}, where:
-
$5$is the prefix used to identify sha256-crypt hashes, following the modular-crypt-format -
{rounds}is the decimal number of rounds to use (80000 in the example). -
{salt}is 0-16 characters drawn from[./0-9A-Za-z], providing a 96-bit salt (wnsT7Yr92oJoP28rin the example). -
{checksum}is 43 characters drawn from the same set, encoding a 256-bit checksum (cKhJImk5mfuSKV9b3mumNzlbstFUplKtQXXMo4G6Ep5in the example).
The official implementation allows omitting the rounds section when it's set to 5000,
resulting in an alternate hash format: $5${salt}${checksum}.
(Passlib supports this via the implicit_rounds constructor parameter).
The algorithm used by SHA256-Crypt is laid out in detail in the specification document linked to below 1.
Security Issues¶
-
The algorithm's initialization stage contains a loop which varies linearly with the square of the password size; and further loops which vary linearly with the password size * rounds.
-
This means an attacker could provide a maliciously large password at the login screen to attempt a DOS on a publically visible login. For example, a 32kib password would require hashing 1gib of data. Passlib mitigates this by limiting the maximum password size to 4k by default.
-
An attacker could also theoretically determine a password's size by observing the time taken on a successful login, and then attempting verification themselves to find the size password which has an equivalent delay. This has not been applied in practice, probably due to the fact that (for normal passwords < 64 bytes), the contribution of the password size to the overall time taken is below the observable noise level when evesdropping on the timings of successful logins for a single user.
-
Deviations¶
This implementation of sha256-crypt differs from the specification, and other implementations, in a few ways:
- Zero-Padded Rounds:
The specification does not specify how to deal with zero-padding within the rounds portion of the hash. No existing examples or test vectors have zero padding, and allowing it would result in multiple encodings for the same configuration / hash. To prevent this situation, Passlib will throw an error if the rounds parameter in a hash has leading zeros.
- Restricted salt string character set:
The underlying algorithm can unambiguously handle salt strings
which contain any possible byte value besides \x00 and $.
However, Passlib strictly limits salts to the
hash64 <passlib.utils.binary.HASH64_CHARS> character set,
as nearly all implementations of sha256-crypt generate
and expect salts containing those characters,
but may have unexpected behaviors for other character values.
- Unicode Policy:
The underlying algorithm takes in a password specified
as a series of non-null bytes, and does not specify what encoding
should be used; though a us-ascii compatible encoding
is implied by nearly all implementations of sha256-crypt
as well as all known reference hashes.
In order to provide support for unicode strings,
Passlib will encode unicode passwords using utf-8
before running them through sha256-crypt. If a different
encoding is desired by an application, the password should be encoded
before handing it to Passlib.
-
Ulrich Drepper's SHA-256/512-Crypt specification, reference implementation, and test vectors - sha-crypt specification ↩↩