PyCryptodome is a self-contained Python package of low-level cryptographic primitives
—
High-level cryptographic protocols and constructions including key derivation functions, secret sharing schemes, and key exchange protocols. These protocols build upon primitive cryptographic functions to provide complete security solutions.
Functions that derive cryptographic keys from passwords, shared secrets, or other key material with configurable security parameters and salt values.
def scrypt(password, salt, key_len, N, r, p, num_keys=1):
"""
Scrypt key derivation function - memory-hard KDF resistant to specialized hardware attacks.
Parameters:
- password (bytes): Password or passphrase to derive key from
- salt (bytes): Salt value (recommend 16+ bytes)
- key_len (int): Length of derived key in bytes
- N (int): CPU/memory cost parameter (power of 2, e.g., 16384)
- r (int): Block size parameter (e.g., 8)
- p (int): Parallelization parameter (e.g., 1)
- num_keys (int): Number of keys to derive (default: 1)
Returns:
bytes or list of bytes: Derived key(s)
"""
def PBKDF2(password, salt, dkLen=16, count=1000, prf=None, hmac_hash_module=None):
"""
PBKDF2 key derivation function - widely supported password-based KDF.
Parameters:
- password (bytes): Password to derive key from
- salt (bytes): Salt value (recommend 16+ bytes)
- dkLen (int): Desired key length in bytes
- count (int): Iteration count (recommend 100,000+)
- prf (callable): Pseudorandom function (default: HMAC-SHA1)
- hmac_hash_module: Hash module for HMAC (e.g., SHA256)
Returns:
bytes: Derived key
"""
def HKDF(master, length, salt, hashmod, num_keys=1, context=b""):
"""
HKDF (HMAC-based Key Derivation Function) - extract and expand pattern for key derivation.
Parameters:
- master (bytes): Input key material (IKM)
- length (int): Length of output key material in bytes
- salt (bytes): Optional salt value (can be empty)
- hashmod: Hash algorithm module (e.g., SHA256)
- num_keys (int): Number of keys to derive
- context (bytes): Optional context and application specific information
Returns:
bytes or list of bytes: Derived key material
"""
def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None):
"""
PBKDF1 key derivation function - legacy, limited output length.
Parameters:
- password (bytes): Password to derive key from
- salt (bytes): 8-byte salt value
- dkLen (int): Desired key length (max 20 bytes for SHA-1)
- count (int): Iteration count
- hashAlgo: Hash algorithm (default: SHA-1)
Returns:
bytes: Derived key
"""
def bcrypt(password, cost, salt=None):
"""
Bcrypt password hashing function - adaptive hash function for passwords.
Parameters:
- password (bytes): Password to hash
- cost (int): Work factor (4-31, recommend 12+)
- salt (bytes): 16-byte salt (auto-generated if None)
Returns:
bytes: Bcrypt hash string
"""
def bcrypt_check(password, bcrypt_hash):
"""
Verify bcrypt password hash.
Parameters:
- password (bytes): Password to verify
- bcrypt_hash (bytes): Bcrypt hash to check against
Returns:
bool: True if password matches hash
"""Shamir's Secret Sharing scheme allowing a secret to be divided into shares where any subset of shares can reconstruct the original secret.
class Shamir:
"""Shamir's Secret Sharing implementation."""
@staticmethod
def split(k, n, secret, ssss=False):
"""
Split secret into n shares where k shares are needed to reconstruct.
Parameters:
- k (int): Threshold - minimum shares needed to reconstruct secret
- n (int): Total number of shares to generate
- secret (bytes): Secret data to split (max 64 bytes)
- ssss (bool): Use SSSS format for compatibility
Returns:
list of tuples: [(share_index, share_data), ...] where share_index is 1-based
"""
@staticmethod
def combine(shares, ssss=False):
"""
Reconstruct secret from threshold number of shares.
Parameters:
- shares (list): List of (share_index, share_data) tuples
- ssss (bool): Interpret shares as SSSS format
Returns:
bytes: Reconstructed secret
Raises:
ValueError: If insufficient shares or shares are invalid
"""Elliptic curve Diffie-Hellman key exchange using modern curves (X25519, X448) for establishing shared secrets.
def import_x25519_public_key(encoded):
"""
Import X25519 public key for key exchange.
Parameters:
- encoded (bytes): 32-byte public key in binary format or PEM/DER
Returns:
ECC key object for X25519 curve
"""
def import_x25519_private_key(encoded, passphrase=None):
"""
Import X25519 private key.
Parameters:
- encoded (bytes): Private key in binary, PEM, or PKCS#8 format
- passphrase (bytes): Password for encrypted keys
Returns:
ECC key object for X25519 curve
"""
def import_x448_public_key(encoded):
"""
Import X448 public key for key exchange.
Parameters:
- encoded (bytes): 56-byte public key in binary format or PEM/DER
Returns:
ECC key object for X448 curve
"""
def import_x448_private_key(encoded, passphrase=None):
"""
Import X448 private key.
Parameters:
- encoded (bytes): Private key in binary, PEM, or PKCS#8 format
- passphrase (bytes): Password for encrypted keys
Returns:
ECC key object for X448 curve
"""Modern hybrid encryption combining public key cryptography with symmetric encryption for efficient encryption of longer messages.
class MODE:
"""HPKE mode constants."""
BASE: int # Base mode
PSK: int # Pre-shared key mode
AUTH: int # Authenticated mode
AUTH_PSK: int # Authenticated + pre-shared key mode
class AEAD:
"""AEAD cipher interface for HPKE."""
def encrypt(self, plaintext: bytes, aad: bytes = b"") -> bytes:
"""Encrypt plaintext with additional authenticated data."""
def decrypt(self, ciphertext: bytes, aad: bytes = b"") -> bytes:
"""Decrypt ciphertext and verify additional authenticated data."""
class DeserializeError(Exception):
"""Exception raised when HPKE key deserialization fails."""
class MessageLimitReachedError(Exception):
"""Exception raised when HPKE message limit is exceeded."""from Crypto.Protocol.KDF import PBKDF2, scrypt
from Crypto.Hash import SHA256
from Crypto.Random import get_random_bytes
# PBKDF2 for general password-based keys
password = b"user_password"
salt = get_random_bytes(16)
key = PBKDF2(password, salt, dkLen=32, count=100000, hmac_hash_module=SHA256)
# Scrypt for high-security applications
scrypt_key = scrypt(password, salt, key_len=32, N=16384, r=8, p=1)
# Verify password with bcrypt
from Crypto.Protocol.KDF import bcrypt, bcrypt_check
password_hash = bcrypt(password, cost=12)
is_valid = bcrypt_check(password, password_hash)from Crypto.Protocol.KDF import HKDF
from Crypto.Hash import SHA256
# Derive keys from shared secret (e.g., from ECDH)
shared_secret = b"shared_key_material_from_ecdh"
salt = get_random_bytes(16)
info = b"application_context"
# Derive encryption and MAC keys
keys = HKDF(shared_secret, 64, salt, SHA256, num_keys=2, context=info)
encryption_key = keys[0][:32]
mac_key = keys[1][:32]from Crypto.Protocol.SecretSharing import Shamir
# Split secret into 5 shares, requiring 3 to reconstruct
secret = b"top_secret_data_to_protect"
shares = Shamir.split(3, 5, secret)
print(f"Generated {len(shares)} shares:")
for idx, share_data in shares:
print(f"Share {idx}: {share_data.hex()}")
# Reconstruct secret from any 3 shares
selected_shares = shares[:3] # Use first 3 shares
reconstructed = Shamir.combine(selected_shares)
assert reconstructed == secretfrom Crypto.PublicKey import ECC
from Crypto.Protocol.DH import import_x25519_public_key, import_x25519_private_key
# Generate X25519 key pairs for Alice and Bob
alice_private = ECC.generate(curve='X25519')
bob_private = ECC.generate(curve='X25519')
# Exchange public keys
alice_public = alice_private.public_key()
bob_public = bob_private.public_key()
# Perform ECDH key agreement (both sides compute the same shared secret)
# Note: Actual ECDH computation requires additional implementation
# This example shows key management onlyfrom Crypto.Protocol.KDF import HKDF
from Crypto.Hash import SHA256
# Derive multiple keys for different purposes
master_secret = get_random_bytes(32)
salt = get_random_bytes(16)
# Derive 3 keys: encryption, MAC, and IV derivation
keys = HKDF(master_secret, 32, salt, SHA256, num_keys=3, context=b"app_v1.0")
encryption_key = keys[0]
mac_key = keys[1]
iv_key = keys[2]ValueError: Invalid parameters, insufficient shares, or malformed inputTypeError: Incorrect parameter typesOverflowError: Parameters outside valid rangesDeserializeError: Invalid key formats in HPKE operationsMessageLimitReachedError: HPKE message limits exceededInstall with Tessl CLI
npx tessl i tessl/pypi-pycryptodome