ring Rust: Kryptographie-Bibliothek mit Beispielen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

ring für Rust: Vollständige Anleitung mit Beispielen

Was ist ring und wofür wird es benötigt?

ring ist eine Kryptographie-Bibliothek für die Programmiersprache Rust, die sichere, geprüfte und leistungsstarke Implementierungen grundlegender kryptografischer Primitive bereitstellt. Sie basiert auf dem Code von BoringSSL (einem Fork von OpenSSL von Google) und wurde mit Fokus auf Sicherheit, einfache Bedienung und Minimierung der Angriffsfläche entwickelt. Im Gegensatz zu allgemeineren Bibliotheken wie openssl oder rust-crypto schränkt ring die unterstützten Algorithmen bewusst ein und schließt veraltete oder unsichere Verfahren (z. B. DES, RC4, MD5) aus, wodurch das Risiko einer versehentlichen Verwendung schwacher Kryptografie reduziert wird.

Wofür wird ring benötigt? Wenn Sie eine Rust-Anwendung entwickeln, die Hashing (SHA-256, SHA-512), symmetrische Verschlüsselung (AES-GCM, ChaCha20-Poly1305), asymmetrische Verschlüsselung und Signaturen (RSA, ECDSA, Ed25519), Zufallszahlengenerierung oder Schlüsselaustausch (X25519, ECDH) benötigt, ist ring die optimale Wahl. Die Bibliothek wird aktiv in Projekten wie rustls (TLS-Implementierung in Rust), reqwest (HTTP-Client) und webpki (Zertifikatsprüfung) eingesetzt. ring benötigt keine externen Abhängigkeiten (außer libc unter Linux/macOS) und wird mit Cargo kompiliert, was sie ideal für eingebettete Systeme und Cross-Kompilierung macht.

Die Hauptvorteile von ring: Sicherheit (ständige Audits, keine unsicheren Algorithmen), Leistung (Verwendung optimierter Assembler-Einschübe aus BoringSSL) und einfache API (minimale Anzahl von Typen und Funktionen, verständliche Dokumentation). ring bietet keine hochwertigen Abstraktionen wie die Arbeit mit Zertifikaten oder Protokollen – dafür gibt es separate Crates. Stattdessen liefert es Bausteine, die sicher kombiniert werden können.

Installation

Um ring zu einem Rust-Projekt hinzuzufügen, führen Sie im Stammverzeichnis des Projekts folgenden Befehl aus:

cargo add ring

Oder fügen Sie manuell in die Datei Cargo.toml ein:

[dependencies]
ring = "0.17"

Zum Zeitpunkt der Erstellung dieses Artikels ist die aktuelle Version 0.17.x. Stellen Sie sicher, dass Rust (rustc 1.70+) installiert ist. ring benötigt einen C-Compiler (gcc, clang oder msvc), um die nativen Komponenten von BoringSSL zu erstellen. Unter Windows kann die Installation der Build Tools für Visual Studio erforderlich sein.

Schnellstart – Minimales Arbeitsbeispiel

Erstellen Sie ein neues Projekt und ersetzen Sie den Inhalt von src/main.rs durch den folgenden Code, der einen SHA-256-Hash eines Strings berechnet:

use ring::digest::{Context, SHA256};
use ring::rand::SystemRandom;

fn main() {
    // SHA-256 Hashing
    let mut context = Context::new(&SHA256);
    context.update("Hallo, ring!".as_bytes());
    let digest = context.finish();
    println!("SHA-256: {:?}", digest);

    // Zufällige Bytes generieren
    let rng = SystemRandom::new();
    let mut random_bytes = [0u8; 32];
    ring::rand::fill(&rng, &mut random_bytes).unwrap();
    println!("Zufallsbytes: {:02x?}", random_bytes);
}

Starten Sie das Programm mit dem Befehl cargo run. Sie sehen den SHA-256-Hash und 32 zufällige Bytes im Hexadezimalformat.

Wichtige Methoden/Funktionen

1. ring::digest::digest

Signatur: pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest

Beschreibung: Berechnet einen Hash der Daten data unter Verwendung des angegebenen Algorithmus (SHA256, SHA384, SHA512, SHA1). Dies ist eine Ein-Pass-Funktion für einfache Fälle.

use ring::digest::{digest, SHA256};

let data = b"Hallo, Welt!";
let result = digest(&SHA256, data);
println!("SHA-256 Hash: {:?}", result);

2. ring::digest::Context

Signatur: pub struct Context { ... }

Beschreibung: Ermöglicht das schrittweise Hashing von Daten, was nützlich ist, wenn Daten in Teilen verarbeitet werden (z. B. beim Lesen einer großen Datei).

use ring::digest::{Context, SHA256};

let mut context = Context::new(&SHA256);
context.update(b"Erster Teil der Daten ");
context.update(b"zweiter Teil der Daten");
let hash = context.finish();
println!("SHA-256 Hash: {:?}", hash);

3. ring::rand::fill

Signatur: pub fn fill(rng: &dyn SecureRandom, dest: &mut [u8]) -> Result<(), Unspecified>

