MD5 vs SHA256: Hash-Funktionen einfach erklärt

9 min19. Mai 2026

Was Hash-Funktionen tun (MD5 vs SHA256 in einfachen Worten)

Eine Hash-Funktion nimmt beliebige Eingaben — ein einzelnes Zeichen, eine 10-GB-Datei, einen leeren String — und produziert eine Ausgabe fester Größe, den Digest. MD5 gibt immer 128 Bits aus (32 Hex-Zeichen). SHA-256 gibt immer 256 Bits aus (64 Hex-Zeichen). Die gleiche Eingabe produziert immer die gleiche Ausgabe, aber du kannst den Prozess nicht umkehren, um die Eingabe wiederherzustellen. Das ist das gesamte Konzept. Die MD5-vs-SHA256-Debatte läuft auf eine Frage hinaus: Brauchst du Kollisionsresistenz?

Kollisionsresistenz bedeutet, dass es rechnerisch unmöglich sein sollte, zwei verschiedene Eingaben zu finden, die den gleichen Hash produzieren. MD5 verlor diese Eigenschaft 2004, als Xiaoyun Wang praktische Kollisionsangriffe demonstrierte. Bis 2012 konnten Forscher kollidierende PDFs mit unterschiedlichem sichtbarem Inhalt aber identischen MD5-Hashes erstellen. SHA-256 hat keine bekannten Kollisionen und wird voraussichtlich noch Jahrzehnte sicher bleiben.

Aber hier ist, was die meisten Artikel falsch machen: MD5 ist nicht für alles "gebrochen". Es ist gebrochen für Sicherheit (digitale Signaturen, Zertifikate, Integritätsprüfung gegen böswillige Manipulation). Es ist völlig in Ordnung für Nicht-Sicherheits-Anwendungen: Deduplizierung, Cache-Keys, Prüfsummen für versehentliche Korruption, Hash-Table-Verteilung. Wenn dein Bedrohungsmodell keinen Angreifer einschließt, der absichtlich Kollisionen erzeugt, ist MD5 schnell und ausreichend.

Wie Hash-Funktionen arbeiten (die Mechanik)

Alle kryptographischen Hash-Funktionen folgen dem gleichen Muster: Eingabe auf ein Vielfaches der Blockgröße auffüllen, in Blöcke aufteilen und jeden Block durch eine Kompressionsfunktion verarbeiten, die ihn mit dem laufenden Zustand mischt. MD5 verwendet 512-Bit-Blöcke und 4 Runden mit je 16 Operationen. SHA-256 verwendet 512-Bit-Blöcke und 64 Runden. Mehr Runden = mehr Mischung = schwerer umzukehren oder Kollisionen zu finden.

Der Lawineneffekt macht Hashes nützlich: Das Ändern eines einzelnen Bits in der Eingabe kippt ungefähr 50% der Ausgabe-Bits. "hello" und "hellp" produzieren komplett verschiedene Hashes ohne sichtbare Beziehung. Das bedeutet, du kannst nichts über die Eingabe aus der Ausgabe ableiten, und ähnliche Eingaben produzieren keine ähnlichen Ausgaben. Unser hash-generator Tool demonstriert das — ändere ein Zeichen und beobachte, wie sich der gesamte Hash ändert.

Die Performance variiert dramatisch. Auf moderner Hardware (Intel i7-13700K) verarbeitet MD5 etwa 6 GB/s, SHA-256 etwa 2 GB/s (oder 8 GB/s mit SHA-NI Hardware-Beschleunigung), SHA-3 etwa 1,5 GB/s und BLAKE3 etwa 12 GB/s (es ist für Geschwindigkeit mit SIMD designed). Für Passwort-Hashing willst du Langsamkeit — bcrypt mit Cost 12 schafft etwa 4 Hashes/Sekunde auf der gleichen CPU. Das ist Absicht.

