PBKDF2

Créé en 2000 • PKCS #5 • RFC 2898Key Derivation

Déprécié - Alternatives RecommandéesStandards GouvernementauxLegacy Systems
⚠️ Guide Migration
Acceptable mais Déprécié

⚠️ STATUT DÉPRÉCIÉ - MIGRATION RECOMMANDÉE

PBKDF2 reste acceptable pour les systèmes legacy mais n'est plus recommandé pour les nouvelles implémentations. Standards gouvernementaux (NIST, ANSSI) exigent 210k+ itérations minimum. Migrez vers Argon2id, bcrypt ou scrypt.

Alternatives Modernes Recommandées 2024

Pourquoi migrer ? PBKDF2 est CPU-only (vulnérable aux ASICs), consomme peu de mémoire (parallélisation facile), et manque des protections modernes contre les attaques par force brute industrielle.

Implémentations Legacy - Standards Gouvernementaux

PBKDF2 avec Avertissements et Migration

Implémentations conformes aux standards NIST SP 800-63B, ANSSI et BSI avec warnings automatiques et recommandations de migration vers alternatives modernes.

Node.js - PBKDF2 Legacy avec Warnings

const crypto = require('crypto');
const { promisify } = require('util');
const pbkdf2 = promisify(crypto.pbkdf2);

// ⚠️ PBKDF2 - Déprécié mais Acceptable pour Legacy 2024
class PBKDF2Manager {
  constructor() {
    // Configurations selon standards gouvernementaux
    this.configs = {
      // Configuration minimum (NIST 2024)
      minimum: {
        iterations: 210000,        // NIST SP 800-63B minimum
        keylen: 32,               // 256-bit output
        digest: 'sha256',
        saltLength: 32
      },
      
      // Configuration gouvernementale (ANSSI, BSI)
      government: {
        iterations: 600000,        // Haute sécurité gouvernementale
        keylen: 64,               // 512-bit output
        digest: 'sha256',
        saltLength: 64
      },
      
      // Configuration legacy compatible
      legacy: {
        iterations: 100000,        // Ancien minimum acceptable
        keylen: 32,
        digest: 'sha1',           // ⚠️ SHA-1 legacy seulement
        saltLength: 16
      }
    };
    
    // Recommandations alternatives
    this.modernAlternatives = [
      'Argon2id - Champion PHC 2015-2024',
      'bcrypt - Éprouvé depuis 25 ans',
      'scrypt - Memory-hard résistant ASIC'
    ];
  }

  async hashPassword(password, config = 'government') {
    const settings = this.configs[config];
    const salt = crypto.randomBytes(settings.saltLength);
    
    const start = process.hrtime.bigint();
    
    try {
      const hash = await pbkdf2(
        password, 
        salt, 
        settings.iterations, 
        settings.keylen, 
        settings.digest
      );
      
      const duration = Number(process.hrtime.bigint() - start) / 1000000;
      
      // Avertissement automatique si PBKDF2 utilisé
      console.warn(`⚠️  PBKDF2 Usage Detected - Consider modern alternatives:
      → Argon2id (recommended 2024)
      → bcrypt (proven reliability)
      → scrypt (ASIC-resistant)`);
      
      return {
        hash: hash.toString('base64'),
        salt: salt.toString('base64'),
        algorithm: 'PBKDF2',
        digest: settings.digest,
        iterations: settings.iterations,
        keyLength: settings.keylen,
        config: config,
        duration: `${duration.toFixed(0)}ms`,
        security_warning: 'Consider modern alternatives',
        alternatives: this.modernAlternatives,
        compliance: this.getComplianceInfo(config)
      };
      
    } catch (error) {
      throw new Error(`PBKDF2 failed: ${error.message}`);
    }
  }

  async verifyPassword(password, hash, salt, config = 'government') {
    const settings = this.configs[config];
    
    const start = process.hrtime.bigint();
    
    try {
      const computedHash = await pbkdf2(
        password, 
        Buffer.from(salt, 'base64'), 
        settings.iterations, 
        settings.keylen, 
        settings.digest
      );
      
      const duration = Number(process.hrtime.bigint() - start) / 1000000;
      
      const isValid = crypto.timingSafeEqual(
        Buffer.from(hash, 'base64'),
        computedHash
      );
      
      return {
        valid: isValid,
        algorithm: 'PBKDF2',
        duration: `${duration.toFixed(2)}ms`,
        timing_safe: true,
        migration_recommendation: isValid ? 'Consider upgrading to Argon2id' : null
      };
      
    } catch (error) {
      throw new Error(`PBKDF2 verification failed: ${error.message}`);
    }
  }

