const express = require('express'); const router = express.Router(); const crypto = require('crypto'); // Natif à Node.js const argon2 = require('argon2'); // Bibliothèque installée /* Simulation d'une base de données utilisateurs. Dans une vraie app, on utiliserait MongoDB, MySQL, PostgreSQL, etc. On la place ici pour que la démo soit auto-contenue. */ const fakeDatabase = {}; /* ================================================================== DÉMONSTRATION 1 : LA MAUVAISE MÉTHODE (MD5) ================================================================== */ /** * @route POST /users/register-bad * @desc Enregistre un utilisateur avec MD5 (DANGEREUX !) */ router.post('/register-bad', (req, res) => { try { const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ msg: 'Veuillez fournir un username et un password' }); } // Hachage MD5 : rapide, synchrone, non salé. // Une simple recherche Google ou Crackstation inverse ce hash. const hash = crypto.createHash('md5').update(password).digest('hex'); // Stockage du hash "cassable" fakeDatabase[username] = { hash, algorithm: 'md5' }; console.log('Utilisateur (MD5) créé :', fakeDatabase[username]); res.status(201).json({ msg: 'Utilisateur créé avec MD5 (Non sécurisé !)', username: username, hash: hash, // On montre que le mot de passe "123456" donne bien le hash connu note: (password === '123456' ? 'Hash pour 123456: e10adc3949ba59abbe56e057f20f883e' : '') }); } catch (err) { res.status(500).json({ error: err.message }); } }); /** * @route POST /users/login-bad * @desc Connecte un utilisateur avec MD5 */ router.post('/login-bad', (req, res) => { const { username, password } = req.body; const user = fakeDatabase[username]; if (!user || user.algorithm !== 'md5') { return res.status(404).json({ msg: 'Utilisateur non trouvé ou mauvais algo' }); } // On re-hache la tentative de mdp const attemptHash = crypto.createHash('md5').update(password).digest('hex'); // Simple comparaison de chaînes. if (user.hash === attemptHash) { res.json({ msg: 'Connexion MD5 réussie ! (Mais vous n\'êtes pas en sécurité)' }); } else { res.status(401).json({ msg: 'Mot de passe incorrect' }); } }); /* ================================================================== DÉMONSTRATION 2 : LA BONNE MÉTHODE (Argon2id) ================================================================== */ /** * @route POST /users/register-good * @desc Enregistre un utilisateur avec Argon2id (SÉCURISÉ) */ router.post('/register-good', async (req, res) => { // La route est déclarée "async" const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ msg: 'Veuillez fournir un username et un password' }); } try { // 1. Le 'await' est crucial. // Pendant que le CPU calcule le hash (ce qui est LENT), // le thread principal de Node.js est libéré et peut traiter // d'autres requêtes. const hash = await argon2.hash(password, { type: argon2.argon2id, // La variante la plus robuste memoryCost: 2 ** 16, // 64Mo de RAM (65536 KiB) timeCost: 3, // 3 itérations parallelism: 1 // Utilise 1 cœur }); // 2. Le hash contient le sel (salt) et les paramètres de coût. // Il est auto-suffisant. // ex: $argon2id$v=19$m=65536,t=3,p=1$Gb... fakeDatabase[username] = { hash, algorithm: 'argon2id' }; console.log('Utilisateur (Argon2id) créé :', fakeDatabase[username]); res.status(201).json({ msg: 'Utilisateur créé avec Argon2id (Sécurisé !)', username: username, hash: hash }); } catch (err) { console.error(err); res.status(500).json({ msg: 'Erreur lors du hachage du mot de passe' }); } }); /** * @route POST /users/login-good * @desc Connecte un utilisateur avec Argon2id */ router.post('/login-good', async (req, res) => { const { username, password } = req.body; const user = fakeDatabase[username]; if (!user || user.algorithm !== 'argon2id') { return res.status(404).json({ msg: 'Utilisateur non trouvé ou mauvais algo' }); } try { // 3. On utilise 'argon2.verify' // Cette fonction lit le hash, extrait le sel et les paramètres, // re-hache la tentative (password) et compare en temps constant. const isMatch = await argon2.verify(user.hash, password); if (isMatch) { res.json({ msg: 'Connexion Argon2id réussie ! (Vous êtes en sécurité)' }); } else { res.status(401).json({ msg: 'Mot de passe incorrect' }); } } catch (err) { // Si le format du hash est mauvais, ou autre erreur console.error(err); res.status(500).json({ msg: 'Erreur lors de la vérification' }); } }); module.exports = router;