Hash-Algorithmen Manuel Pöter TU-Wien - e0226003 motzi@manuel-poeter.de November 2004
Kurzfassung Dieser Artikel liefert einen kurzen Überblick über Funktionsweise und Anwendungsgebiete von Hash-Algorithmen in der Kryptographie. Neben einer allgemeinen Einführung über Bedeutung und Aufbau von Hashfunktionen, werden einige konkrete Algorithem vorgestellt und verglichen und Angriffsmöglichkeiten besprochen.
1 Einführung Hashfunktionen sind unter vielen Namen bekannt: Prüfsummen, Message-Digest, Fingerabdruck, Kompressionsfunktion, Kontraktionsfunktion, u.v.a. Hashfunktionen sind, unter welchem Namen auch immer, ein sehr zentraler Bestandteil der modernen Kryptographie. Sie stellen selbst zwar keine Protokolle dar, bilden aber meistens grundlegende Bausteine für solche. Eine Hashfunktion ist eine mathematisch oder anderweitig definierte Funktion, die einen Eingabestring beliebiger Länge erhält und aus diesem einen (in der Regel kürzeren) Ausgabestring fester Länge berechnet - den Hashwert. Hashfunktionen liefern einen Fingerabdruck der Eingabedaten, also einen Wert, der etwas darüber aussagt, ob eine bestimmte Eingabe aller Wahrscheinlichkeit nach mit dem tatsächlichen Original übereinstimmt. Aufgrund der damit verbundenen Informations-Reduktion lassen sich jedoch so genannte Kollisionen nicht vermeiden, d.h. dass zwangsläufig mehrere unterschiedliche Eingaben ein- und denselben Hashwert ergeben können. Ziel beim Ent- wurf guter Hash-Algorithmen ist es nun diese möglichst kollisionsfrei zu gestalten, d.h. es sollte schwierig sein, zwei unterschiedliche Nachrichten mit demselben Hashwert zu generieren. 1.1 Anwendungsgebiete Hashfunktionen bzw. Hashwerte finden in der Kryptographie vor allem dann Verwendung, wenn Anforderungen wie Authentifizierung, Integrität und Verbindlichkeit erfüllt werden müssen. Authentifizierung - Einem Empfänger soll es möglich sein, die Herkunft einer Nachricht zu ermitteln - ein Angreifer darf sich nicht als andere Person ausgeben können. Integrität - Dem Empfänger soll es möglich sein, die Nachricht auf Änderungen während der Übertragung zu überprüfen - ein Angreifer darf die echte nicht durch eine gefälschte Nachricht ersetzen können. Verbindlichkeit - Dem Sender einer Nachricht soll es nicht möglich sein, das Senden der Nachricht im Nachhinein zu leugnen. Einweg-Hashfunktionen sind ein wichtiger Grundbaustein vieler Protokolle, in denen diese Punkte erfüllt werden müssen. 1.2 Definition und Anforderungen Auf der obersten Ebene unterscheidet man zwischen zwei unterschiedlichen Klassen von Hashfunktionen: 1
1. unkeyed hash functions - diese erhalten als einzigen Eingabe-Parameter eine Nachricht 2. keyed hash functions - diese erhalten zwei unterschiedliche Eingabe-Parameter - eine Nachricht und einen geheimen Schlüssel. Im Allgemeinen wird eine Hashfunktion folgendermaßen definiert: Definition: Eine Hashfunktion ist eine Funktion h, die mindestens folgende Eigenschaften erfüllt: compression - h bildet eine beliebig lange Nachricht x auf einen Hashwert h(x) mit der fixen Länge n ab. ease of computation - für gegebenes h und x muss es leicht sein, h(x) zu berechnen. Basierend auf weiteren Eigenschaften und Anforderungen unterscheidet man zwei verschiedene Arten von Hashfunktionen. Das sind zum einen die manipulation detection codes (MDCs) und zum anderen die message authentication codes (MACs). MDC - Manipulation Detection Codes MDCs (auch bekannt unter message integraty codes - MICs) gehören zu der Obergruppe der unkeyed hash functions. Neben den in obiger Definition festgelegten Eigenschaften werden für MDCs noch folgende Eigenschaften definiert: one-way - es ist schwer für ein gegebenes y ein x zu finden für das gilt h(x ) = y weak collision resistance - es ist schwer für ein gegebenes x ein beliebiges x mit x x zu finden, so dass h(x) = h(x ) strong collision resistance - es ist schwer zwei unterschiedliche Eingaben x und x zu finden, die denselben Hashwert produzieren, so dass h(x) = h(x ). (Hierbei ist zu beachten, dass sowohl x als auch x frei gewählt werden können.) Basierend auf diesen Eigenschaften kann man nun folgende zwei Arten von MDCs unterscheiden: Definition: Eine one-way hash function (OWHF) ist eine Hashfunktion nach obiger Definition, die sowohl die one-way-eigenschaft, als auch die weak collision restistance- Eigenschaft erfüllt. Definition: Eine collision resistance hash function (CRHF) ist eine Hashfunktion nach obiger Definition, die sowohl die weak collision resistance-eigenschaft, als auch die strong collision resistance-eigenschaft erfüllt. 2
MAC - Message Authentication Codes MACs gehören zu der Obergruppe der keyed hash functions und besitzen somit zwei Eingabeparameter - die Nachricht und einen geheimen Schlüssel. Definition: Ein MAC-Algorithmus ist eine Funktion h k, mit einem geheimen Schlüssel als Parameter k, die die folgenden Eigenschaften erfüllt: ease of computation - es ist leicht h k (x) für gegebenes k und x zu berechnen. Das Ergebnis wird als MAC-Value oder kurz MAC bezeichnet. compression - h k bildet eine beliebig lange Nachricht x auf ein einen Hashwert h k (x) mit fixer Länge x ab. computation-resistance - Es ist schwer für Null oder mehr gegebene Nachrichten- MAC Paare (x i, h k (x i )) ein Nachrichten-MAC Paar (x, h k (x)) zu berechnen für das gilt x x i. 1.3 Allgemeiner Aufbau Die meisten Hashfunktionen sind als iterativer Prozess aufgebaut. Dabei werden die beliebig langen Eingabedaten in Blöcken mit fixer Größe verarbeitet: Abbildung 1: Model einer iterierenden Hashfunktion Die Nachricht x wird in Blöcke x i mit fixer Länge r aufgesplittet. Bei diesem Vorgang müssen üblicherweise noch extra Bits an die Nachricht angehängt werden, damit die 3
Länge ein Vielfaches der Blockgröße r beträgt. Aus Sicherheitsgründen wird in diesen Padding-Bits meistens auch die Länge der ursprünglichen Nachricht gespeichert. Jeder Block x i durchläuft nun die Kompressions-Funktion f, welche einen Zwischenhash mit der festen Bitlänge n berechnet. Dieser Zwischenhash wird dann im nächsten iterativen Durchlauf in die Berechnung des nächsten Zwischenhashes mit einbezogen. Das Ergebnis der Hashfunktion ist dann eine Kombination all dieser Zwischenhashwerte. 2 Algorithmen 2.1 MD4 MD4 ist ein von Ronald Rivest 1990 entworfener Hashalgorithmus, der einen 128-Bit langen Hashwert der Eingabedaten berechnet. MD steht dabei für Message Digest, was in etwa Zusammenfassung einer Nachricht bedeutet. Die Entwurfsziele des Algorithmus waren vor allem Sicherheit, Geschwindigkeit und Kompaktheit. Der Algorithmus wurde im Oktober 1990 als RFC 1186 veröffentlicht [1]. Heutzutage gilt MD4 als unsicher, da aber die meisten moderneren Hashalgorithmen mehr oder weniger direkt auf MD4 aufbauen, möchte ich den Algorithmus hier dennoch erklären. MD4 arbeitet mit 512-Bit Blöcken. Die Länge der Nachricht muss daher ein Vielfaches von 512 betragen; damit dies gewährleistet ist, werden zu Beginn entsprechend viele so genannte Padding-Bits angehängt: 1. Padding - Die Nachricht wird so erweitert, dass die Länge kongurent 448 modulo 512 ist. Dadurch wird sichergestellt, dass die Länge genau 64 kleiner als das nächste Vielfache von 512 ist. Das Padding selbst erfolgt in folgender Form: zuerst ein einzelnes 1 -Bit und dann entsprechend viele 0 -Bits anhängen, bis die gewünschte Länge erreicht ist. Insgesamt wird also immer mindestens ein Bit und maximal 512 Bits angehängt. 2. Länge speichern - Die Länge der ursprünglichen Nachricht (vor dem Padding) wird als 64-Bit codierte Zahl an das Ergebnis des vorherigen Schrittes angehängt. Im weiteren Verlauf werden die Blöcke folgendermaßen verarbeitet: 1. MD Puffer initialisieren - Der Algorithmus verwendet vier 32-Bit Wörter (A, B, C, D). Diese werden folgendermaßen initialisiert (little Endian): A 01 23 45 67 B 89 AB CD EF C FE DC BA 98 D 76 54 32 10 4
2. Verarbeiten der Blöcke - Der Algorithmus verarbeitet die Blöcke in drei Funktionen, die als Input je drei 32-Bit Wörter übernehmen und ein 32-Bit Wort als Output zurückliefern: f(x, Y, Z) = (X Y ) (( X) Z) g(x, Y, Z) = (X Y ) (X Z) (Y Z) h(x, Y, Z) = X Y Z Jedes 32-Bit Wort wird nun in drei Runden mit je 16 Operationen verarbeitet (Details dazu findet man in [1]). 3. Output - Das Ergebnis des Algorithmus steht in den vier 32-Bit Wörtern A, B, C, D - beginnend mit dem low-order Byte von A und endend mit dem high-order Byte von D. 2.2 MD5 MD5 wurde als verbesserte Version von MD4 entwickelt und im April 1992 als RFC 1321 veröffentlicht [2]. Die Unterschiede zwischen MD5 und MD4 sind folgende [4]: 1. Eine zusätzliche Runde mit 16 Operationen und einer eigenen Funktion wurde hinzugefügt. 2. Die Funktion g der zweiten Runde wurde durch die neue Funktion g(x, Y, Z) = (X Z) (Y ( Z)) ersetzt um g weniger symmetrisch zu machen. 3. In den Runden 2 und 3 wurde der Zugriff auf die Teilblöcke geändert. 4. Änderung der Verschiebungen (so dass sich die Verschiebungen in jeder Runde unterscheiden) um den Lawineneffekt zu verstärken. 5. Verwendung von zusätzlichen Konstanten in jedem der 4 16 Schritte, basierend auf dem Ganzzahlteil von 2 32 sin(j) für Schritt j. 6. Übernahme des Ergebnis des vorhergehenden Schrittes in jeden der insgesamt 64 Schritte. Dies liefert ebenfalls einen schnelleren Lawineneffekt. Es wurden zwar bis jetzt keine Kollisionen für MD5 gefunden, allerdings konnten Kollisionen für die Kompressions-Funktion von MD5 gefunden werden. Diese Tatsache liefert nicht automatisch einen praktischen Angriff gegen MD5, es bedeutet allerdings, dass eines der grundlegenden Entwurfsprinzipien von MD5 - nämlich eine Kompressionsfunktion, die Schutz vor Kollisionen bietet - verletzt wurde [5]. 5
2.3 SHA-1 SHA steht für Secure Hash Algorithm und ist ein Algorithmus, der in Zusammenarbeit von NIST (National Institute of Standard and Technology) und NSA (National Security Agency) entwickelt wurde und ebenfalls auf MD4 basiert. In der ursprünglichen Version namens SHA wurden Kollisionen gefunden, leider wurden die Entwurfskriterien und Details über diese Attacken von der NSA jedoch nicht veröffentlicht. Der Algorithmus wurde daraufhin verbessert und unter dem neuen Namen SHA-1 veröffentlicht. Die Hauptunterschiede zu MD4 sind folgende [4]: 1. Der produzierte Hashwert ist 160-Bit lang und es werden fünf statt nur vier Initialisierungs-Vektoren verwendet. 2. Die Kompressions-Funktion besteht aus vier Runden, im Gegensatz zu drei. Hierbei werden die drei MD4-Funktionen f, g und h wie folgt benutzt: f in der ersten, g in der dritten, und h in der zweiten und vierten Runde. Außerdem besteht jede Runde aus 20 Operationen anstatt 16. 3. Innerhalb der Kompressions-Funktion wird jeder 16-Wort Block auf einen 80-Wort Block erweitert. Dabei wird so vorgegangen, dass die letzten 64 der 80 Wörter das XOR-Ergebnis von 4 Wörter von früheren Positionen im erweiterten Block sind. Diese 80 Wörter sind nun die einzelnen Inputs für die weiteren 80 Schritte. 4. SHA-1 verwendet vier additive Konstanten ungleich Null, MD4 verwendet nur drei wobei nur zwei ungleich Null sind. SHA-1 bietet aufgrund des längeren Hashwertes bessere Sicherheit gegen Brute-Force- Attacken. 2.4 RIPEMD-160 Die ursprüngliche Version von RIPEMD basierte ebenfalls auf MD4 und produzierte einen Hashwert mit 128-Bit. Diese Version wurde jedoch weiter verbessert, die Länge des produzierten Hashes wurde aufgrund der besseren Sicherheit gegen Bruteforce-Attacken auf 160-Bit erhöht und unter dem Namen RIPEMD-160 veröffentlicht. (Es gibt noch weitere Versionen namens RIPEMD-256 und RIPEMD-320, die jeweils Hashwerte mit 256-Bit bzw. 320-Bit produzieren, aber abgesehen von dem längeren Hashwert keine höhere Sicherheit bieten.) Die Kompressions-Funktion von RIPEMD-160 verarbeitet ein Eingabe, bestehend aus 21 32-Bit Wörtern (5 Initialisierungs-Vektoren plus ein 16-Wort-Block der Nachricht), zu einem 5-Wort Hashwert. Jeder Eingabe-Block durchläuft dabei parallel zwei verschiedene Versionen der Kompressions-Funktion - die linke und rechte Linie. Die beiden 160-Bit Outputs der beiden Linien werden dann zu einem einzigen 160-Bit Hash kombiniert. Mehr Details zu den Unterschieden zwischen RIPEMD-160 und MD4 findet man in [4]. 6
2.5 HMAC HMAC ist ein Verfahren zur Authentifizierung von Nachrichten mit Hilfe von kryptographischen Hashalgorithmen. Dabei kann jeder beliebige MDC wie zb MD5, SHA-1, etc. in Kombination mit einem geheimen Schlüssel benutzt werden. Die Sicherheit des Verfahrens hängt im wesentlichen direkt von der Sicherheit des verwendeten Hashalgorithmus ab. HMAC wurde im Februar 1997 als RFC 2104 veröffentlicht [3]. Das Verfahren verläuft folgendermaßen [6]: 1. An den Schlüssel k werden 0 -Bits angehängt bis dieser die Block-Länge b des zugrundeliegenden Algorithmus hat. Den neuen Schlüssel bezeichne ich hier mit k +. 2. k + wird mit dem sogenannten ipad (dem Byte 0x36) b-mal XOR-verknüpft. 3. Die Nachricht x wird an das Ergebnis aus Schritt 2 angehängt. 4. Die zugrundeliegene Hashfunktion h wird auf das Ergebnis aus Schritt 3 angewandt. 5. k + wird mit dem sogenannten opad (dem Byte 0x5c) b-mal XOR verknüpft 6. Der Hashwert aus Schritt 4 wird an das Ergebnis aus Schritt 5 angehängt. 7. Die zugrundeliegende Hashfunktion h wird auf das Ergebnis aus Schritt 6 angewandt. 3 Angriffsmöglichkeiten Natürlich gibt es auch bei den Hashalgorithmen die klassischen kryptanalytischen Ansätze. Ich möchte an dieser Stelle allerdings nicht näher auf diese eingehen, sondern mich vor allem der Geburtstagsattacke, einer Brute-Force-Attacke speziell für Hashfunktionen, widmen. Es gibt zwei Arten von Brute-Force-Attacken gegen Hashfunktionen. Die erste ist naheliegend: der Angreifer möchte zu einem gegebenen Hashwert h(x) einer Nachricht x eine andere Nachricht x finden, so dass h(x) = h(x ), wodurch dem Angreifer ein Austauschen der Nachricht x durch x möglich wäre. Der zweite Angriff ist ein wenig raffinierter: hier generiert der Angreifer beide Nachrichten x und x und versucht hier eine Kollision der Hashwerte zu finden, so dass h(x) = h(x ). Diese zweite Art von Angriff wird Geburtstagsangriff genannt und ist viel einfacher und effektiver Angriff als der erste. Das Geburtstagsparadoxon ist ein Standardproblem aus der Wahrscheinlichkeitsrechnung. Gegeben sei eine Gruppe von n Personen - wie hoch ist nun die Wahrscheinlichkeit, dass mindestens eine Person am selben Tag Geburtstag hat wie das Geburtstagskind? Die allgemeine Formel lautet: 7
1 ( ) n k 1 k Wir gehen hier von dem allgemeinen Fall aus, dass jeder Geburtstag gleich wahrscheinlich ist (Schaltjahre werden vernachlässigt) und lege k daher mit 365 fest. Wie groß muss man n nun ansetzen, damit die Chance mindestens 50 Prozent beträgt, dass eine Person aus der Geburtstagsgesellschaft am selben Tag Geburtstag hat wie das Geburtstagskind? Die Anwort lautet 253: 1 ( ) 253 364 365 0, 50047715404 Verallgemeinert man hingegen das Problem dahingehend zu sagen - wieviele Personen benötigt man, dass mindestens zwei von ihnen am selben Tag Geburtstag haben - so fällt die Anzahl erstaunlich niedrig aus. Die allgemeine Formel dazu lautet: 1 ( ) n (n 1) k 1 2 k Damit die Wahrscheinlichkeit bei mindestens 50 Prozent liegt, reichen hier bereits 23 Personen: 1 ( ) 23 (22) 364 2 365 0, 50047715404 Jemanden mit einem bestimmten Geburtstag zu finden, entspricht dem ersten (intuitiven) Angriff. Zwei Leute zu finden, die am gleichen Tag (egal an welchem) Geburtstag haben entspricht dem zweiten, wesentlich effektiveren, Angriff. Die Geburtstagsattacke ist ein allgemeiner Angriff, der unabhängig vom verwendeten Algorithmus ist. Sie zeigt im wesentlichen, dass bei einer Hashfunktion die einen n-bit Hashwert produziert, nur 2 n/2 zufällige Nachrichten erzeugt werden müssen, um eine Kollision zu finden - d.h. zwei Nachrichten x und x zu finden, so dass h(x) = h(x ). Literatur [1] R. Rivest - RFC1186 - The MD4 Message Digest Algorithm, MIT Laboratory for Computer Science, October 1990 [2] R. Rivest - RFC1186 - RFC 1321 - The MD5 Message-Digest Algorithm, MIT Laboratory for Computer Science and RSA Data Security, Inc., April 1992 [3] H. Krawczyk, M. Bellare, R. Canetti - RFC 2104 - HMAC: Keyed-Hashing for Message Authentication, IBM and UCSD, February 1997 [4] Alfred J. Menezes, Paul C. van Oorschot, Scott A. Vanstone - Handbook of Applied Cryptography, CRC Press LLC, 2000 8
[5] Bruce Schneier - Angewandte Kryptographie: Protokolle, Algorithmen und Sourcecode in C 2. Auflage, Addison Wesley 1996 [6] William Stallings - Cryptography and Network Security: Principles and Practice, Prentice Hall, 2003 9