Kryptografie in Rust: Verschlüsselung und Hashing mit den Bibliotheken ring und sha2
Rust ist eine systemnahe Programmiersprache, die Speichersicherheit und hohe Leistung garantiert. Dank dieser Eigenschaften eignet sie sich ideal für kryptografische Aufgaben. In diesem Artikel betrachten wir zwei beliebte Bibliotheken: ring (für symmetrische Verschlüsselung und Hashing) und sha2 (für reines Hashing). Sie erfahren, wie Sie Daten mit AES-GCM verschlüsseln, SHA-256-Hashes berechnen und HMAC-Signaturen erstellen.
Warum Rust für Kryptografie?
Rust eliminiert ganze Klassen von Schwachstellen (Pufferüberläufe, Datenrennen) bereits zur Kompilierzeit. Kryptografische Bibliotheken in Rust wie ring sind in Assembler und C mit sicheren Wrappern geschrieben, was eine mit C vergleichbare Geschwindigkeit bei gleichzeitiger Zuverlässigkeit von Rust bietet.
Projekt einrichten
Erstellen Sie ein neues Projekt und fügen Sie die Abhängigkeiten in Cargo.toml hinzu:
[dependencies]ring = "0.17"sha2 = "0.10"hex = "0.4" # für bequeme Anzeige von BytesSymmetrische Verschlüsselung: AES-GCM mit ring
AES-GCM (Galois/Counter Mode) ist ein moderner Standard für symmetrische Verschlüsselung, der sowohl Vertraulichkeit als auch Authentifizierung (Integritätsprüfung) bietet. Die Bibliothek ring stellt eine einfache und sichere API bereit.
Daten verschlüsseln
Für die Verschlüsselung werden benötigt: ein Schlüssel (256 Bit), eine Nonce (96 Bit) und der Klartext. Die Nonce muss für jede Verschlüsselung mit demselben Schlüssel eindeutig sein.
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);
// Zufällige Nonce generieren let mut nonce_bytes = [0u8; 12]; rng.fill(&mut nonce_bytes).unwrap(); let nonce = Nonce::assume_unique_for_key(nonce_bytes);
// Verschlüsselung mit leeren Zusatzdaten (AAD) let mut in_out = plaintext.to_vec(); let tag = key.seal_in_place_separate_tag(nonce, Aad::empty(), &mut in_out).unwrap(); // Nonce + verschlüsselte Daten + Authentifizierungstag zurückgeben let mut result = nonce_bytes.to_vec(); result.extend_from_slice(&in_out); result.extend_from_slice(tag.as_ref()); result}Entschlüsselung
Zur Entschlüsselung extrahieren wir Nonce, Tag und den verschlüsselten Text und rufen dann open_in_place auf.
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 erwartet den Tag am Ende 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 // falscher Schlüssel oder beschädigte Daten }}Anwendungsbeispiel
fn main() { let key = b"0123456789abcdef0123456789abcdef"; // 32 Bytes let data = b"Geheime Nachricht für Rust!"; let encrypted = encrypt_aes_gcm(key, data); println!("Verschlüsselt (hex): {}", hex::encode(&encrypted)); if let Some(decrypted) = decrypt_aes_gcm(key, &encrypted) { println!("Entschlüsselt: {}", String::from_utf8(decrypted).unwrap()) Auch in der Bibliothek
SMS-Versand mit C++: API-Bibliothek LibCurl und REST-Anfragen
PhotosUI für Swift: Vollständige Anleitung mit Beispielen
Markdown-Verarbeitung in C# (.NET): Bibliotheken und Werkzeuge
Combine für Swift: vollständige Anleitung mit Beispielen
Newtonsoft.Json für C# (.NET): Vollständiger Leitfaden mit Beispielen