Cryptographie en Rust : chiffrement et hachage avec les bibliothèques ring et sha2

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

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 octets


Chiffrement 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())                    

Recommendations