Ein Detail, das Leute stolpern lässt: Hash-Funktionen sind deterministisch, aber nicht portabel über Kodierungen. SHA-256 des Strings "hello" hängt davon ab, ob du ihn als UTF-8, UTF-16 oder ASCII kodierst. Die Bytes sind unterschiedlich, also ist der Hash unterschiedlich. Spezifiziere immer die Kodierung. In JavaScript gibt dir new TextEncoder().encode("hello") UTF-8-Bytes, was die Standard-Konvention ist.

// Same string, different encodings = different hashes
const text = "hello";

// UTF-8 (standard): 68 65 6c 6c 6f (5 bytes)
// SHA-256: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

// UTF-16LE: 68 00 65 00 6c 00 6c 00 6f 00 (10 bytes)  
// SHA-256: completely different hash

// Always use UTF-8 unless you have a specific reason not to
const encoder = new TextEncoder(); // UTF-8 by default
const bytes = encoder.encode(text);
const hash = await crypto.subtle.digest("SHA-256", bytes);

Wann welchen Algorithmus verwenden (praktischer Guide)

Dateiintegrität (versehentliche Korruption erkennen): MD5 oder CRC32 reicht. Du schützt gegen Festplattenfehler und Netzwerk-Glitches, nicht gegen Angreifer. MD5 ist schneller als SHA-256 und die 128-Bit-Ausgabe ist ausreichend. Linux-Paketmanager verwenden immer noch MD5-Prüfsummen neben SHA-256 für Abwärtskompatibilität. Wenn du extra Sicherheit bei minimalem Aufwand willst, nimm SHA-256 — es ist schnell genug für die meisten Dateigrößen.

Content Addressing und Deduplizierung: SHA-256 ist der Standard. Git verwendet SHA-1 (migriert zu SHA-256), IPFS verwendet SHA-256, Docker-Image-Layer verwenden SHA-256. Der Hash wird zur Identität des Inhalts — wenn zwei Dateien den gleichen SHA-256 haben, sind sie die gleiche Datei (mit überwältigender Wahrscheinlichkeit). Verwende hier kein MD5, weil ein Angreifer eine bösartige Datei mit dem gleichen MD5 wie eine legitime erstellen könnte.

Digitale Signaturen und Zertifikate: Mindestens SHA-256. TLS-Zertifikate wechselten 2017 von SHA-1 zu SHA-256, nachdem Google eine SHA-1-Kollision demonstrierte (der "SHAttered"-Angriff, der ~110.000 $ an GPU-Zeit kostete). Für neue Systeme sind SHA-256 oder SHA-3 beide gute Wahlen. Ed25519-Signaturen verwenden intern SHA-512.

Passwort-Hashing: KEINES der obigen. MD5, SHA-256, SHA-3 sind alle falsch für Passwörter, weil sie zu schnell sind. Verwende bcrypt, scrypt oder Argon2id — das sind absichtlich langsame Funktionen, die gegen Brute-Force-Angriffe designed sind. Eine GPU kann 10 Milliarden SHA-256-Hashes pro Sekunde berechnen, aber nur ~70 bcrypt-Hashes pro Sekunde. Siehe unser password-generator Tool zum Generieren von Passwörtern, die selbst Slow-Hash-Brute-Forcing widerstehen.

Die SHA-Familie: SHA-1, SHA-2, SHA-3

SHA-1 (160 Bits): Gebrochen seit 2017. Googles SHAttered-Angriff produzierte zwei verschiedene PDFs mit dem gleichen SHA-1-Hash. Kosten: ~110.000 $ an Cloud-GPU-Zeit 2017, wahrscheinlich unter 10.000 $ heute. Verwende SHA-1 für nichts Sicherheitsrelevantes. Git verwendet es noch, migriert aber zu SHA-256. Chrome und Firefox lehnen SHA-1-Zertifikate seit 2017 ab.

SHA-2-Familie (SHA-224, SHA-256, SHA-384, SHA-512): Der aktuelle Standard. SHA-256 ist die häufigste Variante. SHA-512 ist auf 64-Bit-Prozessoren schneller (kontraintuitiv — es verarbeitet 1024-Bit-Blöcke vs SHA-256s 512-Bit-Blöcke, und 64-Bit-Operationen sind nativ). SHA-384 ist einfach SHA-512 mit einem anderen Initialzustand und gekürzter Ausgabe. Für die meisten Zwecke ist SHA-256 die Standard-Wahl.

