sha2 / bcrypt Rust : guide complet avec exemples

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

sha2 / bcrypt pour Rust : guide complet avec exemples

Dans le développement moderne, la sécurité des données est un aspect critique de toute application. Les bibliothèques sha2 et bcrypt pour le langage Rust offrent des outils puissants et sécurisés pour le hachage cryptographique. sha2 implémente la famille d'algorithmes SHA-2 (Secure Hash Algorithm 2), incluant SHA-224, SHA-256, SHA-384, SHA-512, ainsi que leurs variantes tronquées (SHA-512/224, SHA-512/256). bcrypt est une fonction de hachage cryptographique adaptative, spécialement conçue pour le stockage sécurisé des mots de passe. Elle utilise un "sel" (salt) et un nombre configurable de rounds (cost factor), ce qui la rend résistante aux attaques par tables arc-en-ciel et par force brute.

Pourquoi en avez-vous besoin ? SHA-2 est utilisé pour vérifier l'intégrité des données, créer des signatures numériques, dans les systèmes de contrôle de version (Git), la blockchain et bien d'autres domaines nécessitant un hachage rapide et fiable. Bcrypt, quant à lui, est la norme de facto pour le hachage des mots de passe dans les applications web, les bases de données et les systèmes d'authentification. Son avantage clé est sa "lenteur" configurable : vous pouvez augmenter le nombre de rounds pour compenser la puissance de calcul croissante des attaquants.

Dans cet article, nous allons explorer en détail les deux bibliothèques : l'installation, les méthodes principales, des exemples d'utilisation concrets et les erreurs courantes. Vous apprendrez à hacher correctement des données, à vérifier des mots de passe et à intégrer ces fonctions dans vos projets Rust.

Installation

Pour utiliser sha2 et bcrypt dans Rust, vous devez les ajouter au fichier Cargo.toml de votre projet. Ouvrez un terminal dans le répertoire racine de votre projet et exécutez :

cargo add sha2 bcrypt

Cette commande ajoutera les dernières versions des bibliothèques dans la section [dependencies]. Vous pouvez également modifier manuellement le fichier Cargo.toml :

[dependencies]
sha2 = "0.10"
bcrypt = "0.15"

Ensuite, exécutez cargo build pour télécharger les dépendances et vérifier que tout est correctement installé.

Démarrage rapide : exemple minimal fonctionnel

Commençons par un exemple simple : hacher une chaîne avec SHA-256 et vérifier un mot de passe avec bcrypt.

use sha2::{Sha256, Digest};
use bcrypt::{hash, verify, DEFAULT_COST};

fn main() {
    // Hachage SHA-256
    let data = b"Bonjour, le monde !";
    let mut hasher = Sha256::new();
    hasher.update(data);
    let result = hasher.finalize();
    println!("Empreinte SHA-256 : {:x}", result);

    // Hachage bcrypt d'un mot de passe
    let password = "mon_mot_de_passe_securise";
    let hashed = hash(password, DEFAULT_COST).unwrap();
    println!("Empreinte bcrypt : {}", hashed);

    // Vérification du mot de passe
    let is_valid = verify(password, &hashed).unwrap();
    println!("Mot de passe correct : {}", is_valid);
}

Ce code illustre les fonctionnalités de base des deux bibliothèques. La sortie contiendra une empreinte hexadécimale SHA-256 de 64 caractères et une longue chaîne bcrypt (commençant par $2b$).

Méthodes et fonctions principales

Examinons les fonctions et méthodes clés de sha2 et bcrypt. Pour chacune, nous fournissons la signature, une description et un exemple fonctionnel.

1. sha2::Sha256::new()

Signature : pub fn new() -> Sha256

Description : Crée une nouvelle instance du hacheur SHA-256. C'est le point de départ pour hacher des données.

use sha2::{Sha256, Digest};

let mut hasher = Sha256::new();
hasher.update(b"données de test");
let hash = hasher.finalize();
println!("{:x}", hash);

2. sha2::Sha256::update()

Signature : pub fn update(&mut self, data: impl AsRef<[u8]>)

Description : Ajoute des données à l'état interne du hacheur. Peut être appelé plusieurs fois pour hacher des données en flux.