  // Calcul itérations optimales pour temps cible
  async calculateIterationsForTargetTime(targetMs = 500) {
    const testPassword = 'benchmark_password';
    const testSalt = crypto.randomBytes(32);
    let iterations = 100000;
    
    const results = {};
    
    for (let i = 0; i < 3; i++) {
      const start = process.hrtime.bigint();
      
      await pbkdf2(testPassword, testSalt, iterations, 32, 'sha256');
      
      const duration = Number(process.hrtime.bigint() - start) / 1000000;
      results[iterations] = duration;
      
      if (duration >= targetMs) break;
      iterations *= 2;
    }
    
    return {
      target_time_ms: targetMs,
      iterations_tested: results,
      recommended_iterations: iterations,
      warning: 'PBKDF2 is deprecated - use Argon2id instead',
      modern_alternatives: {
        'Argon2id': 'Memory-hard, timing ~200-500ms',
        'bcrypt': 'Adaptive cost, timing ~100-300ms',
        'scrypt': 'Memory-hard, ASIC-resistant'
      }
    };
  }

  // Benchmark contre alternatives modernes
  benchmarkVsAlternatives() {
    return {
      pbkdf2: {
        security: 'ACCEPTABLE_BUT_DEPRECATED',
        performance: 'Good (CPU-bound)',
        memory_usage: 'Very low (~1KB)',
        asic_resistance: 'Poor',
        recommendation: '⚠️ Legacy only - migrate to modern alternatives'
      },
      argon2id: {
        security: 'EXCELLENT_2024_CHAMPION',
        performance: 'Configurable (150ms-2s)',
        memory_usage: 'Configurable (64MB-1GB)',
        asic_resistance: 'Excellent',
        recommendation: '✅ Primary choice for new systems'
      },
      bcrypt: {
        security: 'EXCELLENT_PROVEN',
        performance: 'Good (100-300ms)',
        memory_usage: 'Low (~4KB)',
        asic_resistance: 'Good',
        recommendation: '✅ Reliable choice for web applications'
      },
      scrypt: {
        security: 'VERY_GOOD',
        performance: 'Configurable',
        memory_usage: 'High (configurable)',
        asic_resistance: 'Excellent',
        recommendation: '✅ Good alternative when Argon2 unavailable'
      }
    };
  }

  getComplianceInfo(config) {
    const compliance = {
      minimum: {
        nist_sp_800_63b: 'Compliant (210k+ iterations)',
        owasp: 'Meets minimum requirements',
        pci_dss: 'Acceptable with caveats',
        status: 'MINIMUM_COMPLIANCE'
      },
      government: {
        anssi: 'Compliant (600k iterations)',
        bsi_tr: 'Meets German standards',
        nist_fips: 'FIPS 140-2 compatible',
        status: 'HIGH_COMPLIANCE'
      },
      legacy: {
        status: 'DEPRECATED',
        warning: 'Below current security standards',
        migration_required: true
      }
    };
    
    return compliance[config];
  }
}

Python - PBKDF2 Gouvernemental

import hashlib
import secrets
import time
import warnings
from typing import Dict, Any, Optional

