Auf einen Blick
- Eine Hashfunktion $H: \{0,1\}^* \to \{0,1\}^n$ bildet Eingaben beliebiger Länge auf eine feste Ausgabelänge $n$ ab.
- Drei Sicherheitseigenschaften: Preimage, Second Preimage und Collision Resistance.
- Birthday-Angriff: Kollisionen sind bereits nach $\approx 2^{n/2}$ Versuchen wahrscheinlich – nicht $2^n$.
- MD5 und SHA-1 gelten als gebrochen. Standards heute: SHA-2 und SHA-3.
- Anwendungen: Integritätsprüfung, Passwort-Speicherung (mit Salt + bcrypt/Argon2), HMAC, digitale Signaturen.
Kernkonzepte
Definition Hashfunktion
Eine kryptografische Hashfunktion ist eine Abbildung $$H : \{0,1\}^* \to \{0,1\}^n$$ die beliebig lange Nachrichten $m$ auf einen Hashwert $H(m)$ fester Länge $n$ Bit abbildet (auch Digest genannt).
Wichtige Eigenschaften:
- Deterministisch: gleiche Eingabe $\Rightarrow$ gleicher Hashwert.
- Effizient berechenbar: $H(m)$ ist in linearer Zeit in $|m|$ berechenbar.
- Avalanche-Effekt: kleinste Änderung von $m$ ändert den Hash vollständig.
- Feste Ausgabelänge unabhängig von $|m|$.
Die drei Sicherheitsanforderungen
| Eigenschaft | Formal | Angreifer-Ziel |
|---|---|---|
| Preimage Resistance (Einwegfunktion) | Gegeben $h$, finde $m$ mit $H(m)=h$. | Aus dem Hash das Urbild rekonstruieren. |
| Second Preimage Resistance (schwache Kollisionsresistenz) | Gegeben $m$, finde $m' \neq m$ mit $H(m') = H(m)$. | Zu einer fixierten Nachricht ein Duplikat finden. |
| Collision Resistance (starke Kollisionsresistenz) | Finde irgendein Paar $(m, m')$ mit $m \neq m'$ und $H(m)=H(m')$. | Beliebige Kollision – ist der stärkste Angriff. |
Aufwand für generische Angriffe bei $n$-Bit-Ausgabe:
- Preimage / Second Preimage: $\approx 2^n$ Versuche (Brute Force).
- Collision: $\approx 2^{n/2}$ Versuche (Geburtstagsangriff, "Wurzel-Angriff").
Geburtstagsproblem & Birthday-Angriff
Das Geburtstagsparadoxon: bei $23$ zufällig gewählten Personen ist die Wahrscheinlichkeit für einen gemeinsamen Geburtstag bereits $> 50\%$, obwohl es $365$ Möglichkeiten gibt. Grund: Wir suchen ein Paar, nicht einen konkreten Tag.
Näherung: Für einen Kollisionsanteil von $50\%$ genügen ca. $$k \approx 1{,}177 \cdot \sqrt{N}$$ Versuche bei $N$ möglichen Werten. Für Hashes mit $n$ Bit gilt $N = 2^n$, also: $$k \approx 2^{n/2}.$$
Konsequenz: Um $128$ Bit Sicherheit gegen Kollisionen zu erreichen, benötigt man mindestens $n=256$ Bit Ausgabelänge.
Merkle-Damgård-Konstruktion
Klassisches Bauprinzip von MD5, SHA-1 und SHA-2. Idee: eine feste Kompressionsfunktion $f$ wird iterativ auf Nachrichtenblöcke angewendet.
Vorgehen:
- Padding der Nachricht $m$ auf ein Vielfaches der Blocklänge (inkl. Längenkodierung).
- Aufteilen in Blöcke $m_1, m_2, \ldots, m_t$.
- Initialisierung: $h_0 = IV$ (fester Startwert).
- Iteration: $h_i = f(h_{i-1}, m_i)$ für $i=1,\ldots,t$.
- Ausgabe: $H(m) = h_t$.
Schwäche: Length-Extension-Angriff möglich – wer $H(m)$ und $|m|$ kennt, kann $H(m \| \text{pad} \| x)$ für beliebige $x$ berechnen, ohne $m$ zu kennen. Deshalb ist $H(k \| m)$ als MAC unsicher $\Rightarrow$ HMAC-Konstruktion.
Konkrete Hashverfahren im Überblick
| Verfahren | Ausgabe | Runden | Struktur | Status |
|---|---|---|---|---|
| MD5 | 128 Bit | 64 | Merkle-Damgård | Gebrochen (Kollisionen in Sekunden) |
| SHA-1 | 160 Bit | 80 | Merkle-Damgård | Gebrochen seit 2017 (SHAttered) |
| SHA-256 | 256 Bit | 64 | Merkle-Damgård (SHA-2) | Sicher |
| SHA-384 | 384 Bit | 80 | Merkle-Damgård (SHA-2) | Sicher |
| SHA-512 | 512 Bit | 80 | Merkle-Damgård (SHA-2) | Sicher |
| SHA-3 (Keccak) | 224/256/384/512 Bit | 24 | Sponge-Konstruktion | Sicher, andere Struktur |
Sponge-Konstruktion (SHA-3)
Statt Merkle-Damgård verwendet Keccak/SHA-3 eine Sponge-Konstruktion:
- Zustand der Größe $b = r + c$ Bit ($r$ = Rate, $c$ = Kapazität).
- Absorbing-Phase: Nachrichtenblöcke werden per XOR in die Rate eingespeist, danach Permutation $f$.
- Squeezing-Phase: aus der Rate werden Ausgabeblöcke extrahiert, dazwischen Permutation.
Vorteile: keine Length-Extension-Angriffe, flexible Ausgabelängen, ohne separate Kompressionsfunktion.
HMAC – Hash-based Message Authentication Code
HMAC berechnet einen schlüsselabhängigen Hash und schützt vor Length-Extension-Angriffen: $$\text{HMAC}(k, m) = H\bigl(\, (k' \oplus \text{opad}) \,\|\, H( (k' \oplus \text{ipad}) \,\|\, m ) \,\bigr)$$ mit:
- $k'$ = Schlüssel $k$ auf Blocklänge gepaddet (bzw. gehasht, falls zu lang),
- $\text{ipad} = \underbrace{\texttt{0x36 0x36 \ldots}}_{\text{Blocklänge}}$,
- $\text{opad} = \underbrace{\texttt{0x5c 0x5c \ldots}}_{\text{Blocklänge}}$.
Die doppelte Struktur (inner + outer Hash) sichert die Konstruktion beweisbar gegen die typischen Angriffe auf $H(k\|m)$.
Salting & Passwort-Hashing
Beim Speichern von Passwörtern werden nicht die Passwörter selbst, sondern Hashwerte abgelegt. Ohne Salt sind sog. Rainbow Tables (vorab berechnete Hash-Tabellen) möglich.
Mit Salt $s$ speichert der Server: $$(s,\ H(\text{passwort} \,\|\, s))$$ Jeder Benutzer hat einen individuellen, zufälligen Salt $\Rightarrow$ Rainbow Tables müssten pro Salt neu berechnet werden.
Zusätzlich sollten langsame Passwort-Hashfunktionen verwendet werden:
- bcrypt: konfigurierbarer Kostenparameter (Iterationen).
- scrypt: zusätzlich speicherhart.
- Argon2: aktueller Standard, Sieger des Password Hashing Competition 2015.
Ziel: Brute-Force-Angriffe werden künstlich verlangsamt.
Anwendungen
- Integritätsprüfung: Download-Hashes (z.B. SHA-256 einer ISO-Datei).
- Passwort-Speicherung: nie im Klartext, immer mit Salt + langsamer Hashfunktion.
- Digitale Signaturen: signiert wird der Hash der Nachricht, nicht die Nachricht selbst.
- HMAC: Nachrichtenauthentifizierung mit gemeinsamem Schlüssel.
- Blockchain / Merkle-Trees: Verkettung von Blöcken und effiziente Integritätsbeweise.
- Deduplikation: Identifikation gleicher Dateien anhand ihres Hashwerts.
Merksätze
🧮 Rechenaufgaben mit Lösung
Klick auf eine Aufgabe, um den vollständigen Lösungsweg zu sehen.
R1 · Birthday-Aufwand für SHA-256
Lösungsweg
1. Ausgabelänge: SHA-256 liefert $n = 256$ Bit.
2. Birthday-Formel: Kollisionen sind ab $$k \approx 2^{n/2} = 2^{256/2} = 2^{128}$$ Versuchen wahrscheinlich.
3. Umrechnung in Zehnerpotenz: Mit $\log_{10}(2) \approx 0{,}30103$ folgt $$2^{128} = 10^{128 \cdot 0{,}30103} \approx 10^{38{,}53} \approx 3{,}4 \cdot 10^{38}.$$
4. Einordnung: Bei $10^{18}$ Hashes/s wären das $3{,}4 \cdot 10^{20}$ s $\approx 10^{13}$ Jahre – deutlich mehr als das Alter des Universums.
R2 · Kollisionsaufwand für MD5
Lösungsweg
1. Birthday: $k \approx 2^{128/2} = 2^{64}$.
2. Umrechnung: $$2^{64} = 10^{64 \cdot 0{,}30103} \approx 10^{19{,}27} \approx 1{,}8 \cdot 10^{19}.$$
3. Zeit bei $10^{12}$ Hashes/s: $$t = \frac{1{,}8 \cdot 10^{19}}{10^{12}\,\text{s}^{-1}} = 1{,}8 \cdot 10^{7}\,\text{s}.$$ Umrechnung: $1{,}8 \cdot 10^{7}\,\text{s} / 86\,400\,\text{s/Tag} \approx 208$ Tage.
4. Realität: Für MD5 existieren strukturelle Angriffe (Wang et al., 2004), die Kollisionen in Sekunden auf einem Laptop erzeugen – MD5 ist damit vollständig gebrochen.
R3 · HMAC-Aufbau und Begründung
Definition
Sei $B$ die Blocklänge der Hashfunktion (z.B. $64$ Byte bei SHA-256). Der Schlüssel $k$ wird auf Länge $B$ Byte gebracht ($k'$).
ipad = 0x36 0x36 ... 0x36 (B Bytes) opad = 0x5c 0x5c ... 0x5c (B Bytes)
Dann gilt: $$\text{HMAC}(k, m) = H\bigl( (k' \oplus \text{opad}) \,\|\, H( (k' \oplus \text{ipad}) \,\|\, m ) \bigr).$$
Warum doppelt?
1. Innerer Hash: $H((k' \oplus \text{ipad}) \| m)$ bindet den Schlüssel an die Nachricht.
2. Length-Extension: Ein reines $H(k \| m)$ ist bei Merkle-Damgård-Hashes angreifbar: aus $H(k \| m)$ lässt sich $H(k \| m \| \text{pad} \| x)$ berechnen, ohne $k$ zu kennen.
3. Äußerer Hash: Der zweite $H$-Aufruf verhindert diesen Angriff, da der Ausgang nicht mehr direkt der interne Zustand am Nachrichtenende ist.
4. Verschiedene Padding-Konstanten: ipad und opad unterscheiden sich in jedem Bit – so entstehen zwei effektiv unabhängige "Schlüssel", was den formalen Sicherheitsbeweis ermöglicht.
R4 · Passwort-Speicherung mit Salt
Sommer2026. Der Server generiert einen Salt abc123. Was speichert der Server, und wie prüft er ein Login-Passwort?
Registrierung
- Zufälligen Salt erzeugen: $s = $
abc123. - Konkatenieren:
"Sommer2026" || "abc123". - Hash berechnen: $h = H(\text{"Sommer2026abc123"})$.
- Speichern: das Tupel $(s, h)$ in der Nutzertabelle, plus Nutzername.
| user | salt | hash |
|---|---|---|
| titus | abc123 | H("Sommer2026abc123") |
Login-Prüfung
- Nutzer sendet Passwort $p'$.
- Server liest gespeicherten Salt $s$ =
abc123. - Berechnet $h' = H(p' \| s)$.
- Vergleicht $h'$ mit gespeichertem $h$ (in konstanter Zeit gegen Timing-Angriffe).
Zusätzlich empfehlenswert
Anstelle eines einfachen SHA-256 mit Salt sollte eine langsame Passwort-Hashfunktion wie Argon2 verwendet werden: $h = \text{Argon2}(p, s, \text{Kosten})$.
R5 · Rainbow-Table-Speicherbedarf
Naive Rechnung
MD5 hat $128$ Bit $= 16$ Byte. Bei $10\,\text{GB} = 10 \cdot 10^{9}$ Byte reine Hashwerte: $$\frac{10 \cdot 10^{9}\,\text{Byte}}{16\,\text{Byte/Hash}} = 6{,}25 \cdot 10^{8}\ \text{Hashes}.$$
Reale Rainbow Tables
Rainbow Tables speichern nicht $(p, H(p))$-Paare, sondern Ketten aus abwechselnden Hash- und Reduktionsfunktionen. Nur Kettenanfang und -ende werden gespeichert, was eine Zeit-Speicher-Abwägung erlaubt.
Mit dieser Kompression decken $10\,\text{GB}$ typischerweise $10^{12}$ bis $10^{13}$ Passwörter ab – genug für nahezu alle menschenlesbaren Passwörter bis 8-10 Zeichen.
Warum Salt hilft
Ein $b$-Bit-Salt vergrößert den Suchraum multiplikativ um $2^{b}$. Bei $b=128$ müssten für jeden Nutzer eine eigene Table von $10^{12}$ Einträgen gebaut werden – nicht mehr realistisch.
R6 · Geburtstagsformel für 50% Kollision
Allgemeine Formel
Die Wahrscheinlichkeit für mindestens eine Kollision unter $k$ Werten aus $N$ Möglichkeiten ist $$P(k, N) \approx 1 - e^{-k^2/(2N)}.$$ Setze $P = 0{,}5$ und löse: $$0{,}5 = 1 - e^{-k^2/(2N)} \iff e^{-k^2/(2N)} = 0{,}5 \iff \frac{k^2}{2N} = \ln 2.$$ Also $$k = \sqrt{2 N \ln 2} \approx 1{,}177 \cdot \sqrt{N}.$$
Klassisches Geburtstagsproblem ($N=365$)
$k \approx 1{,}177 \cdot \sqrt{365} \approx 1{,}177 \cdot 19{,}1 \approx 22{,}5 \Rightarrow k=23$.
128-Bit-Hash ($N = 2^{128}$)
$k \approx 1{,}177 \cdot 2^{64} \approx 1{,}177 \cdot 1{,}8 \cdot 10^{19} \approx 2{,}17 \cdot 10^{19}$.
Für Klausurzwecke reicht die Näherung $k \approx 2^{n/2} = 2^{64}$.
R7 · Nötige Ausgabelänge für 128 Bit Sicherheit
Herleitung
Generischer Kollisionsangriff kostet $\approx 2^{n/2}$. Für $128$ Bit Sicherheit: $$2^{n/2} \geq 2^{128} \iff \frac{n}{2} \geq 128 \iff n \geq 256.$$
Passende Verfahren
| Hash | n | Kollisionsaufwand | ausreichend? |
|---|---|---|---|
| MD5 | 128 | 2^64 | Nein (auch gebrochen) |
| SHA-1 | 160 | 2^80 | Nein |
| SHA-256 | 256 | 2^128 | Ja |
| SHA-3-256 | 256 | 2^128 | Ja |
| SHA-512 | 512 | 2^256 | Deutlich mehr als nötig |
Übungsfragen
F1 Was sind die drei Sicherheitseigenschaften einer kryptografischen Hashfunktion?
- Preimage Resistance (Einwegfunktion): Zu gegebenem $h$ ist es schwer, ein $m$ mit $H(m)=h$ zu finden.
- Second Preimage Resistance: Zu gegebenem $m$ ist es schwer, ein $m' \neq m$ mit $H(m)=H(m')$ zu finden.
- Collision Resistance: Es ist schwer, irgendein Paar $(m, m')$ mit $m \neq m'$ und $H(m)=H(m')$ zu finden.
Aufwand: Preimage und Second Preimage $\approx 2^n$, Collision nur $\approx 2^{n/2}$.
F2 Warum reichen bei einem 256-Bit-Hash bereits $2^{128}$ Versuche für eine Kollision?
Wegen des Geburtstagsparadoxons: Man sucht kein bestimmtes Urbild, sondern irgendein kollidierendes Paar. Die Anzahl möglicher Paare wächst quadratisch mit $k$, sodass die Kollisionswahrscheinlichkeit bereits ab $$k \approx \sqrt{2 \cdot 2^n \cdot \ln 2} \approx 1{,}177 \cdot 2^{n/2}$$ Versuchen nennenswert wird. Für $n=256$: $k \approx 2^{128}$.
F3 Wo liegt der Unterschied zwischen Second Preimage Resistance und Collision Resistance?
- Second Preimage: die Nachricht $m$ ist fest vorgegeben. Angreifer sucht $m' \neq m$ mit gleichem Hash. Aufwand $\approx 2^n$.
- Collision: Beide Nachrichten sind frei wählbar. Aufwand nur $\approx 2^{n/2}$ (Birthday).
Aus Collision Resistance folgt Second Preimage Resistance (aber nicht umgekehrt). Deshalb ist Collision Resistance die stärkere Eigenschaft.
F4 Warum sollte man MD5 und SHA-1 nicht mehr verwenden?
- MD5 (128 Bit): Birthday-Grenze bei $2^{64}$, aber strukturelle Angriffe (Wang et al., 2004) liefern Kollisionen in Sekunden. Chosen-Prefix-Kollisionen wurden bereits für gefälschte X.509-Zertifikate ausgenutzt.
- SHA-1 (160 Bit): 2017 durch Google/CWI (SHAttered) praktisch gebrochen – zwei PDFs mit gleichem SHA-1 wurden veröffentlicht. Kosten damals ca. $110$ GPU-Jahre.
Standards heute: SHA-256, SHA-3 oder BLAKE2/BLAKE3.
F5 Was ist Salting und wozu dient es?
Ein Salt ist ein zufälliger, pro Nutzer individueller Wert, der beim Hashen des Passworts angehängt wird: $H(p \| s)$. Der Salt wird zusammen mit dem Hash gespeichert – er muss nicht geheim sein.
Zweck:
- Vernichtet Rainbow-Tables: vorab berechnete Tabellen müssten pro Salt neu berechnet werden.
- Verhindert, dass zwei Nutzer mit identischem Passwort denselben Hash haben.
- Erschwert Massenangriffe: jeder Account muss einzeln angegriffen werden.
F6 Warum ist bcrypt/Argon2 besser als reines SHA-256 für Passwörter?
SHA-256 ist auf Geschwindigkeit optimiert – moderne GPUs berechnen $10^{10}$ Hashes/s. Für Passwörter ist genau das schlecht: Brute-Force wird trivial.
bcrypt / scrypt / Argon2 sind bewusst langsam und (bei Argon2/scrypt) speicherhart:
- Konfigurierbare Kostenparameter (Iterationen, Speicher, Parallelität).
- Ein einzelner Hash dauert z.B. $100$ ms, Brute-Force skaliert nicht linear mit GPU-Kernen.
- Argon2 zusätzlich speicherhart $\Rightarrow$ ASIC/GPU-Angriffe teuer.
Faustregel: für Passwörter immer bcrypt/scrypt/Argon2 statt einer schnellen Hashfunktion.
F7 Was ist HMAC und warum ist es sicherer als $H(k \| m)$?
HMAC ist eine schlüsselabhängige Hashkonstruktion zur Nachrichtenauthentifizierung: $$\text{HMAC}(k, m) = H\bigl((k' \oplus \text{opad}) \,\|\, H((k' \oplus \text{ipad}) \,\|\, m)\bigr).$$
$H(k \| m)$ ist bei Merkle-Damgård-Hashes wegen Length-Extension-Angriffen unsicher: Aus $H(k \| m)$ und $|m|$ lässt sich $H(k \| m \| \text{pad} \| x)$ berechnen, ohne $k$ zu kennen. Ein Angreifer kann so gültige MACs für erweiterte Nachrichten erzeugen.
HMAC umgeht das durch den äußeren Hash-Aufruf mit opad – der finale Zustand ist nicht mehr der interne Zustand am Nachrichtenende, sondern das Ergebnis eines neuen Hashings.
F8 Wozu dient eine Hashfunktion bei einer digitalen Signatur?
Bei RSA/DSA/ECDSA wird nicht die Nachricht $m$ selbst signiert, sondern $H(m)$: $$\sigma = \text{Sign}_{sk}(H(m)).$$
Gründe:
- Effizienz: die Signaturoperation ist teuer (asymmetrisch) und arbeitet auf festem Blockformat.
- Feste Größe: unabhängig von der Nachrichtenlänge.
- Sicherheit: verhindert existentielle Fälschungen (z.B. bei RSA würde ohne Hash die multiplikative Struktur $\text{Sig}(m_1 \cdot m_2) = \text{Sig}(m_1) \cdot \text{Sig}(m_2) \mod n$ Fälschungen erlauben).
- Domain Separation: Hash mit strukturiertem Padding trennt Anwendungsfälle sauber.
Voraussetzung: die verwendete Hashfunktion muss kollisionsresistent sein, sonst könnte ein Angreifer zwei Nachrichten mit gleichem Hash finden und eine Signatur austauschen.
F9 Was ist der Avalanche-Effekt und warum ist er wichtig?
Der Avalanche-Effekt beschreibt: Eine minimale Änderung an der Eingabe (z.B. ein einzelnes Bit) ändert im Idealfall ca. die Hälfte der Ausgabebits – die Ausgabe wirkt zufällig verändert.
Wichtig, weil sonst Ähnlichkeiten von Eingaben in den Hashwerten sichtbar wären, was Angriffe (differentielle Kryptanalyse, gezielte Kollisionssuche) erleichtern würde.
F10 Was ist der Unterschied zwischen SHA-2 und SHA-3 in der Konstruktion?
- SHA-2: Merkle-Damgård-Konstruktion mit Kompressionsfunktion. Nachrichte wird geblockt, iterativ komprimiert. Anfällig für Length-Extension-Angriffe.
- SHA-3 (Keccak): Sponge-Konstruktion. Zustand $b = r+c$ Bit, Absorbing- und Squeezing-Phase mit fester Permutation $f$. Keine Kompressionsfunktion, keine Length-Extension-Anfälligkeit.
SHA-3 wurde als "Sicherheitsreserve" gewählt, falls SHA-2 einmal geschwächt würde – die grundlegend andere Konstruktion macht gemeinsame Angriffe unwahrscheinlich.
F11 Warum ist der Salt beim Passwort-Hashing nicht geheim?
Der Salt hat nicht den Zweck, Informationen zu verstecken, sondern jeden Passwort-Hash zu individualisieren. Dadurch:
- Rainbow Tables werden nutzlos, weil sie pro Salt neu berechnet werden müssten.
- Zwei Nutzer mit identischem Passwort haben unterschiedliche Hashes.
Beim Login muss der Server den Salt kennen, um den Hash reproduzieren zu können – also wird er zusammen mit dem Hash im Klartext gespeichert.
F12 Wie hängt Kollisionsresistenz mit der Ausgabelänge zusammen?
Wegen des Birthday-Angriffs kostet Kollisionsfinden nur $\approx 2^{n/2}$. Die effektive Kollisionssicherheit ist also halbiert gegenüber der Ausgabelänge:
- $n = 128$ (MD5): nur $64$ Bit Kollisionsresistenz $\Rightarrow$ zu wenig.
- $n = 160$ (SHA-1): $80$ Bit $\Rightarrow$ heute unzureichend.
- $n = 256$ (SHA-256, SHA-3-256): $128$ Bit $\Rightarrow$ aktueller Standard.
- $n = 512$ (SHA-512): $256$ Bit $\Rightarrow$ für Langzeit-Sicherheit.
Faustregel: Für $k$ Bit Kollisionssicherheit braucht man $n \geq 2k$ Bit Ausgabelänge.