Beschreibung: Füllt einen Byte-Slice mit kryptografisch sicheren Zufallsdaten. Verwendet SystemRandom als Standard-Zufallszahlengenerator.

use ring::rand::{SystemRandom, fill};

let rng = SystemRandom::new();
let mut buffer = [0u8; 16];
fill(&rng, &mut buffer).unwrap();
println!("Zufallsbytes: {:02x?}", buffer);

4. ring::aead::seal_in_place

Signatur: pub fn seal_in_place(algorithm: &'static Algorithm, key: &dyn Key, nonce: &[u8], aad: &[u8], in_out: &mut [u8], tag: &mut [u8]) -> Result<(), Unspecified>

Beschreibung: Verschlüsselt Daten mit einem authentifizierten Verschlüsselungsverfahren (AEAD) wie AES-GCM oder ChaCha20-Poly1305. Die Daten werden direkt im übergebenen Puffer modifiziert.

use ring::aead::{AES_256_GCM, Nonce, SealingKey, NonceSequence, UnboundKey, seal_in_place};
use ring::rand::{SecureRandom, SystemRandom};

let rng = SystemRandom::new();
let mut key_bytes = [0u8; 32];
rng.fill(&mut key_bytes).unwrap();
let unbound_key = UnboundKey::new(&AES_256_GCM, &key_bytes).unwrap();
let nonce = [0u8; 12]; // In der Praxis muss das Nonce für jede Verschlüsselung eindeutig sein!
let mut in_out = b"Geheime Nachricht".to_vec();
let mut tag = [0u8; 16];
seal_in_place(&AES_256_GCM, &unbound_key, &nonce, b"", &mut in_out, &mut tag).unwrap();
println!("Verschlüsselt: {:02x?}", in_out);

5. ring::signature::sign

Signatur: pub fn sign(algorithm: &'static EcdsaSigningAlgorithm, key: &dyn Key, message: &[u8]) -> Result

Beschreibung: Erstellt eine digitale Signatur für eine Nachricht unter Verwendung eines privaten Schlüssels (z. B. ECDSA oder Ed25519).

use ring::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING, KeyPair};
use ring::rand::SystemRandom;

let rng = SystemRandom::new();
let pkcs8_bytes = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &rng).unwrap();
let key_pair = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8_bytes.as_ref()).unwrap();
let message = b"Zu signierende Nachricht";
let signature = key_pair.sign(&rng, message).unwrap();
println!("Signatur: {:?}", signature);

Häufige Fehler und Problemlösungen

Bei der Arbeit mit ring können einige typische Fehler auftreten:

  • Fehler beim Kompilieren: "Could not find native static library" – Stellen Sie sicher, dass ein C-Compiler installiert ist. Unter Linux: sudo apt install build-essential, unter macOS: xcode-select --install.
  • Falsche Nonce-Verwendung: Bei AEAD-Verschlüsselung muss jedes Nonce für einen bestimmten Schlüssel eindeutig sein. Die Wiederverwendung eines Nonces gefährdet die Sicherheit.
  • Ungültige Schlüssellängen: ring erwartet exakte Schlüssellängen. Für AES-256-GCM sind 32 Bytes erforderlich, für AES-128-GCM 16 Bytes.
  • Panik bei unwrap(): Viele ring-Funktionen geben Result zurück. Verwenden Sie in Produktionscode eine ordnungsgemäße Fehlerbehandlung anstelle von unwrap().

Best Practices und Sicherheitshinweise

Beachten Sie diese wichtigen Sicherheitsaspekte bei der Verwendung von ring:

  • Verwenden Sie aktuelle Versionen: Halten Sie ring immer auf dem neuesten Stand, um von Sicherheitsupdates zu profitieren.
  • Keine eigenen Krypto-Implementierungen: Vertrauen Sie auf die geprüften Implementierungen von ring, anstatt eigene Algorithmen zu schreiben.
  • Sichere Zufallszahlen: Verwenden Sie immer SystemRandom für kryptografische Zwecke, niemals rand::thread_rng.
  • Konstante Zeitvergleiche: Verwenden Sie ring::constant_time::verify_slices_are_equal für den Vergleich von MACs und Signaturen, um Timing-Angriffe zu vermeiden.
  • Schlüsselverwaltung: Speichern Sie private Schlüssel niemals im Quellcode. Verwenden Sie Umgebungsvariablen, sichere Speicher oder Hardware-Sicherheitsmodule.

Fazit

ring ist eine der vertrauenswürdigsten und am weitesten verbreiteten Kryptographie-Bibliotheken im Rust-Ökosystem. Durch ihren Fokus auf Sicherheit, Leistung und eine klare API eignet sie sich hervorragend für sicherheitskritische Anwendungen. Ob Sie eine HTTPS-Verbindung mit rustls aufbauen, Dateien verschlüsseln oder digitale Signaturen erstellen möchten – ring bietet die grundlegenden Bausteine dafür. Die Bibliothek ist gut dokumentiert und wird aktiv von der Rust-Community gewartet. Beginnen Sie noch heute mit der Integration von ring in Ihr Projekt und profitieren Sie von einer robusten, geprüften Kryptographie-Implementierung.

Empfehlungen