Argon2
Créé en 2015 • PHC Winner•Alex Biryukov et équipe
🏆 CHAMPION ABSOLU 2024 - ÉTAT DE L'ART CRYPTOGRAPHIQUE
Argon2 domine l'écosystème moderne des algorithmes de hachage de mots de passe. Winner de la Password Hashing Competition 2015, résistance maximale GPU/ASIC, configuration adaptive et adoption massive par les frameworks modernes.
Variants Argon2 - Architecture Adaptative
| Variant | Sécurité Spécialisée | Performance | Usage Recommandé |
|---|---|---|---|
| Argon2i | Side-channel résistant | Bonne | Environnements non-sécurisés |
| Argon2d | GPU/ASIC résistant | Excellente | Serveurs sécurisés |
| Argon2id | Hybride optimal | Très bonne | RECOMMANDÉ - Usage général |
Argon2id combine le meilleur des deux mondes : sécurité side-channel d'Argon2i et résistance GPU/ASIC d'Argon2d. Premier choix pour toutes nouvelles implémentations.
Guide Configuration Production
| Cas d'Usage | Mémoire | Temps | Parallélisme | Durée Cible |
|---|---|---|---|---|
| Web Interactif | 64 MiB | 2 | 1 | ~200ms |
| API Backend | 256 MiB | 3 | 4 | ~500ms |
| Haute Sécurité | 1 GiB | 5 | 8 | ~2000ms |
| Mobile/IoT | 32 MiB | 2 | 1 | ~150ms |
| Enterprise | 512 MiB | 4 | 16 | ~1000ms |
Détermine la résistance GPU/ASIC. 64 MiB minimum, 1 GiB+ pour haute sécurité.
Nombre d'itérations. Équilibre sécurité/performance. 2-5 selon contexte.
Threads simultanés. Améliore performance sans compromettre la sécurité.
Avantages Sécuritaires Révolutionnaires
Résistance GPU/ASIC
MaximumMemory-hard function avec accès mémoire intensifs et imprévisibles
Configuration Flexible
ExcellentParamètres ajustables : mémoire, temps, parallélisme selon besoin
Sécurité Side-Channel
ImportantArgon2i/id résistants aux attaques cache-timing
Champion PHC 2015
RéférenceValidation académique rigoureuse, adoption industrielle croissante
Résistances Multi-Niveaux
- • GPU : Memory-hard → coût prohibitif
- • ASIC : Accès mémoire → goulot étranglement
- • Parallélisme : Limité par synchronisation
- • Architecture : Favorise processeurs généralistes
- • Side-channel : Argon2i/id protection
- • Cache timing : Accès mémoire masqués
- • Brute force : Configuration adaptive
- • Rainbow tables : Sel unique + iteration
Adoption Moderne et Cas d'Usage
Applications Modernes
Finance & Fintech
Enterprise Security
IoT & Edge Computing
Implémentations Production-Ready
Implémentations complètes avec configuration adaptive, monitoring enterprise et optimisations performance pour usage production intensive.
Node.js - Manager Argon2id Adaptatif
const argon2 = require('argon2');
// ✅ ARGON2 - Configuration Recommandée 2024
class Argon2Manager {
constructor() {
// Configuration optimale sécurité/performance
this.config = {
type: argon2.argon2id, // Variant hybride recommandé
memoryCost: 2 ** 16, // 64 MiB de mémoire
timeCost: 3, // 3 iterations
parallelism: 1, // 1 thread (ajuster selon CPU)
hashLength: 32, // 32 bytes sortie
saltLength: 32 // 32 bytes salt
};
}
// Hash sécurisé mot de passe
async hashPassword(password) {
try {
const hash = await argon2.hash(password, this.config);
return {
hash: hash,
algorithm: 'Argon2id',
config: this.config,
timestamp: new Date().toISOString(),
security: 'MAXIMUM_2024'
};
} catch (error) {
throw new Error(`Argon2 hashing failed: ${error.message}`);
}
}
// Vérification sécurisée
async verifyPassword(password, hash) {
try {
const isValid = await argon2.verify(hash, password);
return {
valid: isValid,
algorithm: 'Argon2id',
timingResistant: true
};
} catch (error) {
throw new Error(`Argon2 verification failed: ${error.message}`);
}
}
// Configuration adaptative selon usage
getConfigForUsage(usage) {
const configs = {
// Applications web interactives
interactive: {
type: argon2.argon2id,
memoryCost: 2 ** 16, // 64 MiB
timeCost: 2, // 2 iterations (~150ms)
parallelism: 1
},
// Applications serveur backend
server: {
type: argon2.argon2id,
memoryCost: 2 ** 18, // 256 MiB
timeCost: 3, // 3 iterations (~500ms)
parallelism: 4
},
// Sécurité maximale
maximum: {
type: argon2.argon2id,
memoryCost: 2 ** 20, // 1 GiB
timeCost: 5, // 5 iterations (~2s)
parallelism: 8
}
};
return configs[usage] || configs.interactive;
}
// Benchmark pour optimiser configuration
async benchmark(password = 'testpassword', configs = ['interactive', 'server', 'maximum']) {
const results = {};
for (const configName of configs) {
const config = this.getConfigForUsage(configName);
const start = process.hrtime.bigint();
try {
await argon2.hash(password, config);
const end = process.hrtime.bigint();
const durationMs = Number(end - start) / 1000000;
results[configName] = {
config: config,
duration: `${durationMs.toFixed(0)}ms`,
memoryMB: config.memoryCost / 1024,
recommendation: this.getRecommendation(durationMs)
};
} catch (error) {
results[configName] = { error: error.message };
}
}
return results;
}
getRecommendation(durationMs) {
if (durationMs < 100) return 'Trop rapide - augmenter paramètres';
if (durationMs < 500) return 'Bon pour applications interactives';
if (durationMs < 1000) return 'Bon pour backend services';
if (durationMs < 2000) return 'Haute sécurité acceptable';
return 'Très sécurisé - vérifier UX';
}
}
// Usage Production
const argon2Manager = new Argon2Manager();
// Hash mot de passe
(async () => {
const password = 'MonMotDePasseSecurise2024!';
// Hash
const result = await argon2Manager.hashPassword(password);
console.log('Hash Result:', result);
// Vérification
const verification = await argon2Manager.verifyPassword(password, result.hash);
console.log('Verification:', verification);
// Benchmark configurations
const benchmark = await argon2Manager.benchmark();
console.log('Benchmark:', benchmark);
})();Python - Configuration Multi-Profils
import argon2
import secrets
import time
from typing import Optional, Dict, Any
class Argon2Manager:
"""Manager Argon2 optimisé pour production Python"""
def __init__(self):
# Configuration recommandée 2024
self.hasher = argon2.PasswordHasher(
time_cost=3, # 3 iterations
memory_cost=65536, # 64 MiB (2^16 KiB)
parallelism=1, # 1 thread
hash_len=32, # 32 bytes output
salt_len=32, # 32 bytes salt
encoding='utf-8'
)
# Configurations prédéfinies
self.configs = {
'interactive': argon2.PasswordHasher(
time_cost=2, memory_cost=65536, parallelism=1
),
'server': argon2.PasswordHasher(
time_cost=3, memory_cost=262144, parallelism=4 # 256 MiB
),
'maximum': argon2.PasswordHasher(
time_cost=5, memory_cost=1048576, parallelism=8 # 1 GiB
)
}
def hash_password(self, password: str, config: str = 'default') -> Dict[str, Any]:
"""Hash sécurisé avec Argon2id"""
hasher = self.configs.get(config, self.hasher)
start_time = time.perf_counter()
try:
hash_result = hasher.hash(password)
duration = time.perf_counter() - start_time
return {
'hash': hash_result,
'algorithm': 'Argon2id',
'variant': 'argon2id',
'duration': f"{duration*1000:.0f}ms",
'config': config,
'security_level': 'MAXIMUM',
'timestamp': time.time()
}
except argon2.exceptions.HashingError as e:
raise Exception(f"Argon2 hashing failed: {e}")
def verify_password(self, password: str, hash_value: str) -> Dict[str, Any]:
"""Vérification sécurisée temps constant"""
start_time = time.perf_counter()
try:
# Vérification avec timing constant
is_valid = self.hasher.verify(hash_value, password)
duration = time.perf_counter() - start_time
return {
'valid': is_valid,
'algorithm': 'Argon2id',
'duration': f"{duration*1000:.2f}ms",
'timing_safe': True
}
except argon2.exceptions.VerifyMismatchError:
# Maintenir temps constant même pour échecs
time.sleep(max(0, 0.1 - (time.perf_counter() - start_time)))
return {
'valid': False,
'algorithm': 'Argon2id',
'timing_safe': True
}
except Exception as e:
raise Exception(f"Argon2 verification failed: {e}")
def needs_rehash(self, hash_value: str, config: str = 'default') -> bool:
"""Vérifie si le hash doit être mis à jour"""
hasher = self.configs.get(config, self.hasher)
try:
return hasher.check_needs_rehash(hash_value)
except:
return True # En cas d'erreur, recommander rehash
def benchmark_configurations(self, test_password: str = 'benchmark123') -> Dict[str, Any]:
"""Benchmark des différentes configurations"""
results = {}
for config_name, hasher in self.configs.items():
start_time = time.perf_counter()
try:
hasher.hash(test_password)
duration = (time.perf_counter() - start_time) * 1000
results[config_name] = {
'duration_ms': round(duration),
'memory_mb': hasher.memory_cost // 1024,
'time_cost': hasher.time_cost,
'parallelism': hasher.parallelism,
'recommendation': self._get_recommendation(duration)
}
except Exception as e:
results[config_name] = {'error': str(e)}
return results
def _get_recommendation(self, duration_ms: float) -> str:
"""Recommandations basées sur la durée"""
if duration_ms < 100:
return "⚠️ Trop rapide - augmenter paramètres"
elif duration_ms < 500:
return "✅ Optimal pour applications interactives"
elif duration_ms < 1000:
return "✅ Bon pour services backend"
elif duration_ms < 2000:
return "🔒 Haute sécurité - acceptable"
else:
return "🔒 Très sécurisé - vérifier impact UX"
def memory_usage_estimate(self, config: str = 'default') -> Dict[str, Any]:
"""Estimation usage mémoire"""
hasher = self.configs.get(config, self.hasher)
memory_kb = hasher.memory_cost
memory_mb = memory_kb // 1024
return {
'config': config,
'memory_kb': memory_kb,
'memory_mb': memory_mb,
'parallelism': hasher.parallelism,
'total_memory_mb': memory_mb * hasher.parallelism,
'concurrent_users_estimate': max(1, 1000 // memory_mb)
}
# Usage Production
if __name__ == "__main__":
manager = Argon2Manager()
# Test complet
password = "MotDePasseSecurise2024!"
# Hash
hash_result = manager.hash_password(password, 'interactive')
print(f"Hash: {hash_result}")
# Vérification
verify_result = manager.verify_password(password, hash_result['hash'])
print(f"Verification: {verify_result}")
# Vérifier si rehash nécessaire
needs_rehash = manager.needs_rehash(hash_result['hash'], 'server')
print(f"Needs rehash: {needs_rehash}")
# Benchmark
benchmark = manager.benchmark_configurations()
print("Benchmark results:")
for config, result in benchmark.items():
print(f" {config}: {result}")
# Usage mémoire
memory = manager.memory_usage_estimate('server')
print(f"Memory usage: {memory}")Système Enterprise Adaptatif avec Monitoring
// Système Argon2 Enterprise avec Monitoring
// Production-ready avec adaptive tuning et compliance
class EnterpriseArgon2System {
constructor(options = {}) {
this.argon2 = require('argon2');
// Configurations adaptatives
this.profiles = {
web_interactive: {
type: this.argon2.argon2id,
memoryCost: 2 ** 16, // 64 MiB
timeCost: 2, // ~150-200ms
parallelism: 1,
target_time_ms: 200
},
api_backend: {
type: this.argon2.argon2id,
memoryCost: 2 ** 18, // 256 MiB
timeCost: 3, // ~400-600ms
parallelism: 4,
target_time_ms: 500
},
high_security: {
type: this.argon2.argon2id,
memoryCost: 2 ** 20, // 1 GiB
timeCost: 5, // ~1500-2500ms
parallelism: 8,
target_time_ms: 2000
}
};
// Métriques et monitoring
this.metrics = {
total_hashes: 0,
total_verifications: 0,
avg_hash_time: 0,
avg_verify_time: 0,
memory_peak_mb: 0,
errors: 0,
adaptive_adjustments: 0
};
// Configuration adaptive
this.adaptive = {
enabled: options.adaptive || true,
target_time_ms: options.target_time_ms || 300,
adjustment_threshold: options.adjustment_threshold || 0.3,
min_memory_cost: 2 ** 15, // 32 MiB minimum
max_memory_cost: 2 ** 22 // 4 GiB maximum
};
this.current_profile = options.profile || 'api_backend';
this.compliance_mode = options.compliance || false;
// Auto-tuning initial
if (this.adaptive.enabled) {
this.initializeAdaptiveTuning();
}
}
async hashPassword(password, options = {}) {
const startTime = performance.now();
const profile = options.profile || this.current_profile;
try {
// Validation sécurité
this.validatePassword(password);
// Configuration active
const config = this.getCurrentConfig(profile);
// Hash avec monitoring
const hash = await this.argon2.hash(password, config);
const duration = performance.now() - startTime;
// Mise à jour métriques
this.updateHashMetrics(duration, config.memoryCost);
// Ajustement adaptatif
if (this.adaptive.enabled) {
await this.adjustConfigIfNeeded(duration, profile);
}
// Résultat avec metadata
const result = {
hash: hash,
algorithm: 'Argon2id',
profile: profile,
config: config,
performance: {
duration_ms: Math.round(duration),
memory_mb: config.memoryCost / 1024,
threads: config.parallelism
},
compliance: this.compliance_mode ? this.getComplianceInfo() : undefined,
timestamp: new Date().toISOString()
};
// Audit log
this.auditLog('HASH_CREATED', { profile, duration, memory_mb: config.memoryCost / 1024 });
return result;
} catch (error) {
this.metrics.errors++;
this.auditLog('HASH_ERROR', { error: error.message, profile });
throw new Error(`Argon2 hash failed: ${error.message}`);
}
}
async verifyPassword(password, hash, options = {}) {
const startTime = performance.now();
try {
// Vérification avec protection timing
const isValid = await this.argon2.verify(hash, password);
const duration = performance.now() - startTime;
// Mise à jour métriques
this.updateVerifyMetrics(duration);
// Check si rehash recommandé
const needsRehash = await this.checkRehashNeeded(hash);
const result = {
valid: isValid,
algorithm: 'Argon2id',
verification_time_ms: Math.round(duration),
needs_rehash: needsRehash,
timing_safe: true
};
// Audit
this.auditLog('VERIFY_ATTEMPT', {
valid: isValid,
duration,
needs_rehash: needsRehash
});
return result;
} catch (error) {
this.metrics.errors++;
this.auditLog('VERIFY_ERROR', { error: error.message });
// Timing constant même en cas d'erreur
const minTime = 100;
const elapsed = performance.now() - startTime;
if (elapsed < minTime) {
await new Promise(resolve => setTimeout(resolve, minTime - elapsed));
}
return { valid: false, error: error.message, timing_safe: true };
}
}
// Auto-tuning adaptatif
async adjustConfigIfNeeded(actualDuration, profile) {
const targetTime = this.profiles[profile].target_time_ms;
const threshold = this.adaptive.adjustment_threshold;
const ratio = actualDuration / targetTime;
if (ratio < (1 - threshold) || ratio > (1 + threshold)) {
await this.adjustProfile(profile, ratio);
this.metrics.adaptive_adjustments++;
}
}
async adjustProfile(profile, ratio) {
const currentConfig = this.profiles[profile];
if (ratio > 1.2) {
// Trop lent - réduire charge
if (currentConfig.memoryCost > this.adaptive.min_memory_cost) {
currentConfig.memoryCost = Math.max(
this.adaptive.min_memory_cost,
Math.floor(currentConfig.memoryCost * 0.8)
);
} else if (currentConfig.timeCost > 1) {
currentConfig.timeCost = Math.max(1, currentConfig.timeCost - 1);
}
} else if (ratio < 0.8) {
// Trop rapide - augmenter sécurité
if (currentConfig.memoryCost < this.adaptive.max_memory_cost) {
currentConfig.memoryCost = Math.min(
this.adaptive.max_memory_cost,
Math.floor(currentConfig.memoryCost * 1.25)
);
} else {
currentConfig.timeCost = Math.min(10, currentConfig.timeCost + 1);
}
}
this.auditLog('CONFIG_ADJUSTED', {
profile,
ratio: ratio.toFixed(2),
new_config: currentConfig
});
}
// Monitoring et métriques
updateHashMetrics(duration, memoryCost) {
this.metrics.total_hashes++;
this.metrics.avg_hash_time = (
this.metrics.avg_hash_time * (this.metrics.total_hashes - 1) + duration
) / this.metrics.total_hashes;
const memoryMB = memoryCost / 1024;
this.metrics.memory_peak_mb = Math.max(this.metrics.memory_peak_mb, memoryMB);
}
updateVerifyMetrics(duration) {
this.metrics.total_verifications++;
this.metrics.avg_verify_time = (
this.metrics.avg_verify_time * (this.metrics.total_verifications - 1) + duration
) / this.metrics.total_verifications;
}
getSystemMetrics() {
const uptime = process.uptime();
return {
uptime_seconds: Math.floor(uptime),
total_operations: this.metrics.total_hashes + this.metrics.total_verifications,
operations_per_second: (this.metrics.total_hashes + this.metrics.total_verifications) / uptime,
average_hash_time_ms: Math.round(this.metrics.avg_hash_time),
average_verify_time_ms: Math.round(this.metrics.avg_verify_time),
memory_peak_mb: this.metrics.memory_peak_mb,
adaptive_adjustments: this.metrics.adaptive_adjustments,
error_rate: (this.metrics.errors / (this.metrics.total_hashes + this.metrics.total_verifications) * 100).toFixed(3) + '%',
current_configs: this.profiles
};
}
// Conformité et audit
getComplianceInfo() {
return {
algorithm: 'Argon2id',
phc_winner: '2015',
resistance: ['GPU', 'ASIC', 'Side-channel', 'Parallel'],
certification: 'PHC Winner - Industry Standard',
memory_hard: true,
quantum_resistant: 'Partially (brute-force protection)',
recommended_by: ['OWASP', 'NIST', 'RFC-9106']
};
}
auditLog(action, details) {
const logEntry = {
timestamp: new Date().toISOString(),
action: action,
algorithm: 'Argon2id',
details: details,
system_state: {
total_operations: this.metrics.total_hashes + this.metrics.total_verifications,
current_profile: this.current_profile,
adaptive_enabled: this.adaptive.enabled
}
};
console.log('ARGON2_AUDIT:', JSON.stringify(logEntry));
}
// Utilitaires
validatePassword(password) {
if (!password || typeof password !== 'string') {
throw new Error('Password must be a non-empty string');
}
if (password.length > 4096) {
throw new Error('Password too long (max 4096 characters)');
}
}
getCurrentConfig(profile) {
return { ...this.profiles[profile] };
}
async checkRehashNeeded(hash) {
try {
// Logique pour déterminer si rehash nécessaire
// (ex: configuration changée, sécurité améliorée)
return false; // Simplifié pour l'exemple
} catch {
return true; // En cas d'erreur, recommander rehash
}
}
}
// Usage Enterprise
const argon2System = new EnterpriseArgon2System({
adaptive: true,
profile: 'api_backend',
compliance: true,
target_time_ms: 300
});
// Monitoring en temps réel
setInterval(() => {
const metrics = argon2System.getSystemMetrics();
console.log('System Metrics:', metrics);
}, 60000); // Chaque minute⚡ Points Clés Implémentation
- • Auto-tuning selon performance cible
- • Profils prédéfinis par cas d'usage
- • Monitoring temps réel
- • Ajustement dynamique charge
- • Parallélisation intelligente
- • Gestion mémoire optimisée
- • Cache des configurations
- • Métriques enterprise détaillées
Métriques Champion
Argon2 est le standard de facto pour 2024 et au-delà. Adopté massivement par l'industrie moderne.
Ressources et Documentation PHC
Argon2 : L'Avenir du Hachage de Mots de Passe
Argon2 incarne l'excellence cryptographique moderne. Winner de la Password Hashing Competition 2015, il offre une résistance inégalée aux attaques GPU/ASIC, une configuration flexible et une adoption massive. Le choix évident pour toute nouvelle application nécessitant une sécurité de pointe.