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
Comprehensive exception hierarchy for different error conditions in Argon2 operations, providing specific error types for verification failures, hashing errors, invalid parameters, and platform-specific limitations.
Root exception class for all Argon2-related errors.
class Argon2Error(Exception):
"""
Superclass of all argon2 exceptions.
Never thrown directly - used as base class for specific error types.
Catch this to handle any Argon2-related error.
"""from argon2 import PasswordHasher
from argon2.exceptions import Argon2Error
ph = PasswordHasher()
try:
result = ph.hash("password")
ph.verify(result, "password")
except Argon2Error as e:
print(f"Argon2 operation failed: {e}")Exceptions raised during password verification operations.
class VerificationError(Argon2Error):
"""
Verification failed for unspecified reasons.
Base class for verification-related errors. The original error
message from Argon2 C library is available in args[0].
"""
class VerifyMismatchError(VerificationError):
"""
The secret does not match the hash.
Raised when password verification fails because the provided
password does not match the stored hash. This is the most
common verification error during normal operation.
"""from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError, VerificationError
ph = PasswordHasher()
stored_hash = ph.hash("correct_password")
# Handle specific verification failures
try:
ph.verify(stored_hash, "wrong_password")
except VerifyMismatchError:
print("Invalid password - access denied")
except VerificationError as e:
print(f"Verification failed due to error: {e}")
# Handle all verification errors together
try:
ph.verify(stored_hash, user_input)
print("Login successful")
except VerificationError:
print("Login failed")Exception raised when hash generation fails.
class HashingError(Argon2Error):
"""
Raised if hashing failed.
Indicates that the Argon2 hashing operation could not be completed.
The original error message from Argon2 C library is available in args[0].
Common causes:
- Invalid parameters (e.g., memory cost too high)
- System resource limitations
- Memory allocation failures
"""from argon2 import PasswordHasher
from argon2.exceptions import HashingError
# Attempt hashing with potentially problematic parameters
try:
ph = PasswordHasher(
memory_cost=999999999, # Excessive memory requirement
time_cost=1000, # Very high time cost
)
hash_result = ph.hash("password")
except HashingError as e:
print(f"Hashing failed: {e}")
# Fall back to more conservative parameters
ph_safe = PasswordHasher() # Use defaults
hash_result = ph_safe.hash("password")Exception raised for invalid hash formats.
class InvalidHashError(ValueError):
"""
Raised if the hash is invalid before passing it to Argon2.
Indicates that the hash string format is so malformed that
it cannot be processed by the Argon2 library. This includes:
- Incorrect hash string structure
- Missing required components
- Invalid encoding
"""
# Deprecated alias (still available for compatibility)
InvalidHash = InvalidHashError
"""
Deprecated alias for InvalidHashError.
Use InvalidHashError instead.
"""from argon2 import PasswordHasher
from argon2.exceptions import InvalidHashError
ph = PasswordHasher()
invalid_hashes = [
"not_a_hash_at_all",
"$argon2id$invalid$format",
"",
"$argon2id$v=19$m=65536,t=3,p=4", # Missing salt and hash
]
for bad_hash in invalid_hashes:
try:
ph.verify(bad_hash, "password")
except InvalidHashError:
print(f"Invalid hash format: {bad_hash}")Exception raised when parameters are not supported on the current platform.
class UnsupportedParametersError(ValueError):
"""
Raised if the current platform does not support the parameters.
Examples:
- WebAssembly environments require parallelism=1
- Memory-constrained systems may not support high memory costs
- Some embedded platforms have threading limitations
"""from argon2 import PasswordHasher
from argon2.exceptions import UnsupportedParametersError
try:
# This may fail in WebAssembly environments
ph = PasswordHasher(parallelism=8)
except UnsupportedParametersError as e:
print(f"Parameters not supported on this platform: {e}")
# Fall back to platform-compatible settings
ph = PasswordHasher(parallelism=1)
# Alternative: Use platform-aware defaults
from argon2.profiles import get_default_parameters
default_params = get_default_parameters() # Automatically adjusts for platform
ph = PasswordHasher.from_parameters(default_params)Handle all possible Argon2 errors with appropriate fallbacks:
from argon2 import PasswordHasher
from argon2.exceptions import (
VerifyMismatchError,
VerificationError,
HashingError,
InvalidHashError,
UnsupportedParametersError,
Argon2Error
)
def safe_hash_password(password: str) -> str:
"""Hash password with error handling and fallbacks."""
try:
ph = PasswordHasher()
return ph.hash(password)
except UnsupportedParametersError:
# Fall back to platform-compatible parameters
ph = PasswordHasher(parallelism=1)
return ph.hash(password)
except HashingError as e:
# Log error and use more conservative parameters
print(f"Hashing failed, trying conservative settings: {e}")
ph = PasswordHasher(memory_cost=32768, time_cost=2)
return ph.hash(password)
def safe_verify_password(hash_str: str, password: str) -> bool:
"""Verify password with comprehensive error handling."""
try:
ph = PasswordHasher()
ph.verify(hash_str, password)
return True
except VerifyMismatchError:
# Normal case - wrong password
return False
except InvalidHashError:
# Hash is corrupted/invalid - treat as verification failure
print("Warning: Invalid hash format detected")
return False
except VerificationError as e:
# Other verification issues - log but treat as failure
print(f"Verification error: {e}")
return FalseTypical integration pattern for authentication systems:
from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError, Argon2Error
def authenticate_user(username: str, password: str) -> bool:
"""Authenticate user with proper error handling."""
# Retrieve stored hash from database
stored_hash = get_user_hash(username)
if not stored_hash:
return False
ph = PasswordHasher()
try:
# Verify password
ph.verify(stored_hash, password)
# Check if hash needs updating
if ph.check_needs_rehash(stored_hash):
new_hash = ph.hash(password)
update_user_hash(username, new_hash)
print(f"Updated password hash for user: {username}")
return True
except VerifyMismatchError:
# Wrong password - normal case
return False
except Argon2Error as e:
# Any other Argon2 error - log and deny access
print(f"Authentication error for {username}: {e}")
return FalseValidate parameters before creating PasswordHasher instances:
from argon2 import PasswordHasher, Parameters
from argon2.exceptions import UnsupportedParametersError
from argon2._utils import validate_params_for_platform
def create_secure_hasher(
time_cost: int = 3,
memory_cost: int = 65536,
parallelism: int = 4
) -> PasswordHasher:
"""Create hasher with parameter validation."""
# Create parameters object for validation
params = Parameters(
type=Type.ID,
version=19,
salt_len=16,
hash_len=32,
time_cost=time_cost,
memory_cost=memory_cost,
parallelism=parallelism,
)
try:
# Validate parameters for current platform
validate_params_for_platform(params)
return PasswordHasher.from_parameters(params)
except UnsupportedParametersError as e:
print(f"Parameters not supported: {e}")
# Return hasher with platform defaults
from argon2.profiles import get_default_parameters
return PasswordHasher.from_parameters(get_default_parameters())Install with Tessl CLI
npx tessl i tessl/pypi-argon2-cffi