passlib.hash.sha1_crypt - SHA-1 Crypt¶
SHA1-Crypt is a hash algorithm introduced by NetBSD in 2004. It's based on a variation of the PBKDF1 algorithm, and supports a large salt and variable number of rounds.
Tip
password hash usage -- for examples of how to use this class via the common hash interface.
Interface¶
sha1_crypt
¶
sha1_crypt(rounds=None, **kwds)
This class implements the SHA1-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, an 8 character one will be autogenerated (this is recommended). If specified, it must be 0-64 characters, drawn from the regexp range
[./0-9A-Za-z]. -
salt_size(int) –Optional number of bytes to use when autogenerating new salts. Defaults to 8 bytes, but can be any value between 0 and 64.
-
rounds(int, default:None) –Optional number of rounds to use. Defaults to 480000, must be between 1 and 4294967295, inclusive.
-
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
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 sha1-crypt (NetBSD). - a pure python implementation of sha1-crypt built into Passlib.
You can see which backend is in use by calling the get_backend() method.
Format¶
An example hash (of password) is $sha1$40000$jtNX3nZ2$hBNaIXkt4wBI2o5rsi8KejSjNqIq.
An sha1-crypt hash string has the format $sha1${rounds}${salt}${checksum}, where:
-
$sha1$is the prefix used to identify sha1-crypt hashes, following the modular-crypt-format -
{rounds}is the decimal number of rounds to use (40000 in the example). -
{salt}is 0-64 characters drawn from[./0-9A-Za-z](jtNX3nZ2in the example). -
{checksum}is 28 characters drawn from the same set, encoding a 168-bit checksum. (hBNaIXkt4wBI2o5rsi8KejSjNqIq/in the example).
Algorithm¶
The checksum is calculated using a modified version of PBKDF1 1, replacing its use of the SHA1 message digest with HMAC-SHA1, (which does not suffer from the current vulnerabilities that SHA1 itself does, as well as providing some of the advancements made in PBKDF2).
-
first, the HMAC-SHA1 digest of
{salt}$sha1${rounds}is generated, using the password as the HMAC-SHA1 key. -
then, for
{rounds}-1iterations, the previous HMAC-SHA1 digest is fed back through HMAC-SHA1, again using the password as the HMAC-SHA1 key. -
the checksum is then rendered into hash-64 format using an ordering that roughly corresponds to big-endian encoding of 24-bit chunks (see
passlib.hash.sha1_crypt._chk_offsetsfor exact byte order).
Deviations¶
This implementation of sha1-crypt differs from the NetBSD implementation in a few ways:
- Default Rounds:
The NetBSD implementation randomly varies the actual number of rounds
when generating a new configuration string, in order to decrease
predictability. This feature is provided by Passlib to all hashes,
via the CryptContext class, and so it omitted
from this implementation.
- 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 in a hash have 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 sha1-crypt generate
and expect salts containing those characters.
- 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 known reference hashes.
In order to provide support for unicode strings,
Passlib will encode unicode passwords using utf-8
before running them through sha1-crypt. If a different
encoding is desired by an application, the password should be encoded
before handing it to Passlib.
References¶
- description of sha1-crypt algorithm - http://mail-index.netbsd.org/tech-userlevel/2004-05-29/0001.html
- NetBSD implementation of SHA1-Crypt - http://fxr.googlebit.com/source/lib/libcrypt/crypt-sha1.c?v=NETBSD-CURRENT
-
rfc defining PBKDF1 & PBKDF2 - http://tools.ietf.org/html/rfc2898 - ↩