class PBKDF2Manager:
    """PBKDF2 Manager avec avertissements et alternatives modernes"""
    
    def __init__(self):
        # Émettre warning à l'initialisation
        warnings.warn(
            "PBKDF2 is deprecated for new applications. "
            "Consider Argon2id, bcrypt, or scrypt instead.",
            DeprecationWarning,
            stacklevel=2
        )
        
        # Configurations standards gouvernementaux
        self.configs = {
            'minimum': {
                'iterations': 210000,      # NIST SP 800-63B 2024
                'key_length': 32,          # 256-bit
                'hash_algo': 'sha256',
                'salt_length': 32
            },
            'government': {
                'iterations': 600000,      # ANSSI/BSI high security
                'key_length': 64,          # 512-bit
                'hash_algo': 'sha256',
                'salt_length': 64
            },
            'legacy': {
                'iterations': 100000,      # Ancien minimum
                'key_length': 32,
                'hash_algo': 'sha1',       # ⚠️ Legacy seulement
                'salt_length': 16
            }
        }
    
    def hash_password(self, password: str, config: str = 'government') -> Dict[str, Any]:
        """Hash mot de passe avec PBKDF2 et avertissement"""
        if config not in self.configs:
            raise ValueError(f"Unknown config: {config}")
        
        settings = self.configs[config]
        salt = secrets.token_bytes(settings['salt_length'])
        
        start_time = time.perf_counter()
        
        # Hash avec PBKDF2
        hash_result = hashlib.pbkdf2_hmac(
            hash_name=settings['hash_algo'],
            password=password.encode('utf-8'),
            salt=salt,
            iterations=settings['iterations'],
            dklen=settings['key_length']
        )
        
        duration = time.perf_counter() - start_time
        
        # Warning automatique
        print(f"⚠️  PBKDF2 Usage Warning:")
        print(f"   → Consider upgrading to Argon2id (2024 champion)")
        print(f"   → Or bcrypt (proven 25+ years reliability)")
        print(f"   → Current PBKDF2 provides adequate but dated security")
        
        return {
            'hash': hash_result.hex(),
            'salt': salt.hex(),
            'algorithm': 'PBKDF2',
            'hash_algo': settings['hash_algo'],
            'iterations': settings['iterations'],
            'key_length': settings['key_length'],
            'config': config,
            'duration': f"{duration*1000:.0f}ms",
            'security_level': 'DEPRECATED_BUT_ACCEPTABLE',
            'migration_recommendation': 'Upgrade to Argon2id when possible',
            'compliance': self._get_compliance_info(config)
        }
    
    def verify_password(self, password: str, hash_hex: str, salt_hex: str, config: str = 'government') -> Dict[str, Any]:
        """Vérification mot de passe PBKDF2"""
        settings = self.configs[config]
        
        start_time = time.perf_counter()
        
        # Reconstituer hash
        computed_hash = hashlib.pbkdf2_hmac(
            hash_name=settings['hash_algo'],
            password=password.encode('utf-8'),
            salt=bytes.fromhex(salt_hex),
            iterations=settings['iterations'],
            dklen=settings['key_length']
        )
        
        duration = time.perf_counter() - start_time
        
        # Comparaison timing-safe
        is_valid = secrets.compare_digest(hash_hex, computed_hash.hex())
        
        return {
            'valid': is_valid,
            'algorithm': 'PBKDF2',
            'duration': f"{duration*1000:.2f}ms",
            'timing_safe': True,
            'upgrade_recommendation': 'Consider migrating to Argon2id' if is_valid else None
        }
    
    def calculate_iterations_for_target_time(self, target_ms: int = 500) -> Dict[str, Any]:
        """Calcul itérations optimales pour temps cible"""
        test_password = 'benchmark_test_password'
        test_salt = secrets.token_bytes(32)
        
        iterations = 100000
        results = {}
        
        for _ in range(5):
            start_time = time.perf_counter()
            
            hashlib.pbkdf2_hmac('sha256', test_password.encode(), test_salt, iterations, 32)
            
            duration_ms = (time.perf_counter() - start_time) * 1000
            results[iterations] = round(duration_ms)
            
            if duration_ms >= target_ms:
                break
                
            iterations = int(iterations * 1.5)
        
        return {
            'target_time_ms': target_ms,
            'benchmark_results': results,
            'recommended_iterations': iterations,
            'warning': '⚠️ PBKDF2 deprecated - use Argon2id instead',
            'better_alternatives': {
                'Argon2id': 'Memory-hard, PHC winner, configurable',
                'bcrypt': 'Adaptive cost, battle-tested 25+ years',
                'scrypt': 'Memory-hard, ASIC-resistant'
            }
        }
    
    def benchmark_vs_alternatives(self) -> Dict[str, Any]:
        """Benchmark PBKDF2 vs alternatives modernes"""
        return {
            'pbkdf2': {
                'year': '2000 (PKCS #5)',
                'status': 'DEPRECATED_BUT_ACCEPTABLE',
                'security_2024': 'Adequate with 210k+ iterations',
                'performance': 'Good (CPU-only)',
                'memory_usage': 'Very low (~1KB)',
                'asic_resistance': 'Poor',
                'adoption': 'Legacy systems',
                'recommendation': '⚠️ Migrate to modern alternatives'
            },
            'argon2id': {
                'year': '2015 (PHC Winner)',
                'status': 'MODERN_CHAMPION',
                'security_2024': 'Excellent - state of the art',
                'performance': 'Configurable (150ms-2s)',
                'memory_usage': 'Configurable (64MB-1GB+)',
                'asic_resistance': 'Excellent',
                'adoption': 'New systems, security-critical',
                'recommendation': '✅ Primary choice 2024'
            },
            'bcrypt': {
                'year': '1999',
                'status': 'PROVEN_RELIABLE',
                'security_2024': 'Excellent - proven track record',
                'performance': 'Good (100-300ms)',
                'memory_usage': 'Low (~4KB)',
                'asic_resistance': 'Good',
                'adoption': 'Massive (web applications)',
                'recommendation': '✅ Reliable alternative'
            }
        }
    
    def _get_compliance_info(self, config: str) -> Dict[str, Any]:
        """Information conformité standards"""
        compliance_map = {
            'minimum': {
                'nist_sp_800_63b': '✅ Compliant (210k iterations)',
                'owasp': '✅ Meets 2024 requirements',
                'pci_dss': '⚠️ Acceptable but not recommended',
                'level': 'MINIMUM_ACCEPTABLE'
            },
            'government': {
                'anssi': '✅ Compliant (600k iterations)',
                'bsi_tr_02102': '✅ German government standard',
                'nist_fips_140_2': '✅ Compatible',
                'level': 'HIGH_SECURITY_COMPLIANT'
            },
            'legacy': {
                'status': '❌ BELOW_CURRENT_STANDARDS',
                'warning': 'Immediate upgrade required',
                'level': 'NON_COMPLIANT_2024'
            }
        }
        
        return compliance_map.get(config, {'level': 'UNKNOWN'})

