Kryptografische Hash Funktionen

Dozent:

Prof. Dr. Michael Eichberg

Kontakt:

michael.eichberg@dhbw-mannheim.de

Basierend auf:

Cryptography and Network Security - Principles and Practice, 8th Edition, William Stallings

Version:
2024-05-09
Folien:

https://delors.github.io/sec-hashfunktionen/folien.rst.html

https://delors.github.io/sec-hashfunktionen/folien.rst.html.pdf

Fehler auf Folien melden:

https://github.com/Delors/delors.github.io/issues

Hashfunktionen - Grundlagen

Hashfunktionen

Beispiel: Berechnung von Hashwerten mittels MD5

md5("Hello") = 8b1a9953c4611296a827abf8c47804d7
md5("hello") = 5d41402abc4b2a76b9719d911017c592
md5("Dieses Passwort ist wirklich total sicher
      und falls Du es mir nicht glaubst, dann
      tippe es zweimal hintereinander blind
      fehlerfrei ein.")
             = 8fcf22b1f8327e3a005f0cba48dd44c8

Sicherheitsanforderungen an kryptografische Hashfunktion I

Variable Eingabegröße:

H kann auf einen Block beliebiger Größe angewendet werden.

Pseudozufälligkeit:

Die Ausgabe von \(H\) erfüllt die Standardtests für Pseudozufälligkeit.

Einweg Eigenschaft:

Es ist rechnerisch/praktisch nicht machbar für einen gegeben Hashwert \(h\) ein \(N\) zu finden so dass gilt: \(H(N) = h\)

(Preimage resistant; one-way property)

Sicherheitsanforderungen an kryptografische Hashfunktion II

Schwache Kollisionsresistenz:

Es ist rechnerisch nicht machbar für eine gegebene Nachricht M eine Nachricht N zu finden so dass gilt: \(M \neq N\) mit \(H(M) = H(N)\)

(Second preimage resistant; weak collision resistant)

Starke Kollisionsresistenz:

Es ist rechnerisch unmöglich ein paar \((N,M)\) zu finden so dass gilt: \(H(M) = H(N)\).

(Collision resistant; strong collision resistant)

Hintergrund

Im Deutschen wird auch von Urbild-Angriffen gesprochen. In dem Fall ist preimage resistance (d. h. die Einweg Eigenschaft) gleichbedeutend damit, dass man nicht effektiv einen Erstes-Urbild-Angriff durchführen kann. Hierbei ist das Urbild die ursprüngliche Nachricht \(M\), die gehasht wurde.

Second preimage resistance ist dann gleichbedeutend damit, dass man nicht effektiv einen Zweites-Urbild-Angriff durchführen kann. Es ist nicht möglich zu einer Nachricht M eine zweite Nachricht N (d. h. ein zweites Urbild) zu finden, die für eine gegebene Hashfunktion den gleich Hash aufweist.

Beziehung zwischen den Sicherheitsanforderungen an Hashfunktionen

Beziehung zwischen den Eigenschaften von Hashfunktionen

Nachrichtenauthentifizierung - vereinfacht

Nachrichten können auf verschiedene Weisen authentifiziert werden, so dass Man-in-the-Middle-Angriffe (MitM)[1] verhindert werden können.

drawings/digests/all_encrypted.svg
drawings/digests/hash_encrypted.svg
drawings/digests/secret_appended.svg
drawings/digests/secret_encrypted.svg

Im ersten Szenario wird der Hash an die Nachricht angehängt und als ganzes verschlüsselt. Wir erhalten Vertraulichkeit und Authentizität.

Im zweiten Szenario wird der Hash der Nachricht berechnet und dann verschlüsselt. Der Empfänger kann den Hash berechnen und mit dem entschlüsselten Hash vergleichen. Wir erhalten Authentizität, aber keine Vertraulichkeit.

Im dritten Szenario wird an die Nachricht ein geteiltes Secret angehängt und alles zusammen gehasht. Die Nachricht wird dann mit dem Ergebnis der vorhergehenden Operation zusammen verschickt.

Im letzten Szenario werden alle Ansätze

Digitale Signaturen - vereinfacht

Digitale Signaturen dienen dem Nachweis der Authentizität einer Nachricht und der Integrität der Nachricht. Jeder, der einen öffentlichen Schlüssel hat, kann die Signatur überprüfen, aber nur der Besitzer des privaten Schlüssels kann die Signatur erstellen.

drawings/signatures/just_authentication.svg
drawings/signatures/authentication_and_encryption.svg

Anforderungen an die Resistenz von Hashfunktionen

Preimage Resistant

Second Preimage Resistant

Collision Resistant

Hash + Digitale Signaturen

Einbruchserkennung und Viruserkennung

Hash + Symmetrische Verschlüsselung

Passwortspeicherung

MAC

Einbruchserkennung und Viruserkennung - Hintergrund

Bei der Einbruchserkennung und Viruserkennung ist second preimage Resistenz erforderlich. Andernfalls könnte ein Angreifer seine Malware so schreiben, ass diese einen Hash wie eine vorhandene gutartige Software hat und so verhindern, dass die Malware auf eine schwarze Liste gesetzt werde kann, ohne den Kollateralschaden, dass auch die gutartige Software fälschlicherweise als Malware erkannt wird.

Aufwand eines Kollisionsangriffs

Ein Kollisionsangriff erfordert weniger Aufwand als ein preimage oder ein second preimage Angriff.

Dies wird durch das Geburtstagsparadoxon erklärt. Wählt man Zufallsvariablen aus einer Gleichverteilung im Bereich von \(0\) bis \(N-1\), so übersteigt die Wahrscheinlichkeit, dass ein sich wiederholendes Element gefunden wird, nach \(\sqrt{N}\) Auswahlen \(0,5\). Wenn wir also für einen m-Bit-Hashwert Datenblöcke zufällig auswählen, können wir erwarten, zwei Datenblöcke innerhalb von \(\sqrt{2^m} = 2^{m/2}\) Versuchen zu finden.

Effizienzanforderungen an kryptografische Hashfunktionen

Effizienz bei der Verwendung für Signaturen und zur Authentifizierung:

Bei der Verwendung zur Nachrichtenauthentifizierung und für digitale Signaturen ist \(H(N)\) für jedes beliebige \(N\) relativ einfach zu berechnen. Dies soll sowohl Hardware- als auch Softwareimplementierungen ermöglichen.

vs.

Brute-Force-Angriffe auf Passwörter erschweren:

Bei der Verwendung für das Hashing von Passwörtern soll es schwierig sein den Hash effizient zu berechnen, selbst auf spezialisierter Hardware (GPUs, ASICs).

Struktur eines sicheren Hash-Codes

drawings/hash_functions/structure_of_secure_hash_codes.svg

\(IV\) = Initialer Wert (Algorithmus-abhängig)

\(CV_i\) = Verkettungsvariable

\(Y_i\) = ier Eingabeblock

\(f\) = Kompressions-funktion

\(n\) = Länge des Blocks

\(L\) = Anzahl der Eingabeblöcke

\(b\) = Länge des Eingabeblocks

Übung

XOR als Hashfunktion

Warum ist eine einfache Hash-Funktion, die einen 256-Bit-Hash-Wert berechnet, indem sie ein XOR über alle Blöcke einer Nachricht durchführt, im Allgemeinen ungeeignet?

MTAwMDAw:De/lba18laNIM2EqIfQeewOvHgigKfBwdqtrQY+D2eE=:Mlu92VhhZwNr/vGd:lGbchAASXBw34twYyWreQri20VSc/76Fa7nZGn15ekeaDK8iof6yGsmHTuETow3n4oE3R6/DyyeXxsUPzqdglzlFBg2Ct7O4OEBhQRfzBVv+/Hb/4rABoEVY83JmVxvpGXblfpnaJPWtQLFh3jFUPt9CT7IjvZ9rnvDwA8Dl58pHpFky2htR096v3dKJ3msvMh47z7KyoOMP/mPvD5IN7jJ7wvmmP4YBpR8qibXWi5FVyt9I+qtvpgtFmGsey78ZEkEc689jY/jmJr4zR1XwK7nG3lnQAaACcy9g+pEXZEU5Wyg1bGRbz8woIwzEM6I/mDKyXSksny541GwWF7WYJ5zeIW3hjKllv0AM8WCHleCqzBIaNeiXnGsvm62/dkqy1jwA58Wcn5gfrIsq3nlsrO2MNgWHBCdTpCrqfwNNTX/riAM+RIYsk2nCYUM/Q6M12LvCEnH8og==

Übung

Bewertung der Sicherheit

MTAwMDAw:/ZGWPhnNIr6ESQwu+8HKkokehUYYKFURvhmzeTuLbPs=:Ho1vxOY5E6cgliGZ:vLRdYS7wvQa6yc2P7rJ3gpSDiC1la06b5OCydEwFIgbV03VbwGswvqcCtPUjcAvhYBVnHPY0oihA5reMDGTkhdcQ39/ZL/y2QEiPcPj26WY73ZMCJOZJZcIy5k5C6L5HSn2qVJAQW37w6yeIDuW5xX2zhsI9thL2znw3ZtA6AogksZZeRhypDPNeh8bHVR3kzpEXBwZoO3Z2kQG9QdNn9M9J1t7TjE4Pf4qR4ijr7hYtNk+AzMJwt8zsSK6rRyksIMFF/9rLukJyDPpaWHFrJZeWBDYGpH+L4qkKNYDcuz1QpFXAw4f1FIS+6YcfatRMDYzUGkwozQ7GQQ4WqbxDxltBIwLZffM+XLi6+oXM1wf0YfN45mcyTu8VSb0hthrCLbS8ihvwOL3p1c8kMpHWgjP9YdRbhfJAgbnJ4u4pQuOkgFqtW2wP5AqT8dew0v0owR6KvtBcSg+Fy4eytnLWu6kekRaJAVrEE1DQ9kvHNqxSCrvZ5NofV5hP+G+QT6eI8YScPVnIXfYQlL3zP0QopcaypFD7mhIl5QQ2Xq9VKQT3/HDSdWS6DA4P+R3hZ2DmPQ1qApwLOtnNC0D6dy366kOK1oEJRVLMoso8fPMhWuX8tAb6rfvGZvHukxvfOojzZjtvGZDiI4l1ZWlRr3yiKRlrGOqGe1xfUoKlnljGuJNxutML1efNVSoTUGGhvqpnIayoRt1lKa8JFoiMmElRV93VCreJvxq2mNodc9rwYr1X7yO5f9B2XFs9tA3g3+8IYvmQoYDDlXBcRRwpnnn7ukT0hu00glpNqQQ+BKg2cFZhQ33obNDkbbmZ169Y554wqkTzGkeJG0krrXp0q3Xxe0pmqOTN0XXAYf8z

Übung

Irrelevanz von Second-Preimage-Resistenz und Kollisionssicherheit

Warum sind Second-Preimage-Resistenz und Kollisionssicherheit von nachgeordneter Relevanz, wenn der Hash-Algorithmus zum Hashing von Passwörtern verwendet wird?

MTAwMDAw:jUGDoPcO2YABl/QfqpZ1pcKK1GXKnJvycZXHzmQM92o=:OOtvZlmIYGLiHr+t:fHY7YJUmjHLuK35yPZ+4m9ysOTHvP1BgvRGb0WPJ5wz38IjWIgnkwLWLcyJwWZX8J9CnYGQHXtMvUnC9Ltn/YwiDMT2tTCW+PAkZKTpd0vXoOB/AETtv50swidSsX7we7qnTBDajRlhb7m47QtHJw5yCw8A1YgpCZ8WGXcuAeBUgoglKarwhj9uSr/HbOxQhX4gP95Xu9UNZRUgqyvKOkFznrccOQzgky+GUiDNdgaT4brtstnR9Xh10XVKKenuUEU6hvEv/ojhdyZrTgmIzTu9bh8obruTbenINfGhHfv2qyEOjJC5b4jTySPB0kP4Yvc9Jio9486E8uHZFIuiKgt3mqx5PapV9jL3QzWCbLRNkIrRQdInGl5hp/tM0c7wAVWCFnyXe4TXBSQLIn2o7vRGwbHYJfuL9WYg8V3lmA5Lpap93K0/BZmmGixmSj0mr5Xg4f1e/GGqN7hsVmwPUbcOudB0mwLQfGDIAAg==

Message Authentication Codes (MACs)

HMAC (Hash-based Message Authentication Code)

Auch als keyed-hash message authentication code bezeichnet.

\begin{align*} \begin{array}{rcl} HMAC(K,m) & = & H( (K' \oplus opad) || H( ( K' \oplus ipad) || m) ) \\ K' & = &\begin{cases} H(K) & \text{falls K größer als die Blockgröße ist}\\ K & \text{andernfalls} \end{cases} \end{array} \end{align*}

