Cryptographie en Rust : chiffrement et hachage avec les bibliothèques ring et sha2
Rust est un langage de programmation système qui garantit la sécurité mémoire et des performances élevées. Grâce à ces qualités, il est idéal pour les tâches de cryptographie. Dans cet article, nous examinerons deux bibliothèques populaires : ring (pour le chiffrement symétrique et le hachage) et sha2 (pour le hachage pur). Vous apprendrez à chiffrer des données avec AES-GCM, à calculer des hachages SHA-256 et à créer des signatures HMAC.
Pourquoi Rust pour la cryptographie ?
Rust élimine des classes entières de vulnérabilités (dépassement de tampon, conditions de concurrence) dès la compilation. Les bibliothèques cryptographiques en Rust, comme ring, sont écrites en assembleur et en C avec des enveloppes sécurisées, offrant une vitesse comparable à celle du C, mais avec la fiabilité de Rust.
Configuration du projet
Créez un nouveau projet et ajoutez les dépendances dans Cargo.toml :
[dependencies]ring = "0.17"sha2 = "0.10"hex = "0.4" # pour un affichage pratique des octetsChiffrement symétrique : AES-GCM avec ring
AES-GCM (Galois/Counter Mode) est une norme moderne de chiffrement symétrique qui assure à la fois la confidentialité et l'authentification (vérification de l'intégrité). La bibliothèque ring fournit une API simple et sécurisée.
Chiffrement des données
Pour le chiffrement, vous avez besoin : d'une clé (256 bits), d'un nonce (96 bits) et d'un texte clair. Le nonce doit être unique pour chaque chiffrement avec une même clé.
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, AES_256_GCM};use ring::rand::{SecureRandom, SystemRandom};
fn encrypt_aes_gcm(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> { let rng = SystemRandom::new(); let unbound_key = UnboundKey::new(&AES_256_GCM, key).unwrap(); let key = LessSafeKey::new(unbound_key);
// Génération d'un nonce aléatoire let mut nonce_bytes = [0u8; 12]; rng.fill(&mut nonce_bytes).unwrap(); let nonce = Nonce::assume_unique_for_key(nonce_bytes);
// Chiffrement avec des données supplémentaires vides (AAD) let mut in_out = plaintext.to_vec(); let tag = key.seal_in_place_separate_tag(nonce, Aad::empty(), &mut in_out).unwrap(); // Retourne nonce + données chiffrées + tag d'authentification let mut result = nonce_bytes.to_vec(); result.extend_from_slice(&in_out); result.extend_from_slice(tag.as_ref()); result}Déchiffrement
Pour déchiffrer, extrayez le nonce, le tag et le texte chiffré, puis appelez open_in_place.
fn decrypt_aes_gcm(key: &[u8; 32], ciphertext: &[u8]) -> Option<Vec<u8>> { if ciphertext.len() < 28 { return None; } // 12 (nonce) + 16 (tag) minimum
let (nonce_bytes, rest) = ciphertext.split_at(12); let (encrypted, tag_bytes) = rest.split_at(rest.len() - 16); let nonce = Nonce::assume_unique_for_key(*nonce_bytes); let unbound_key = UnboundKey::new(&AES_256_GCM, key).unwrap(); let key = LessSafeKey::new(unbound_key);
let mut in_out = encrypted.to_vec(); in_out.extend_from_slice(tag_bytes); // ring attend le tag à la fin match key.open_in_place(nonce, Aad::empty(), &mut in_out) { Ok(plaintext) => { let plain_len = plaintext.len(); Some(plaintext[..plain_len].to_vec()) }, Err(_) => None // clé incorrecte ou données corrompues }}Exemple d'utilisation
fn main() { let key = b"0123456789abcdef0123456789abcdef"; // 32 octets let data = b"Message secret pour Rust !"; let encrypted = encrypt_aes_gcm(key, data); println!("Chiffré (hex) : {}", hex::encode(&encrypted)); if let Some(decrypted) = decrypt_aes_gcm(key, &encrypted) { println!("Déchiffré : {}", String::from_utf8(decrypted).unwrap()) Aussi dans la bibliothèque
Génération Swagger/OpenAPI pour TypeScript : bibliothèques et outils
Traitement d'images en Java : bibliothèques, outils et exemples de code
Autorisation et authentification en Kotlin : JWT, Spring Security et Ktor
Jetons JWT en Rust : bibliothèques et implémentation de l'authentification
Client Redis Swift : RediStack pour iOS/macOS