Bcrypt: The Pioneer of Adaptive Hashing

Bcrypt: The Pioneer of Adaptive Hashing

Bcrypt, designed by Niels Provos and David Mazières in 1999, pioneered the concept of adaptive password hashing. Based on the Blowfish cipher, bcrypt incorporates a work factor (cost parameter) that exponentially increases computation time. This adaptability ensures bcrypt remains secure as hardware improves—simply increasing the cost parameter maintains consistent security margins over time.

The algorithm's structure deliberately resists optimization. Bcrypt requires 4KB of memory that must be accessed in a password-dependent manner, preventing simple time-memory trade-offs. The algorithm performs key schedule computation followed by 64 iterations of expensive state manipulation. This design ensures that even specialized hardware cannot dramatically outperform general-purpose processors, maintaining defense against well-resourced attackers.

import bcrypt
import time
import secrets

def demonstrate_bcrypt():
    """Demonstrate bcrypt usage and performance characteristics"""
    
    password = b"SecurePassword123!"
    
    # Show how cost factor affects performance
    print("Bcrypt Performance vs Cost Factor:\n")
    
    for cost in range(8, 15):
        start = time.time()
        salt = bcrypt.gensalt(rounds=cost)
        hashed = bcrypt.hashpw(password, salt)
        elapsed = time.time() - start
        
        print(f"Cost {cost:2d}: {elapsed:6.3f} seconds - Hash: {hashed[:20]}...")
        
        # Verify the hash
        assert bcrypt.checkpw(password, hashed)
    
    # Demonstrate salt integration
    print("\nSalt Integration (same password, different salts):")
    for i in range(3):
        hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=10))
        print(f"Hash {i+1}: {hashed}")
    
    # Show adaptive security
    print("\nAdaptive Security Demonstration:")
    costs_over_time = [
        (2000, 10),  # Year 2000: cost 10
        (2010, 12),  # Year 2010: cost 12
        (2020, 13),  # Year 2020: cost 13
        (2024, 14),  # Year 2024: cost 14
    ]
    
    for year, cost in costs_over_time:
        start = time.time()
        bcrypt.hashpw(password, bcrypt.gensalt(rounds=cost))
        elapsed = time.time() - start
        print(f"Year {year} (cost={cost}): {elapsed:.3f} seconds per hash")

demonstrate_bcrypt()

Bcrypt's format includes algorithm identifier, cost parameter, salt, and hash in a single string, making it self-contained and portable. The standard format $2b$12$salt.hash indicates bcrypt version 2b with cost 12. This encoding simplifies storage and ensures systems can verify passwords even after parameter updates. The 72-byte password length limit, while sometimes criticized, prevents certain denial-of-service attacks.