CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-argon2-cffi

Argon2 password hashing algorithm for Python with secure defaults and multiple variants

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

password-hasher.mddocs/

Password Hashing

High-level password hashing interface with the PasswordHasher class, designed for typical password storage and verification use cases with secure defaults.

Capabilities

PasswordHasher Class

High-level class for password hashing with sensible defaults. Uses Argon2id by default and generates random salts automatically. Designed for convenience while maintaining security best practices.

class PasswordHasher:
    """
    High level class to hash passwords with sensible defaults.
    
    Uses Argon2id by default and uses a random salt for hashing. Can verify
    any type of Argon2 as long as the hash is correctly encoded.
    """
    
    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,
    ):
        """
        Initialize PasswordHasher with specified parameters.
        
        Args:
            time_cost: Number of iterations (computation time)
            memory_cost: Memory usage in kibibytes
            parallelism: Number of parallel threads
            hash_len: Length of hash in bytes
            salt_len: Length of random salt in bytes
            encoding: Text encoding for string passwords
            type: Argon2 variant to use
        """

Usage Example

from argon2 import PasswordHasher

# Use default parameters (recommended for most applications)
ph = PasswordHasher()

# Or customize for specific security requirements
ph_custom = PasswordHasher(
    time_cost=4,        # More iterations for higher security
    memory_cost=131072, # 128 MiB memory usage
    parallelism=2,      # Fewer threads for limited environments
    hash_len=64,        # Longer hash output
)

Password Hashing

Hash passwords with automatic salt generation and configurable parameters.

def hash(self, password: str | bytes, *, salt: bytes | None = None) -> str:
    """
    Hash password and return an encoded hash.
    
    Args:
        password: Password to hash (str or bytes)
        salt: Optional salt bytes. If None, random salt is generated.
                WARNING: Only provide salt if you know what you're doing.
    
    Returns:
        Encoded Argon2 hash string
    
    Raises:
        argon2.exceptions.HashingError: If hashing fails
    """

Usage Example

from argon2 import PasswordHasher

ph = PasswordHasher()

# Hash a password (recommended - automatic salt generation)
password = "my_secure_password"
hash_string = ph.hash(password)
print(hash_string)
# Output: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash

# Hash with custom salt (advanced usage)
import os
custom_salt = os.urandom(16)
hash_with_salt = ph.hash(password, salt=custom_salt)

Password Verification

Verify passwords against stored hashes with constant-time comparison to prevent timing attacks.

def verify(self, hash: str | bytes, password: str | bytes) -> Literal[True]:
    """
    Verify that password matches hash.
    
    Args:
        hash: Encoded hash string (from hash() method)
        password: Password to verify
    
    Returns:
        True if password matches hash
    
    Raises:
        argon2.exceptions.VerifyMismatchError: Password doesn't match
        argon2.exceptions.VerificationError: Verification failed for other reasons
        argon2.exceptions.InvalidHashError: Hash format is invalid
    """

Usage Example

from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError

ph = PasswordHasher()

# Store this hash in your database
stored_hash = ph.hash("user_password")

# Later, during login verification
try:
    ph.verify(stored_hash, "user_password")
    print("Login successful!")
except VerifyMismatchError:
    print("Invalid password!")

Rehash Detection

Check if stored hashes need to be updated due to changed security parameters.

def check_needs_rehash(self, hash: str | bytes) -> bool:
    """
    Check whether hash was created using the instance's parameters.
    
    Use this to detect when passwords should be rehashed due to:
    - Changed security parameters
    - Updated library defaults
    - Security policy changes
    
    Args:
        hash: Encoded Argon2 hash string
    
    Returns:
        True if hash should be rehashed with current parameters
    """

Usage Example

from argon2 import PasswordHasher

ph = PasswordHasher()

# During login, check if hash needs updating
stored_hash = "$argon2id$v=19$m=102400,t=2,p=8$..."  # Old parameters

if ph.check_needs_rehash(stored_hash):
    # User provided correct password, update hash in database
    new_hash = ph.hash(user_password)
    # Save new_hash to database
    print("Password hash updated to current security standards")

Class Methods

Create PasswordHasher instances from parameter objects.

@classmethod
def from_parameters(cls, params: Parameters) -> PasswordHasher:
    """
    Construct a PasswordHasher from a Parameters object.
    
    Args:
        params: Parameters object with Argon2 configuration
    
    Returns:
        PasswordHasher instance configured with params
    """

Usage Example

from argon2 import PasswordHasher
from argon2.profiles import RFC_9106_HIGH_MEMORY

# Create hasher from predefined profile
ph = PasswordHasher.from_parameters(RFC_9106_HIGH_MEMORY)

# Or from extracted parameters
from argon2 import extract_parameters
existing_hash = "$argon2id$v=19$m=65536,t=3,p=4$..."
params = extract_parameters(existing_hash)
ph_same = PasswordHasher.from_parameters(params)

Properties

Access current hasher configuration parameters.

@property
def time_cost(self) -> int:
    """Current time cost (iterations)"""

@property  
def memory_cost(self) -> int:
    """Current memory cost (kibibytes)"""

@property
def parallelism(self) -> int:
    """Current parallelism (threads)"""

@property
def hash_len(self) -> int:
    """Current hash length (bytes)"""

@property
def salt_len(self) -> int:
    """Current salt length (bytes)"""

@property
def type(self) -> Type:
    """Current Argon2 type"""

Usage Example

from argon2 import PasswordHasher

ph = PasswordHasher()

print(f"Using {ph.type.name} with:")
print(f"  Time cost: {ph.time_cost}")
print(f"  Memory: {ph.memory_cost} KiB")
print(f"  Threads: {ph.parallelism}")
print(f"  Hash length: {ph.hash_len} bytes")

Install with Tessl CLI

npx tessl i tessl/pypi-argon2-cffi

docs

exceptions.md

index.md

low-level.md

password-hasher.md

profiles.md

tile.json