use sha2::{Sha256, Digest};

let mut hasher = Sha256::new();
hasher.update(b"première partie ");
hasher.update(b"deuxième partie");
let hash = hasher.finalize();
println!("{:x}", hash);

3. sha2::Sha256::finalize()

Signature : pub fn finalize(self) -> GenericArray<u8, U32>

Description : Finalise le calcul du hachage et retourne le résultat sous forme de tableau d'octets. Consomme le hacheur.

use sha2::{Sha256, Digest};

let mut hasher = Sha256::new();
hasher.update(b"finalisation");
let hash = hasher.finalize();
// Conversion en chaîne hexadécimale
let hex_hash = format!("{:x}", hash);
println!("{}", hex_hash);

4. bcrypt::hash()

Signature : pub fn hash<S: AsRef<[u8]>>(password: S, cost: u32) -> Result<String, BcryptError>

Description : Hache un mot de passe avec bcrypt en utilisant le facteur de coût spécifié. Retourne une chaîne contenant le sel et le hachage.

use bcrypt::{hash, DEFAULT_COST};

let password = "mon_mot_de_passe";
match hash(password, DEFAULT_COST) {
    Ok(hashed) => println!("Haché : {}", hashed),
    Err(e) => eprintln!("Erreur : {}", e),
}

5. bcrypt::verify()

Signature : pub fn verify<S: AsRef<[u8]>>(password: S, hashed: &str) -> Result<bool, BcryptError>

Description : Vérifie si un mot de passe correspond à un hachage bcrypt existant. Extrait automatiquement le sel et le facteur de coût du hachage.

use bcrypt::verify;

let password = "mon_mot_de_passe";
let hashed = "$2b$12$..."; // Hachage existant
match verify(password, hashed) {
    Ok(true) => println!("Mot de passe correct"),
    Ok(false) => println!("Mot de passe incorrect"),
    Err(e) => eprintln!("Erreur : {}", e),
}

6. bcrypt::DEFAULT_COST

Signature : pub const DEFAULT_COST: u32 = 12

Description : Constante représentant le facteur de coût par défaut (12 rounds). Offre un bon équilibre entre sécurité et performance.

use bcrypt::{hash, DEFAULT_COST};

let hashed = hash("mot_de_passe", DEFAULT_COST).unwrap();

Exemple avancé : hachage de fichiers volumineux avec SHA-256

Pour hacher des fichiers volumineux sans les charger entièrement en mémoire, utilisez la méthode update() de manière incrémentale :

use sha2::{Sha256, Digest};
use std::fs::File;
use std::io::{BufReader, Read};

fn hash_file(path: &str) -> Result println!("Empreinte SHA-256 du fichier : {}", hash),
        Err(e) => eprintln!("Erreur : {}", e),
    }
}

Bonnes pratiques et erreurs courantes

  • Ne jamais stocker les mots de passe en clair : Utilisez toujours bcrypt (ou Argon2) pour hacher les mots de passe avant de les stocker.
  • Choisir un facteur de coût adapté : Pour bcrypt, DEFAULT_COST (12) est un bon point de départ. Ajustez-le en fonction de la puissance de votre serveur (entre 10 et 14).
  • Ne pas utiliser SHA-2 pour les mots de passe : SHA-2 est trop rapide et vulnérable aux attaques par force brute. Réservez-le pour l'intégrité des données.
  • Vérifier les erreurs : Les fonctions hash() et verify() retournent des Result. Gérez toujours les erreurs potentielles.
  • Mettre à jour régulièrement : Les bibliothèques cryptographiques évoluent. Utilisez les dernières versions pour bénéficier des correctifs de sécurité.

Conclusion

Les bibliothèques sha2 et bcrypt sont des outils essentiels pour tout développeur Rust soucieux de la sécurité. SHA-2 offre un hachage rapide et fiable pour l'intégrité des données, tandis que bcrypt protège efficacement les mots de passe contre les attaques modernes. En suivant les exemples et les bonnes pratiques de ce guide, vous pouvez intégrer ces fonctionnalités de manière sécurisée dans vos projets.

N'hésitez pas à consulter la documentation officielle de sha2 et bcrypt pour explorer toutes les fonctionnalités avancées.

Recommendations