Loading vLEI.wiki
Fetching knowledge base...
Fetching knowledge base...
This comprehensive explanation has been generated from 16 GitHub source documents. All source documents are searchable here.
Last updated: October 7, 2025
This content is meant to be consumed by AI agents via MCP. Click here to get the MCP configuration.
Note: In rare cases it may contain LLM hallucinations.
For authoritative documentation, please consult the official GLEIF vLEI trainings and the ToIP Glossary.
Key stretching is a cryptographic technique that transforms weak, low-entropy secrets (typically passwords or passphrases) into cryptographically strong keys by applying computationally intensive derivation functions, thereby increasing the time and resources required for brute-force attacks against each password candidate.
Key stretching is a cryptographic security process that addresses the fundamental vulnerability of human-generated secrets in cryptographic systems. The process transforms potentially weak input material—such as passwords, passphrases, or other low-entropy secrets—into cryptographically strong keys suitable for use in encryption, authentication, and key derivation operations.
The primary accomplishment of key stretching is computational amplification of password security. By applying iterative cryptographic operations to the input secret, key stretching increases the computational cost of testing each password candidate during a brute-force attack. This transforms a weak password that might be cracked in seconds into one that requires hours, days, or years to crack, depending on the stretching parameters.
Key stretching achieves several critical security objectives:
Key stretching is employed in several critical scenarios within cryptographic systems:
Password-Based Key Derivation: When cryptographic keys must be derived from user-provided passwords or passphrases, key stretching ensures the derived keys have sufficient cryptographic strength despite the weak input material.
: In implementations like and , key stretching protects encrypted keystores. The user's passcode undergoes key stretching to derive the encryption key that protects the stored private keys and .
Prefer Argon2id for New Implementations: Argon2id provides the best resistance against both GPU and side-channel attacks. It combines the data-dependent memory access of Argon2d with the data-independent memory access of Argon2i.
PBKDF2 for Compatibility: Use PBKDF2-HMAC-SHA256 when compatibility with existing systems is required, but increase iteration counts to at least 600,000 (OWASP 2023 recommendation).
Avoid Deprecated Algorithms: Never use MD5, SHA-1, or single-iteration hashing for password storage.
Argon2id Parameters (OWASP recommendations):
PBKDF2 Parameters:
Generation: Always use cryptographically secure random number generators (CSPRNG) for salt generation. Never use predictable values or reuse salts.
Storage: Store salts in plaintext alongside encrypted data or in keystore metadata. Salts are not secret—their purpose is uniqueness, not confidentiality.
Length: Use at least 128-bit (16-byte) salts, preferably 256-bit (32-byte) salts for future-proofing.
Clear Sensitive Data: Always zero out passwords and stretched keys from memory after use. In Python, this is challenging due to immutable strings, but use memoryview and bytearray for mutable buffers that can be cleared.
Avoid Logging: Never log passwords, stretched keys, or intermediate values. Ensure exception handlers don't expose sensitive data.
Constant-Time Operations: Use constant-time comparison functions for password verification to prevent timing attacks.
Calibration: Calibrate iteration counts on target hardware to achieve acceptable authentication delays (100-500ms for interactive systems).
: For session-based systems, cache the stretched key in memory during the session to avoid repeated stretching. Clear the cache on session termination.
Authentication Systems: Password verification systems use key stretching to slow down authentication attempts, making online brute-force attacks impractical while maintaining reasonable performance for legitimate users.
Seed Generation: When generating cryptographic seeds or salts from user-provided entropy, key stretching ensures the resulting material has sufficient cryptographic strength for secure key generation.
The key stretching process involves several participants:
Input Secret: The weak, human-generated password or passphrase that serves as the initial entropy source. This typically has low entropy (40-60 bits for typical passwords) compared to cryptographic requirements (128+ bits).
Salt: A random value unique to each user or key derivation instance. The salt prevents identical passwords from producing identical stretched keys and defeats rainbow table attacks.
Key Derivation Function (KDF): The cryptographic algorithm that performs the stretching operation. Modern KDFs include PBKDF2, bcrypt, scrypt, and Argon2.
Iteration Count/Work Factor: A parameter controlling how many times the stretching operation is applied. Higher values provide greater security but require more computation time.
Output Key: The cryptographically strong key produced by the stretching process, suitable for use in encryption, authentication, or further key derivation.
The key stretching process follows a well-defined sequence of operations designed to maximize computational cost for attackers while remaining practical for legitimate users.
The process begins with input preparation, where the user-provided secret (password or passphrase) is prepared for processing:
The salt component is either generated (for new keys) or retrieved (for existing keys):
New Key Generation:
Existing Key Derivation:
The core stretching operation applies the selected KDF with configured parameters:
PBKDF2 (Password-Based Key Derivation Function 2):
DK = PBKDF2(PRF, Password, Salt, c, dkLen)
Where:
The function iteratively applies the PRF:
U1 = PRF(Password, Salt || INT(i))
U2 = PRF(Password, U1)
U3 = PRF(Password, U2)
...
Uc = PRF(Password, Uc-1)
T = U1 XOR U2 XOR U3 XOR ... XOR Uc
Modern Alternatives:
Argon2 (recommended for new implementations):
scrypt:
bcrypt:
The output extraction phase produces the final stretched key:
The final phase involves secure handling of the stretched key:
Storage Considerations:
Usage Patterns:
Implementing secure key stretching requires careful attention to cryptographic requirements, performance considerations, and error handling.
Algorithm Selection:
The choice of key derivation function significantly impacts security:
PBKDF2 Requirements:
Argon2 Requirements (preferred for new implementations):
Salt Requirements:
Output Key Requirements:
Performance Tuning:
Key stretching introduces intentional computational delay that must be balanced against usability:
Target Delay:
Iteration Count Calibration:
# Pseudocode for calibrating iteration count
def calibrate_iterations(target_delay_ms, algorithm):
iterations = 10000
while True:
start = time()
test_stretch(algorithm, iterations)
elapsed = time() - start
if elapsed >= target_delay_ms:
return iterations
# Increase iterations proportionally
iterations = int(iterations * (target_delay_ms / elapsed))
Hardware Considerations:
Adaptive Parameters:
Input Validation Errors:
class KeyStretchingError(Exception):
"""Base exception for key stretching errors"""
pass
class InvalidPasswordError(KeyStretchingError):
"""Password does not meet requirements"""
pass
class InvalidSaltError(KeyStretchingError):
"""Salt is invalid or missing"""
pass
def validate_inputs(password, salt, iterations):
if not password or len(password) < MIN_PASSWORD_LENGTH:
raise InvalidPasswordError("Password too short")
if not salt or len(salt) < MIN_SALT_LENGTH:
raise InvalidSaltError("Salt too short or missing")
if iterations < MIN_ITERATIONS:
raise KeyStretchingError(f"Iteration count too low: {iterations}")
Cryptographic Errors:
Timing Attack Mitigation:
Key stretching appears in several common patterns within cryptographic systems, particularly in KERI implementations.
The most common usage pattern in KERI is keystore protection, where key stretching derives the encryption key for the keystore database:
Initialization Flow:
encryption_key = stretch(passcode, salt, iterations)Unlock Flow:
encryption_key = stretch(passcode, salt, iterations)Key stretching can strengthen user-provided entropy for seed generation:
Seed Generation:
def generate_seed_from_passphrase(passphrase, salt=None):
# Generate salt if not provided
if salt is None:
salt = os.urandom(32) # 256 bits
# Stretch the passphrase
stretched = argon2.hash(
passphrase.encode('utf-8'),
salt=salt,
time_cost=3,
memory_cost=65536, # 64 MB
parallelism=4,
hash_len=32, # 256 bits
type=argon2.Type.ID
)
# Use stretched key as seed
seed = stretched
return seed, salt
Combining key stretching with multiple factors for enhanced security:
Two-Factor Key Derivation:
def derive_key_two_factor(password, device_secret, salt):
# Stretch password
password_key = pbkdf2_hmac(
'sha256',
password.encode('utf-8'),
salt,
iterations=600000,
dklen=32
)
# Combine with device secret
combined = password_key + device_secret
# Final derivation
final_key = pbkdf2_hmac(
'sha256',
combined,
salt,
iterations=1, # Already stretched
dklen=32
)
return final_key
Using stretched keys as master keys for hierarchical deterministic key derivation:
Master Key Derivation:
def derive_master_key(passphrase, salt):
# Stretch passphrase to master key
master_key = argon2.hash(
passphrase.encode('utf-8'),
salt=salt,
time_cost=3,
memory_cost=65536,
parallelism=4,
hash_len=64, # 512 bits for HKDF
type=argon2.Type.ID
)
return master_key
def derive_child_key(master_key, context, index):
# Use HKDF to derive child keys
info = f"{context}:{index}".encode('utf-8')
child_key = hkdf.derive(
master_key,
length=32,
info=info,
salt=b''
)
return child_key
Security Best Practices:
Performance Best Practices:
Integration Considerations:
Within the KERI ecosystem, key stretching plays a critical role in protecting the root-of-trust established by autonomic identifiers.
KERI implementations like KERIpy and cesride use key stretching to protect encrypted keystores containing:
The keystore encryption key is derived from a user-provided passcode using key stretching, ensuring that even if the encrypted keystore file is compromised, the attacker must perform expensive key stretching operations for each password guess.
When generating seeds from user-provided passphrases (rather than purely random generation), key stretching ensures the resulting seed has sufficient cryptographic strength for secure key derivation. This is particularly important for:
Key stretching in KERI contexts involves balancing several factors:
Security vs. Usability:
Entropy vs. Memorability:
Performance vs. Security:
By properly implementing key stretching, KERI systems can accommodate human-friendly authentication mechanisms while maintaining the cryptographic strength required for secure autonomic identifier management.
Async Operations: Perform key stretching asynchronously in web applications to avoid blocking the UI thread.
Store Parameters: Always store the algorithm identifier, version, and parameters (iterations, memory, parallelism) alongside the salt. This enables:
Migration Strategy: Implement opportunistic re-stretching: when a user successfully authenticates with old parameters, re-stretch their password with updated parameters and update the stored values.
Validation: Validate all inputs before stretching:
Timing Attacks: Ensure consistent timing regardless of password correctness. Don't return early on validation failures.
Resource Limits: Handle memory allocation failures gracefully, especially for memory-hard algorithms like Argon2 and scrypt.
Keystore Protection: In KERI implementations, key stretching protects the keystore containing private keys, pre-rotated keys, and seeds. The stretched key serves as the encryption key for the keystore database.
Seed Derivation: When deriving seeds from user passphrases, apply key stretching before using the seed for hierarchical key derivation.
Multi-Device Synchronization: For synchronized keystores across devices, ensure consistent key stretching parameters and salt values. Store parameters in keystore metadata that syncs with the encrypted data.
Hardware Security Modules: When using HSMs, leverage hardware-accelerated key stretching if available, but ensure the HSM supports the chosen algorithm and parameters.
Unit Tests: Test key stretching with known test vectors to ensure correct implementation.
Performance Tests: Measure key stretching performance on target hardware to validate parameter choices.
Security Tests: Verify that different passwords produce different stretched keys, and that the same password with different salts produces different keys.
Compatibility Tests: Ensure stretched keys can be reproduced across different platforms and library versions.