SHA-3 (Keccak, standardisiert 2015): Ein komplett anderes internes Design als SHA-2 (Sponge-Konstruktion vs Merkle-Damgård). Es existiert als Backup, falls SHA-2 gebrochen wird — zwei unverwandte Algorithmen zu haben bedeutet, dass ein Durchbruch gegen einen den anderen nicht betrifft. SHA-3 ist in Software etwas langsamer als SHA-2, hat aber eine breitere Sicherheitsmarge. Verwende es, wenn deine Compliance-Anforderungen es vorschreiben, sonst ist SHA-256 in Ordnung.

BLAKE3 (2020): Keine SHA-Variante, aber erwähnenswert. Es ist 3-6x schneller als SHA-256, parallelisierbar (skaliert mit CPU-Kernen) und hat eine 256-Bit-Ausgabe. Es wird in Bao (verifiziertes Streaming), dem Rust-Ökosystem und zunehmend in Content-Addressed Storage verwendet. Der Nachteil: Es ist neuer und noch nicht in NIST-Standards, also können regulierte Branchen es nicht verwenden. Für interne Tools und performance-sensitive Anwendungen ist BLAKE3 ausgezeichnet.

Hash-Kollisionen: Was sie in der Praxis bedeuten

Eine Kollision sind zwei verschiedene Eingaben, die die gleiche Hash-Ausgabe produzieren. Für einen 128-Bit-Hash (MD5) sagt das Geburtstagsparadoxon, dass du wahrscheinlich nach etwa 2^64 Versuchen (~18 Trillionen) eine Kollision findest. Für SHA-256 (256 Bits) sind es 2^128 Versuche — mehr als die Anzahl der Atome im beobachtbaren Universum. In der Praxis werden SHA-256-Kollisionen nie durch Brute Force gefunden.

Aber Brute Force ist nicht der einzige Angriff. Kryptoanalyse nutzt mathematische Schwächen im Algorithmus aus. MD5s Kompressionsfunktion hat strukturelle Fehler, die es erlauben, Kollisionen in Sekunden auf einem Laptop zu finden (nicht 2^64 Versuche, sondern etwa 2^18 — ein paar hunderttausend Operationen). SHA-1 erfordert etwa 2^63 Operationen (immer noch teuer, aber machbar für Nationalstaaten und gut finanzierte Angreifer).

Was kann ein Angreifer mit einer Kollision tun? Er kann zwei Dokumente mit dem gleichen Hash erstellen — eines harmlos, eines bösartig. Er lässt das harmlose signieren/zertifizieren und substituiert dann das bösartige. So nutzte die Flame-Malware (2012) eine MD5-Kollision, um ein Microsoft-Windows-Update-Zertifikat zu fälschen. Die Zertifizierungsstelle signierte ein legitim aussehendes Zertifikat, aber die Angreifer hatten ein kollidierendes Zertifikat, das für ihre Malware funktionierte.

Für Nicht-Sicherheits-Anwendungen sind Kollisionen kein Thema. Wenn du MD5 als Hash-Table-Key oder Cache-Identifier verwendest, bedeutet eine Kollision nur, dass zwei verschiedene Eingaben auf den gleichen Bucket mappen — dein Code handhabt das mit Chaining oder Open Addressing. Die Wahrscheinlichkeit ist so niedrig (1 zu 2^64 für zufällige Eingaben), dass du es in der Praxis nie sehen wirst. Die Sicherheitsbedenken betreffen nur absichtlich erzeugte Kollisionen.

HMAC: Wenn du Authentifizierung brauchst, nicht nur Hashing

