Implementation Approaches

Implementation Approaches

Several peppering strategies exist, each with distinct security properties and operational characteristics. Pre-hashing peppering applies the pepper before the main password hashing algorithm, while post-hashing applies it after. HMAC-based peppering uses the pepper as a key for message authentication. Each approach offers different trade-offs between security, performance, and compatibility.

import time
import base64
from enum import Enum

class PepperStrategy(Enum):
    PREPEND = "prepend"
    HMAC_FIRST = "hmac_first"
    ENCRYPT_HASH = "encrypt_hash"
    DOUBLE_HASH = "double_hash"

class AdvancedPepperSystem:
    """Comprehensive pepper implementation with multiple strategies"""
    
    def __init__(self, pepper_key=None):
        self.pepper = pepper_key or secrets.token_bytes(32)
        self.ph = PasswordHasher(time_cost=3, memory_cost=65536)
        
    def apply_pepper(self, password, strategy=PepperStrategy.HMAC_FIRST):
        """Apply pepper using specified strategy"""
        
        if strategy == PepperStrategy.PREPEND:
            # Simple prepending (least secure)
            return self.pepper.hex() + password
            
        elif strategy == PepperStrategy.HMAC_FIRST:
            # HMAC before hashing (recommended)
            peppered = hmac.new(
                self.pepper,
                password.encode('utf-8'),
                hashlib.sha256
            ).digest()
            return base64.b64encode(peppered).decode('ascii')
            
        elif strategy == PepperStrategy.DOUBLE_HASH:
            # Hash with pepper as salt component
            intermediate = hashlib.pbkdf2_hmac(
                'sha256',
                password.encode('utf-8'),
                self.pepper,
                100000
            )
            return base64.b64encode(intermediate).decode('ascii')
    
    def hash_password(self, password, strategy=PepperStrategy.HMAC_FIRST):
        """Hash password with selected pepper strategy"""
        
        # Apply pepper
        peppered = self.apply_pepper(password, strategy)
        
        # Hash with Argon2
        hash_value = self.ph.hash(peppered)
        
        # Store strategy for verification
        return f"{strategy.value}${hash_value}"
    
    def verify_password(self, password, stored_hash):
        """Verify password with appropriate pepper strategy"""
        
        try:
            # Extract strategy and hash
            strategy_str, hash_value = stored_hash.split('$', 1)
            strategy = PepperStrategy(strategy_str)
            
            # Apply same pepper strategy
            peppered = self.apply_pepper(password, strategy)
            
            # Verify with Argon2
            return self.ph.verify(hash_value, peppered)
            
        except Exception:
            return False
    
    def benchmark_strategies(self):
        """Compare performance of different strategies"""
        
        password = "BenchmarkPassword123!"
        iterations = 100
        
        print("\nPepper Strategy Performance Comparison:")
        print("-" * 50)
        
        for strategy in PepperStrategy:
            start = time.time()
            
            for _ in range(iterations):
                self.hash_password(password, strategy)
            
            elapsed = time.time() - start
            per_hash = elapsed / iterations
            
            print(f"{strategy.value:12}: {per_hash*1000:.1f}ms per hash")

# Demonstrate different strategies
pepper_system = AdvancedPepperSystem()

# Test each strategy
password = "TestPassword123!"
print("Different Pepper Strategies:\n")

for strategy in PepperStrategy:
    hashed = pepper_system.hash_password(password, strategy)
    print(f"{strategy.value}:")
    print(f"  Hash: {hashed[:50]}...")
    
    # Verify
    assert pepper_system.verify_password(password, hashed)
    assert not pepper_system.verify_password("wrong", hashed)
    print(f"  ✓ Verification works\n")

# Benchmark performance
pepper_system.benchmark_strategies()

HMAC-based peppering provides the strongest security properties by cryptographically binding the password and pepper. This approach ensures that any modification to either value produces completely different results, preventing length extension attacks and providing standard cryptographic guarantees. The HMAC output can be used directly as input to password hashing functions, maintaining compatibility with existing systems.