Python Scrypt Bindings
The `scrypt` library provides Python bindings for the scrypt key derivation function, which is designed to make brute-force attacks on password hashes more difficult by requiring more memory and CPU. It's commonly used for securely hashing passwords. The current version is 0.9.4, with minor releases occurring periodically to address bug fixes and build improvements.
Common errors
-
ModuleNotFoundError: No module named 'scrypt'
cause The `scrypt` package is not installed in your Python environment.fixRun `pip install scrypt` to install the library. -
TypeError: Expected bytes, got str
cause The `scrypt.hash()` or `scrypt.verify()` function received a string (`str`) where it expected bytes (`bytes`) for password or salt.fixEnsure that both your password and salt are `bytes` objects. Convert strings using `.encode('utf-8')` or by prefixing string literals with `b` (e.g., `b"password"`). -
error: command 'gcc' failed with exit status 1 (or similar C compiler error during installation)
cause The `scrypt` library is a C extension and requires a C compiler and development headers to be present on your system for installation.fixInstall the necessary build tools: - **Windows**: Install 'Build Tools for Visual Studio 20XX' from Microsoft (e.g., Visual C++ build tools 14.0 or greater). - **Debian/Ubuntu**: `sudo apt-get install build-essential python3-dev` - **Fedora/RHEL**: `sudo yum groupinstall 'Development Tools' && sudo yum install python3-devel` - **macOS**: `xcode-select --install` (Xcode Command Line Tools). -
scrypt.error: Invalid scrypt parameters (N, r, p)
cause The provided `N`, `r`, or `p` parameters are outside the valid range, or `N` is not a power of 2, or the combination leads to an impossible memory/CPU allocation.fixReview your `N`, `r`, and `p` values. `N` must be a power of 2 (e.g., 2048, 4096, 16384). `r` and `p` typically default to 8 and 1 respectively, and must be positive integers. Ensure they match the values used during hashing if verifying.
Warnings
- breaking Installing `scrypt` requires a C compiler and development headers for your system. On Windows, this means Visual C++ Build Tools; on Linux, `build-essential` (Debian/Ubuntu) or `Development Tools` (Fedora/RHEL); on macOS, Xcode Command Line Tools.
- gotcha The `scrypt.hash` and `scrypt.verify` functions expect `bytes` objects for password and salt inputs, not `str`.
- gotcha Choosing the right `N`, `r`, and `p` parameters is crucial. Incorrectly chosen high values can lead to excessive memory/CPU consumption, making your application vulnerable to denial-of-service attacks, while low values compromise security.
- gotcha The `scrypt` library does not automatically format hashes into a standard string format (e.g., `$s0$...`) that includes the salt and parameters. Users must manually store or encode these alongside the hash for later verification.
Install
-
pip install scrypt
Imports
- scrypt
import scrypt
- hash
from scrypt import scrypt_hash
from scrypt import hash
- verify
from scrypt import verify
Quickstart
import scrypt
import os
# --- Parameters for scrypt (N, r, p) ---
# N: CPU/Memory cost parameter (must be a power of 2, e.g., 2**14 = 16384)
# Higher N means more work, increasing security against brute-force attacks.
# r: Block size parameter
# p: Parallelization parameter
# Choosing these values appropriately is critical for security and performance.
# For production, recommended values are often N=2**14 to 2**20, r=8, p=1.
# Values too high can cause excessive memory/CPU usage, potentially leading to DoS.
N = 16384 # 2**14
r = 8
p = 1
password = b"my_super_secret_password"
# Generate a cryptographically secure random salt (at least 16 bytes)
salt = os.urandom(16)
try:
# 1. Hash the password
# The hash function returns bytes
hashed_password_bytes = scrypt.hash(password, salt, N, r, p)
print(f"Scrypt hash (hex): {hashed_password_bytes.hex()}")
# 2. Verify the password
# For verification, the original password, salt, and parameters (N, r, p)
# used during hashing must be provided.
is_valid = scrypt.verify(password, hashed_password_bytes, salt, N, r, p)
print(f"Password verification successful: {is_valid}")
# Example of a wrong password
wrong_password = b"wrong_password"
try:
scrypt.verify(wrong_password, hashed_password_bytes, salt, N, r, p)
print("Verification with wrong password succeeded (ERROR!)")
except scrypt.error:
print("Verification with wrong password failed (EXPECTED)")
except scrypt.error as e:
print(f"An scrypt error occurred: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# In a real application, you would store the salt and N, r, p parameters
# alongside the hash (e.g., as part of a standard scrypt format string like $s0$...)
# The 'scrypt' library does not provide this format string generation directly;
# you need to implement that logic yourself or use a higher-level library.