Ein einfacher Hash verifiziert Integrität (die Daten wurden nicht versehentlich beschädigt), aber nicht Authentizität (die Daten kamen von dem, von dem du denkst). Ein Angreifer, der die Daten modifiziert, kann den Hash neu berechnen. HMAC (Hash-based Message Authentication Code) löst das, indem es einen geheimen Schlüssel in den Hash mischt: HMAC(key, message) = Hash((key ⊕ opad) || Hash((key ⊕ ipad) || message)).

Verwende HMAC wenn: du API-Webhook-Signaturen verifizierst (Stripe, GitHub, Shopify verwenden alle HMAC-SHA256), manipulationssichere Tokens erstellst (JWT-Signaturen verwenden HMAC-SHA256 mit dem HS256-Algorithmus) oder validierst, dass Daten nicht im Transit von einem Angreifer modifiziert wurden. Der Schlüssel muss geheim bleiben — wenn der Angreifer den Schlüssel hat, bietet HMAC keinen Schutz.

Häufiger Fehler: Hash(key + message) statt HMAC verwenden. Das ist anfällig für Length-Extension-Angriffe — ein Angreifer, der Hash(key + message) kennt, kann Hash(key + message + attacker_data) berechnen, ohne den Schlüssel zu kennen. SHA-256 und MD5 sind beide dafür anfällig. HMACs Doppel-Hashing-Konstruktion verhindert das. SHA-3 ist nicht anfällig für Length Extension (andere interne Struktur), aber verwende trotzdem HMAC für Konsistenz.

Im Code: Node.js hat crypto.createHmac("sha256", key).update(message).digest("hex"). Python hat hmac.new(key, message, hashlib.sha256).hexdigest(). Implementiere HMAC nie selbst — verwende die Standardbibliothek deiner Sprache. Die Konstruktion sieht einfach aus, aber Timing-Angriffe auf den Vergleich (=== statt crypto.timingSafeEqual verwenden) können den korrekten HMAC Byte für Byte leaken.

Häufige Fehler mit Hash-Funktionen

Fehler 1: SHA-256 für Passwörter verwenden. SHA-256 ist schnell — das ist schlecht für Passwörter. Eine RTX 4090 berechnet 22 Milliarden SHA-256-Hashes pro Sekunde. Ein 8-Zeichen-Passwort aus dem vollen ASCII-Set (6,6 Billiarden Kombinationen) fällt in 3,5 Tagen. Verwende bcrypt/Argon2id, die das auf Jahrhunderte reduzieren. Wenn du User-Passwörter mit SHA-256 speicherst (selbst mit Salt), migriere sofort.

Fehler 2: Hashes mit == in einem Sicherheitskontext vergleichen. String-Vergleich bricht beim ersten unterschiedlichen Zeichen ab und gibt Timing-Informationen preis. Ein Angreifer kann den korrekten HMAC Zeichen für Zeichen bestimmen, indem er Antwortzeiten misst. Verwende Constant-Time-Vergleich: crypto.timingSafeEqual() in Node.js, hmac.compare_digest() in Python, subtle.ConstantTimeCompare() in Go.

Fehler 3: Hashes für "kürzere IDs" abschneiden. Wenn du die ersten 8 Zeichen eines SHA-256-Hashes nimmst (32 Bits), springt deine Kollisionswahrscheinlichkeit auf 50% bei nur 77.000 Elementen (Geburtstagsparadoxon). Ich habe das bei URL-Shortenern und Cache-Keys gesehen. Wenn du kürzere Identifier brauchst, verwende einen zweckgebundenen Short-ID-Generator (nanoid, hashids) statt einen kryptographischen Hash abzuschneiden.

Fehler 4: Annehmen, Hash = Verschlüsselung. Hashing ist Einweg — du kannst die Eingabe nicht aus der Ausgabe wiederherstellen. Verschlüsselung ist Zweiweg — du kannst mit dem Schlüssel entschlüsseln. Wenn du Daten speichern musst, die du später lesen willst (API-Keys, Kreditkartennummern), verwende Verschlüsselung (AES-256-GCM). Wenn du Daten verifizieren musst, ohne sie zu speichern (Passwörter, Integritätsprüfungen), verwende Hashing. Das sind grundlegend verschiedene Operationen.