Skip to content

passlib.hash.scrypt - SCrypt

This is a custom hash scheme provided by Passlib which allows storing password hashes generated using the SCrypt 1 key derivation function, and is designed as the of a new generation of "memory hard" functions.

Warning

Be careful when using this algorithm, as the memory and CPU requirements needed to achieve adequate security are generally higher than acceptable for heavily used production systems 2. This is because (unlike many password hashes), increasing the rounds value of scrypt will increase the memory required as well as the time.

Unless you know what you're doing, You probably want argon2 instead.

This class can be used directly as follows:

from passlib.hash import scrypt

# generate new salt, hash password
h = scrypt.hash("password")
print(h)
# > '$scrypt$ln=16,r=8,p=1$aM15713r3Xsvxbi31lqr1Q$nFNh2CVHVjNldFVKDHDlm4CbdRSCdEBsjjJxD+iCs5E'

# the same, but with an explicit number of rounds
hashed = scrypt.using(rounds=8).hash("password")
print(hashed)
# > '$scrypt$ln=8,r=8,p=1$WKs1xljLudd6z9kbY0wpJQ$yCR4iDZYDKv+iEJj6yHY0lv/epnfB6f/w1EbXrsJOuQ'

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

Note

It is strongly recommended that you install scrypt when using this hash.

Tip

the generic PasswordHash usage examples

Interface

scrypt

scrypt(block_size=None, **kwds)

This class implements an SCrypt-based password [#scrypt-home]_ hash, and follows the :ref:password-hash-api.

It supports a variable-length salt, a variable number of rounds, as well as some custom tuning parameters unique to scrypt (see below).

The :meth:~passlib.ifc.PasswordHash.using method accepts the following optional keywords:

Parameters:

  • salt (str) –

    Optional salt string. If specified, the length must be between 0-1024 bytes. If not specified, one will be auto-generated (this is recommended).

  • salt_size (int) –

    Optional number of bytes to use when autogenerating new salts. Defaults to 16 bytes, but can be any value between 0 and 1024.

  • rounds (int) –

    Optional number of rounds to use. Defaults to 16, but must be within range(1,32).

    .. warning::

    Unlike many hash algorithms, increasing the rounds value
    will increase both the time *and memory* required to hash a password.
    
  • block_size (int, default: None ) –

    Optional block size to pass to scrypt hash function (the r parameter). Useful for tuning scrypt to optimal performance for your CPU architecture. Defaults to 8.

  • parallelism (int) –

    Optional parallelism to pass to scrypt hash function (the p parameter). Defaults to 1.

  • relaxed (bool) –

    By default, providing an invalid value for one of the other keywords will result in a :exc:ValueError. If relaxed=True, and the error can be corrected, a :exc:~passlib.exc.PasslibHashWarning will be issued instead. Correctable errors include rounds that are too small or too large, and salt strings that are too long.

    .. note::

    The underlying scrypt hash function has a number of limitations
    on it's parameter values, which forbids certain combinations of settings.
    The requirements are:
    
    * ``linear_rounds = 2**<some positive integer>``
    * ``linear_rounds < 2**(16 * block_size)``
    * ``block_size * parallelism <= 2**30-1``
    

    .. todo::

    This class currently does not support configuring default values
    for ``block_size`` or ``parallelism`` via a :class:`~passlib.context.CryptContext`
    configuration.
    

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)

Scrypt Backends

This class will use the first available of two possible backends:

  1. Python stdlib's hashlib.scrypt method (only present for Python 3.6+ and OpenSSL 1.1+)
  2. The C-accelerated scrypt package, if installed.
  3. A pure-python implementation of SCrypt, built into Passlib.

Warning

If hashlib.scrypt is not present on your system, it is strongly recommended to install the external scrypt package. The pure-python backend is intended as a reference and last-resort implementation only; it is 10-100x too slow to be usable in production at a secure rounds cost.

Warning

Changed in 1.7.2: Added support for using stdlib's hashlib.scrypt

Format & Algorithm

This Scrypt hash format is compatible with the PHC Format and modular-crypt-format, and uses $scrypt$ as the identifying prefix for all its strings. An example hash (of password) is:

$scrypt$ln=16,r=8,p=1$aM15713r3Xsvxbi31lqr1Q$nFNh2CVHVjNldFVKDHDlm4CbdRSCdEBsjjJxD+iCs5E

This string has the format $scrypt$ln={logN},r={R},p={P}${salt}${checksum}, where:

  • {logN} is the exponent for calculating SCRYPT's cost parameter (N), encoded as a decimal digit, (logN is 16 in the example, corresponding to n = 2**16 = 65536).

  • {R} is the value of SCRYPT's block size parameter (r), encoded as a decimal digit, (r is 8 in the example).

  • {P} is the value of SCRYPT's parallel count parameter (p), encoded as a decimal digit, (p is 1 in the example).

  • {salt} - this base64 encoded salt bytes passed into the SCRYPT function (aM15713r3Xsvxbi31lqr1Q in the example).

  • {checksum} - this is the base64 encoded derived key bytes returned from the SCRYPT function. This hash currently always uses 32 bytes, resulting in a 43-character checksum. (nFNh2CVHVjNldFVKDHDlm4CbdRSCdEBsjjJxD+iCs5E in the example).

All byte strings are encoded using the standard base64 encoding, but without any trailing padding ("=") chars. The password is encoded into UTF-8 if not already encoded, and run throught the SCRYPT function; along with the salt, and the values of n, r, and p. The first 32 bytes of the returned result are encoded as the checksum.

See http://www.tarsnap.com/scrypt.html for the canonical description of the scrypt kdf.

Security Issues

SCrypt is the first in a class of "memory-hard" key derivation functions. Initially, it looked very promising as a replacement for BCrypt, PBKDF2, and SHA512-Crypt. However, the fact that its N parameter controls both time and memory cost means the two cannot be varied completely independantly. This eventually proved to be problematic, as N values required for even BCrypt levels of security resulting in memory requirements that were unacceptable on most production systems.

Tip

passlib.hash.argon2, a next generation memory-hard KDF designed as the successor to SCrypt.