Argon2 password hashing algorithm for Python with secure defaults and multiple variants
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Python bindings for the Argon2 password hashing algorithm, winner of the Password Hashing Competition. Provides secure password hashing with industry-standard defaults, supporting all three Argon2 variants (Argon2i, Argon2d, Argon2id) with configurable memory usage, parallelism, and time costs.
pip install argon2-cffiimport argon2Common usage pattern:
from argon2 import PasswordHasherAccess to all public components:
from argon2 import (
PasswordHasher,
Type,
Parameters,
extract_parameters,
exceptions,
low_level,
profiles
)from argon2 import PasswordHasher
# Create a password hasher with secure defaults
ph = PasswordHasher()
# Hash a password
password = "supersecret"
hash = ph.hash(password)
print(hash) # $argon2id$v=19$m=65536,t=3,p=4$...
# Verify a password
try:
ph.verify(hash, password)
print("Password is correct!")
except argon2.exceptions.VerifyMismatchError:
print("Password is wrong!")
# Check if hash needs rehashing (due to changed parameters)
if ph.check_needs_rehash(hash):
new_hash = ph.hash(password)
# Update stored hash in databaseArgon2-CFFI provides a layered architecture for different use cases:
PasswordHasher): Simple, secure API with sensible defaults for typical password hashing needsThe library automatically handles salt generation, constant-time verification to prevent timing attacks, and parameter validation for the current platform.
High-level password hashing with the PasswordHasher class, providing secure defaults and convenient methods for common password operations including hashing, verification, and rehash detection.
class PasswordHasher:
def __init__(
self,
time_cost: int = DEFAULT_TIME_COST,
memory_cost: int = DEFAULT_MEMORY_COST,
parallelism: int = DEFAULT_PARALLELISM,
hash_len: int = DEFAULT_HASH_LENGTH,
salt_len: int = DEFAULT_RANDOM_SALT_LENGTH,
encoding: str = "utf-8",
type: Type = Type.ID,
): ...
def hash(self, password: str | bytes, *, salt: bytes | None = None) -> str: ...
def verify(self, hash: str | bytes, password: str | bytes) -> Literal[True]: ...
def check_needs_rehash(self, hash: str | bytes) -> bool: ...Direct access to Argon2 C library functions for advanced users who need fine-grained control over hashing parameters, raw hash outputs, or custom implementations.
def hash_secret(
secret: bytes,
salt: bytes,
time_cost: int,
memory_cost: int,
parallelism: int,
hash_len: int,
type: Type,
version: int = ARGON2_VERSION,
) -> bytes: ...
def verify_secret(hash: bytes, secret: bytes, type: Type) -> Literal[True]: ...Comprehensive exception hierarchy for different error conditions including verification failures, hashing errors, invalid parameters, and platform-specific limitations.
class Argon2Error(Exception): ...
class VerificationError(Argon2Error): ...
class VerifyMismatchError(VerificationError): ...
class HashingError(Argon2Error): ...
class InvalidHashError(ValueError): ...
class UnsupportedParametersError(ValueError): ...Predefined parameter configurations following RFC 9106 recommendations and utilities for parameter management, extraction, and platform validation.
class Parameters:
type: Type
version: int
salt_len: int
hash_len: int
time_cost: int
memory_cost: int
parallelism: int
def get_default_parameters() -> Parameters: ...
def extract_parameters(hash: str) -> Parameters: ...Deprecated functions maintained for backward compatibility with older code. Use PasswordHasher for new applications.
def hash_password(
password: bytes,
salt: bytes | None = None,
time_cost: int = DEFAULT_TIME_COST,
memory_cost: int = DEFAULT_MEMORY_COST,
parallelism: int = DEFAULT_PARALLELISM,
hash_len: int = DEFAULT_HASH_LENGTH,
type: Type = Type.I,
) -> bytes: ...
def hash_password_raw(
password: bytes,
salt: bytes | None = None,
time_cost: int = DEFAULT_TIME_COST,
memory_cost: int = DEFAULT_MEMORY_COST,
parallelism: int = DEFAULT_PARALLELISM,
hash_len: int = DEFAULT_HASH_LENGTH,
type: Type = Type.I,
) -> bytes: ...
def verify_password(hash: bytes, password: bytes, type: Type = Type.I) -> Literal[True]: ...from typing import Literal
class Type(Enum):
"""Argon2 algorithm variants"""
D = ... # Argon2d (data-dependent)
I = ... # Argon2i (data-independent)
ID = ... # Argon2id (hybrid)
# Default configuration constants
DEFAULT_TIME_COST: int
DEFAULT_MEMORY_COST: int
DEFAULT_PARALLELISM: int
DEFAULT_HASH_LENGTH: int
DEFAULT_RANDOM_SALT_LENGTH: intInstall with Tessl CLI
npx tessl i tessl/pypi-argon2-cffi