# Usage avec avertissements appropriés
if __name__ == "__main__":
    # Warning global
    print("⚠️  PBKDF2 USAGE DETECTED - MODERN ALTERNATIVES RECOMMENDED")
    print("=" * 65)
    print("✅ Argon2id: Memory-hard, PHC winner 2015")
    print("✅ bcrypt: 25+ years proven, adaptive cost")
    print("✅ scrypt: Memory-hard, ASIC-resistant")
    print("⚠️  PBKDF2: Acceptable for legacy, not recommended for new systems")
    print("=" * 65)
    
    manager = PBKDF2Manager()
    
    # Test avec configuration gouvernementale
    password = "MotDePasseComplexe2024!"
    
    hash_result = manager.hash_password(password, 'government')
    print(f"\nPBKDF2 Result: {hash_result}\n")
    
    # Vérification
    verify_result = manager.verify_password(
        password, 
        hash_result['hash'], 
        hash_result['salt'], 
        'government'
    )
    print(f"Verification: {verify_result}\n")
    
    # Benchmark alternatives
    comparison = manager.benchmark_vs_alternatives()
    print("Modern Alternatives Comparison:")
    for alg, info in comparison.items():
        print(f"{alg}: {info['recommendation']}"))

📋 Standards de Conformité 2024

🏛️ Standards Gouvernementaux
  • • NIST SP 800-63B: 210k+ itérations
  • • ANSSI: 600k itérations recommandées
  • • BSI TR-02102: Conformité allemande
  • • PCI DSS: Acceptable avec caveats
⚠️ Limitations Techniques
  • • CPU-only (vulnérable ASICs)
  • • Faible usage mémoire (~1KB)
  • • Parallélisation facile
  • • Pas de résistance GPU moderne

Actions Rapides

⚠️ Statut PBKDF2

SécuritéAcceptable
StatutDéprécié
PerformanceMoyenne
RecommandationMigrer
Déprécié

PBKDF2 reste acceptable pour legacy mais migrez vers Argon2id pour la sécurité moderne.

Guide de Migration PBKDF2 → Alternatives Modernes

Migration vers Argon2id
• Nouvelles applications: Argon2id directement
• Systèmes existants: Migration graduelle
• Rehash progressif à la connexion
Migration vers bcrypt
• Applications web: bcrypt cost 12+
• Compatibilité: Excellente universalité
• Migration: Simple, éprouvée
Maintenance PBKDF2
• Legacy: 600k+ itérations minimum
• Monitoring: Temps de calcul
• Planning: Migration 2024-2025

PBKDF2 : L'Héritage à Moderniser

PBKDF2 a servi fidèlement pendant 25 ans mais les menaces modernes (ASICs, GPUs, cloud computing) dépassent ses capacités défensives. Standards gouvernementaux maintiennent la compatibilité legacy, mais toute nouvelle implémentation doit privilégier Argon2id ou bcrypt.