\(H\) is eine kryptografische Hashfunktion.

\(m\) ist die Nachricht.

\(K\) ist der geheime Schlüssel (Secret Key).

\(K'\) ist vom Schlüssel K abgeleiteter Schlüssel mit Blockgröße (ggf. padded oder gehasht).

\(||\) ist die Konkatenation.

\(\oplus\) ist die XOR Operation.

\(opad\) ist das äußere Padding bestehend aus Wiederholungen von 0x5c in Blockgröße.

\(ipad\) ist das innere Padding bestehend aus Wiederholungen von 0x36 in Blockgröße.

Schlüsselableitung für den inneren und äußeren Schlüssel K' Schlüsselableitung für den inneren und äußeren Schlüssel K'

Padding und Hashing

Im Rahmen der Speicherung von Passwörtern und Secret Keys ist die Verwendung von Padding Operationen bzw. das Hashing von Passwörtern, um Eingaben in einer wohl-definierten Länge zu bekommen, üblich. Neben dem hier gesehenen Padding, bei dem 0x00 Werte angefügt werden, ist zum Beispiel auch das einfache Wiederholen des ursprünglichen Wertes, bis man auf die notwendige Länge kommt, ein Ansatz.

Diese Art Padding darf jedoch nicht verwechselt werden mit dem Padding, dass ggf. im Rahmen der Verschlüsselung von Nachrichten notwendig ist, um diese ggf. auf eine bestimmte Blockgröße zu bringen (zum Beispiel bei ECB bzw. CBC Block Mode Operations.)

HMAC Berechnung in Python

Implementierung

import hashlib
pwd = b"MyPassword"
stretched_pwd = pwd + (64-len(pwd)) * b"\x00"
ikeypad = bytes(map(lambda x : x ^ 0x36 , stretched_pwd)) # xor with ipad
okeypad = bytes(map(lambda x : x ^ 0x5c , stretched_pwd)) # xor with opad
hash1 = hashlib.sha256(ikeypad+b"JustASalt"+b"\x00\x00\x00\x01").digest()
hmac  = hashlib.sha256(okeypad+hash1).digest()

Ausführung

hmac =
b'h\x88\xc2\xb6X\xb7\xcb\x9c\x90\xc2R...
  \x16\x87\x87\x0e\xad\xa1\xe1:9\xca'

HMAC ist auch direkt als Bibliotheksfunktion verfügbar.

import hashlib
import hmac

hash_hmac = hmac.new(
    b"MyPassword",
    b"JustASalt"+b"\x00\x00\x00\x01",
    hashlib.sha256).digest()

hash_hmac =
    b'h\x88\xc2\xb6X\xb7\xcb\x9c\x90\xc2R...
      \x16\x87\x87\x0e\xad\xa1\xe1:9\xca'

GCM - Glaois Counter Mode

TODO