Cryptographie en TypeScript : chiffrement et hachage — guide complet
Le développement web moderne est impensable sans la sécurité des données. TypeScript, en tant que surcouche de JavaScript, offre des outils puissants pour implémenter des fonctions cryptographiques, tant côté client que côté serveur (Node.js). Dans cet article, nous allons détailler les primitives cryptographiques essentielles : le chiffrement symétrique et asymétrique, le hachage, ainsi que le travail avec les signatures numériques. Tous les exemples de code sont écrits en TypeScript et prêts à être utilisés dans des projets réels.
1. Bases de la cryptographie en TypeScript
Dans l'écosystème TypeScript, il existe deux approches principales pour la cryptographie :
- Web Crypto API — API intégrée des navigateurs et de Node.js (à partir de la version 15), offrant un accès de bas niveau aux opérations cryptographiques.
- Bibliothèques tierces — comme
crypto-js,node-forge,bcryptjspour des tâches spécifiques.
Pour le développement serveur avec Node.js, il est recommandé d'utiliser le module intégré crypto, qui fait partie de la plateforme et ne nécessite pas l'installation de dépendances supplémentaires.
2. Hachage des données
Le hachage est une transformation unidirectionnelle de données en une chaîne de longueur fixe. Il est utilisé pour stocker les mots de passe, vérifier l'intégrité des fichiers et créer des sommes de contrôle.
2.1. SHA-256 avec Web Crypto API
async function hashSHA256(data: string): Promise<string> { const encoder = new TextEncoder(); const dataBuffer = encoder.encode(data); const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer); const hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');}
// Exemple d'utilisationconst myHash = await hashSHA256('Bonjour le monde !');console.log(myHash); // 64 caractères hexadécimaux2.2. Hachage de mots de passe avec bcrypt
Pour stocker les mots de passe en toute sécurité, utilisez des algorithmes spécialisés avec sel, comme bcrypt :
import bcrypt from 'bcryptjs';
async function hashPassword(password: string): Promise<string> { const salt = await bcrypt.genSalt(12); // 12 rounds — bon équilibre return await bcrypt.hash(password, salt);}
async function verifyPassword(password: string, hash: string): Promise<boolean> { return await bcrypt.compare(password, hash);}
// Exempleconst password = 'MonMotDePasseSecurise!';const hashedPassword = await hashPassword(password);const isValid = await verifyPassword('MonMotDePasseSecurise!', hashedPassword);console.log(isValid); // true3. Chiffrement symétrique
Le chiffrement symétrique utilise une seule clé pour chiffrer et déchiffrer les données. L'algorithme le plus moderne et sécurisé est AES-GCM, qui assure à la fois la confidentialité et l'authentification.
3.1. Chiffrement et déchiffrement AES-GCM
interface EncryptedData { iv: Uint8Array; ciphertext: Uint8Array; tag: Uint8Array;}
async function encryptAESGCM( plaintext: string, key: CryptoKey): Promise<EncryptedData> { const encoder = new TextEncoder(); const data = encoder.encode(plaintext); const iv = crypto.getRandomValues(new Uint8Array(12)); // IV de 96 bits const encrypted = await crypto.subtle.encrypt( { name: 'AES-GCM', iv }, key, data ); // GCM ajoute 16 octets de tag d'authentification à la fin const ciphertext = new Uint8Array(encrypted.slice(0, encrypted.byteLength - 16)); const tag = new Uint8Array(encrypted.slice(encrypted.byteLength - 16)); return { iv, ciphertext, tag };}
async function decryptAESGCM( encrypted: EncryptedData, key: CryptoKey): Promise<string> { // Combinaison du ciphertext et du tag pour Web Cry