Cryptographic recipes and primitives for Python developers
—
Cryptographic hash functions providing both one-shot hashing and incremental hash contexts. Includes SHA family, SHA-3, BLAKE2, MD5, SM3, and extendable output functions (XOFs).
from cryptography.hazmat.primitives import hashesAll hash functions provide a consistent context-based interface for incremental hashing.
class Hash:
def __init__(self, algorithm, backend=None):
"""
Create hash context.
Args:
algorithm: Hash algorithm instance (SHA256(), BLAKE2b(), etc.)
backend: Cryptographic backend (usually None for default)
"""
def update(self, data: bytes) -> None:
"""
Update hash with additional data.
Args:
data (bytes): Data to add to hash
"""
def finalize(self) -> bytes:
"""
Finalize hash and return digest.
Returns:
bytes: Hash digest
Note:
Cannot call update() after finalize()
"""
def copy(self) -> 'Hash':
"""
Create copy of current hash state.
Returns:
Hash: Independent copy of hash context
"""
class HashAlgorithm:
"""Abstract base class for hash algorithms"""
@property
def name(self) -> str:
"""Algorithm name"""
@property
def digest_size(self) -> int:
"""Digest size in bytes"""XOFs can produce variable-length output.
class XOFHash:
def __init__(self, algorithm, backend=None):
"""
Create XOF hash context.
Args:
algorithm: XOF algorithm (SHAKE128(), SHAKE256())
backend: Cryptographic backend
"""
def update(self, data: bytes) -> None:
"""Update XOF with data"""
def finalize(self, length: int) -> bytes:
"""
Finalize XOF and return digest of specified length.
Args:
length (int): Desired output length in bytes
Returns:
bytes: XOF digest of requested length
"""
def copy(self) -> 'XOFHash':
"""Create copy of XOF state"""
class ExtendableOutputFunction:
"""Abstract base for XOF algorithms"""
@property
def name(self) -> str:
"""Algorithm name"""Standard SHA-2 hash functions with fixed output sizes.
class SHA1:
"""
SHA-1 hash algorithm (160-bit digest).
Note: SHA-1 is cryptographically broken, use SHA-256 or higher.
"""
name = "sha1"
digest_size = 20
class SHA224:
"""SHA-224 hash algorithm (224-bit digest)"""
name = "sha224"
digest_size = 28
class SHA256:
"""SHA-256 hash algorithm (256-bit digest)"""
name = "sha256"
digest_size = 32
class SHA384:
"""SHA-384 hash algorithm (384-bit digest)"""
name = "sha384"
digest_size = 48
class SHA512:
"""SHA-512 hash algorithm (512-bit digest)"""
name = "sha512"
digest_size = 64
class SHA512_224:
"""SHA-512/224 hash algorithm (224-bit digest from SHA-512)"""
name = "sha512-224"
digest_size = 28
class SHA512_256:
"""SHA-512/256 hash algorithm (256-bit digest from SHA-512)"""
name = "sha512-256"
digest_size = 32NIST SHA-3 standard hash functions.
class SHA3_224:
"""SHA3-224 hash algorithm (224-bit digest)"""
name = "sha3-224"
digest_size = 28
class SHA3_256:
"""SHA3-256 hash algorithm (256-bit digest)"""
name = "sha3-256"
digest_size = 32
class SHA3_384:
"""SHA3-384 hash algorithm (384-bit digest)"""
name = "sha3-384"
digest_size = 48
class SHA3_512:
"""SHA3-512 hash algorithm (512-bit digest)"""
name = "sha3-512"
digest_size = 64
class SHAKE128:
"""SHAKE128 extendable output function"""
name = "shake128"
class SHAKE256:
"""SHAKE256 extendable output function"""
name = "shake256"High-performance cryptographic hash functions.
class BLAKE2b:
def __init__(self, digest_size: int):
"""
BLAKE2b hash algorithm with configurable output size.
Args:
digest_size (int): Output size in bytes (1-64)
"""
@property
def name(self) -> str:
return "blake2b"
@property
def digest_size(self) -> int:
"""Configured digest size"""
class BLAKE2s:
def __init__(self, digest_size: int):
"""
BLAKE2s hash algorithm with configurable output size.
Args:
digest_size (int): Output size in bytes (1-32)
"""
@property
def name(self) -> str:
return "blake2s"
@property
def digest_size(self) -> int:
"""Configured digest size"""class MD5:
"""
MD5 hash algorithm (128-bit digest).
Note: MD5 is cryptographically broken, use SHA-256 or higher.
"""
name = "md5"
digest_size = 16
class SM3:
"""SM3 hash algorithm (256-bit digest) - Chinese national standard"""
name = "sm3"
digest_size = 32from cryptography.hazmat.primitives import hashes
# One-shot hashing
data = b"Hello, World!"
# SHA-256
digest = hashes.Hash(hashes.SHA256())
digest.update(data)
hash_value = digest.finalize()
print(f"SHA-256: {hash_value.hex()}")
# SHA-3
digest = hashes.Hash(hashes.SHA3_256())
digest.update(data)
hash_value = digest.finalize()
print(f"SHA3-256: {hash_value.hex()}")from cryptography.hazmat.primitives import hashes
# Hash large data incrementally
hasher = hashes.Hash(hashes.SHA256())
# Process data in chunks
with open('large_file.bin', 'rb') as f:
while chunk := f.read(8192):
hasher.update(chunk)
final_hash = hasher.finalize()
print(f"File hash: {final_hash.hex()}")from cryptography.hazmat.primitives import hashes
# Create base hash state
base_hasher = hashes.Hash(hashes.SHA256())
base_hasher.update(b"Common prefix")
# Create multiple branches from same state
hasher1 = base_hasher.copy()
hasher1.update(b"Branch 1 data")
hash1 = hasher1.finalize()
hasher2 = base_hasher.copy()
hasher2.update(b"Branch 2 data")
hash2 = hasher2.finalize()
print(f"Hash 1: {hash1.hex()}")
print(f"Hash 2: {hash2.hex()}")from cryptography.hazmat.primitives import hashes
# SHAKE128 - variable length output
data = b"Input data for XOF"
xof = hashes.XOFHash(hashes.SHAKE128())
xof.update(data)
# Generate different length outputs
short_output = xof.copy().finalize(16) # 16 bytes
long_output = xof.copy().finalize(64) # 64 bytes
print(f"Short SHAKE128: {short_output.hex()}")
print(f"Long SHAKE128: {long_output.hex()}")
# SHAKE256
xof256 = hashes.XOFHash(hashes.SHAKE256())
xof256.update(data)
output256 = xof256.finalize(32)
print(f"SHAKE256: {output256.hex()}")from cryptography.hazmat.primitives import hashes
data = b"Data to hash with BLAKE2"
# BLAKE2b with 32-byte output
blake2b_32 = hashes.Hash(hashes.BLAKE2b(32))
blake2b_32.update(data)
hash_32 = blake2b_32.finalize()
# BLAKE2b with 64-byte output (maximum)
blake2b_64 = hashes.Hash(hashes.BLAKE2b(64))
blake2b_64.update(data)
hash_64 = blake2b_64.finalize()
print(f"BLAKE2b-32: {hash_32.hex()}")
print(f"BLAKE2b-64: {hash_64.hex()}")
# BLAKE2s with 16-byte output
blake2s_16 = hashes.Hash(hashes.BLAKE2s(16))
blake2s_16.update(data)
hash_16 = blake2s_16.finalize()
print(f"BLAKE2s-16: {hash_16.hex()}")from cryptography.hazmat.primitives import hashes
import os
class FileHasher:
def __init__(self, algorithm=hashes.SHA256()):
self.algorithm = algorithm
def hash_file(self, filepath):
"""Compute hash of file"""
hasher = hashes.Hash(self.algorithm)
with open(filepath, 'rb') as f:
while chunk := f.read(65536): # 64KB chunks
hasher.update(chunk)
return hasher.finalize()
def verify_file(self, filepath, expected_hash):
"""Verify file matches expected hash"""
actual_hash = self.hash_file(filepath)
return actual_hash == expected_hash
# Usage
file_hasher = FileHasher(hashes.SHA256())
# Compute file hash
file_hash = file_hasher.hash_file('document.pdf')
print(f"File hash: {file_hash.hex()}")
# Later, verify file integrity
is_valid = file_hasher.verify_file('document.pdf', file_hash)
print(f"File integrity: {'OK' if is_valid else 'FAILED'}")from cryptography.hazmat.primitives import hashes, hmac
# HMAC typically uses hash functions
key = b"secret_key_32_bytes_long_for_hmac"
message = b"Message to authenticate"
# HMAC-SHA256
h = hmac.HMAC(key, hashes.SHA256())
h.update(message)
signature = h.finalize()
print(f"HMAC-SHA256: {signature.hex()}")
# Verify HMAC
h_verify = hmac.HMAC(key, hashes.SHA256())
h_verify.update(message)
try:
h_verify.verify(signature)
print("HMAC verification: SUCCESS")
except Exception:
print("HMAC verification: FAILED")from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import os
def hash_password(password: str, salt: bytes = None) -> tuple:
"""Hash password using PBKDF2-HMAC-SHA256"""
if salt is None:
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000, # OWASP recommended minimum
)
key = kdf.derive(password.encode())
return key, salt
def verify_password(password: str, stored_hash: bytes, salt: bytes) -> bool:
"""Verify password against stored hash"""
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
try:
kdf.verify(password.encode(), stored_hash)
return True
except Exception:
return False
# Usage
password = "user_password123"
# Hash password for storage
password_hash, salt = hash_password(password)
print(f"Password hash: {password_hash.hex()}")
print(f"Salt: {salt.hex()}")
# Verify password
is_valid = verify_password(password, password_hash, salt)
print(f"Password valid: {is_valid}")Install with Tessl CLI
npx tessl i tessl/pypi-cryptography