Artikelserie: Teil 3, Welcher Hash darfs sein?

Kryptografie für Anfänger: Hash-Funktion und Message-Authentication-Codes
Keine Kommentare

Nachrichten zu verschlüsseln schützt nicht vor Manipulation. Wie lässt sich die Integrität von Daten beweisen? Hash-Funktionen und Message Authentication Codes helfen.

Wer Nachrichten verschlüsselt, macht das, um ihre Inhalte vor den neugierigen Blicken von Dritten zu schützen. Verwendet man dazu einen sicheren und zeitgemäßen Algorithmus wie AES oder das One-Time Pad (OTP), lässt sich das Ziel mit überschaubarem Aufwand erreichen. Allerdings wiegt man sich rasch zu sehr in Sicherheit: Denn das Verschlüsseln von Nachrichten schützt nicht vor deren Manipulation.

Das mag zunächst unerwartet sein, ist aber letztlich logisch. Beim Verschlüsseln werden nämlich lediglich die Zeichen des Klartexts durch andere Zeichen ersetzt, je nach Algorithmus auf mehr oder weniger komplizierte Art. Dabei findet aber keinerlei Plausibilitätsprüfung statt, immerhin lässt sich auch jeder beliebige Text verschlüsseln.

Greift man noch einmal auf die Cäsar-Verschlüsselung zurück, die aus dem ersten Teil dieser Serie bekannt ist, lässt sich das sehr anschaulich demonstrieren. Verschlüsselt man beispielsweise den Klartext LIEBE SUSANNA, indem man die Buchstaben um ein Zeichen im Alphabet verschiebt, erhält man den Geheimtext MJFCF TVTBOOB. Ein Angreifer kann diesen Geheimtext manipulieren, beispielsweise indem die ersten fünf Zeichen durch den Text IBMMP ersetzt werden. Man erhält so den geänderten Geheimtext IBMMP TVTBOOB.

Artikelserie

Entschlüsselt man ihn nun wieder, indem man die Verschiebung rückgängig macht, erhält man als Klartext HALLO SUSANNA. Das erste Wort ist also erfolgreich ersetzt worden. Damit ist es theoretisch möglich, jede verschlüsselte Nachricht zu manipulieren.

Sicherheit von Text – und von Zahlen?

Zugegebenermaßen ist das bei Text wenig sinnvoll, da selten eine zielgerichtete Manipulation möglich ist. Es liegt auf der Hand, dass das vorige Beispiel entsprechend konstruiert war, damit sich wieder ein vernünftiger Klartext ergibt. Eine Manipulation ohne Kenntnis des verwendeten Schlüssels ist da schon schwieriger und führt in der Regel zu einem sinnlosen Klartext, ist also wenig erfolgversprechend.

Doch was passiert, wenn eine Nachricht keinen menschenlesbaren Text enthält, sondern beispielsweise Messdaten eines Sensors? In diesem Fall führt die Manipulation eines nahezu beliebigen Zeichens zu verfälschten Messwerten. Denkt man dabei an Szenarien, wo zum Beispiel medizinische Daten erfasst werden, ist schnell klar, dass ein verfälschter Wert unter Umständen über Leben und Tod entscheiden kann.

International JavaScript Conference

Effective Microservices Architecture In Node.js

by Tamar Stern (Palto Alto Networks)

React Components And How To Style Them

by Jemima Abu (Telesoftas)

Angular Camp 2020

Als Online- oder Präsenztraining!

Das 360°-Intensivtraining mit Angular-Koryphäe Manfred Steyer
Präsentiert von Entwickler Akademie

Wie schwierig es ist, verfälschte Zahlen aufzudecken, zeigt der Informatiker David Kriesel in seinem äußerst unterhaltsamen und lehrreichen Vortrag „Traue keinem Scan, den du nicht selbst gefälscht hast“. Darin zeigt er, wie einige Kopierer von Xerox beim Scannen von Dokumenten unter gewissen Umständen Zahlen verfälschen, die zu allem Unglück auch noch perfekt ins Layout des gescannten Dokuments passen.

Solche Fehler fallen nur auf, wenn die Daten semantisch nicht mehr sinnvoll sind – wenn also beispielsweise die Abstellkammer auf einem Grundriss mehr Quadratmeter aufweist als der nebenan liegende Ballsaal. Doch solche verhältnismäßig offensichtlichen Fehler sind selten, und müssen zudem trotzdem erst einmal auffallen. Wie lässt sich also die Integrität von Nachrichten sicherstellen und überprüfen?

Ein digitaler Fingerabdruck?

Abhilfe schaffen hier die sogenannten Hash-Funktionen. Dabei handelt es sich um mathematische Funktionen, die zu einem gegebenen Eingabewert einen passenden digitalen Fingerabdruck erstellen. So wie jeder Mensch über einen persönlichen und einzigartigen Fingerabdruck verfügt, erzeugen auch Hash-Funktionen für unterschiedliche Eingaben verschiedene digitale Fingerabdrücke. Die Idee dahinter ist, dass man zu einer Nachricht zusätzlich auch ihren Fingerabdruck übermitteln kann, der Empfänger dann den Fingerabdruck neu berechnet und mit dem übermittelten Fingerabdruck vergleicht. Sind beide Werte identisch, kann man davon ausgehen, dass die Nachricht nicht verfälscht wurde. Sind sie unterschiedlich, liegt offenbar eine Manipulation vor.

Für gute Hash-Funktionen gibt es eine Reihe von Kriterien, die eingehalten werden müssen:

  • Hash-Funktionen müssen unumkehrbar sein. Anders formuliert handelt es sich bei ihnen um sogenannte Einwegfunktionen: Wie eine Falltür ermöglichen sie die Berechnung in eine Richtung auf sehr einfache Art, der Rückweg ist aber ausgeschlossen. Übersetzt heißt das, dass eine Hash-Funktion es zwar ermöglicht, aus einer Eingabe einen Hash-Wert zu berechnen, aber nicht andersherum.
  • Hash-Funktionen müssen schnell berechenbar sein, damit man effizient mit ihnen arbeiten kann. Das ist sowohl für den Absender als auch für den Empfänger der Nachricht notwendig. Dauert die Berechnung zu lange, leidet die Praxistauglichkeit.
  • Hash-Funktionen müssen nicht nur für unterschiedliche Eingaben verschiedene Hash-Werte produzieren, sie müssen sogar bereits bei kleinsten Unterschieden in der Eingabe zu gravierenden Unterschieden in den erzeugten Hash-Werten führen.

Kollisionen von Hash-Werten

Eine weitere Besonderheit von Hash-Funktionen ist, dass sie unabhängig von der Länge der Eingabe stets einen Hash-Wert der gleichen Länge generieren. Daraus ergibt sich aber ein Problem: Wenn die Länge des Hash-Werts begrenzt ist, die potenzielle Länge der Eingabe jedoch unbegrenzt, führt das logischerweise dazu, dass es unendlich viele Eingaben gibt, die im gleichen Hash-Wert resultieren: Es wird nämlich eine unendliche Menge an Eingaben auf eine endliche Menge an Ausgaben abgebildet.

Findet man zwei unterschiedliche Eingaben, die im gleichen Hash-Wert resultieren, spricht man von einer Kollision. Aus naheliegenden Gründen sollte es möglichst schwer sein, zu einer gegebenen Eingabe eine Alternative zu konstruieren, die den gleichen Hash-Wert aufweist. Unter anderem deshalb ist es so wichtig, dass bereits kleinste Änderungen der Eingabe gravierende Unterschiede in den erzeugten Hash-Werten nach sich ziehen.

Ein weiterer Aspekt der Tatsache, dass es mehrere Eingaben zu einem Hash-Wert gibt, ist, dass man aus unterschiedlichen Hash-Werten zwar schließen kann, dass die Eingaben verschieden waren – aus einem identischen Hash-Wert kann man jedoch nur bedingt schließen, dass auch die Eingabe identisch war. Genau darauf basiert aber die ursprünglich skizzierte Idee der Prüfung der Authentizität von Nachrichten. Diese Prüfung ist also mit einem (zumindest theoretischen) Fragezeichen zu versehen.

Welchen Algorithmus soll man nehmen

Schaut man sich um, welche Hash-Algorithmen es gibt, fallen zunächst zwei Familien von Funktionen auf: Zum einen gibt es die Message-Digest-Algorithmen, beispielsweise MD-4 und MD-5. Alle Algorithmen, die zu dieser Familie gehören, gelten als veraltet und kompromittiert. Daher werden sie auch nur noch in den wenigsten Anwendungen eingesetzt. Für neue Entwicklungen sollte man komplett auf diese Algorithmen verzichten.

Zum anderen gibt es die Secure-Hash-Algorithm-Familie, von der es wiederum drei Generationen gibt: SHA-1, SHA-2 und SHA-3. Die erste und älteste Generation davon, SHA-1, gilt ebenfalls als veraltet und sollte daher nicht mehr eingesetzt werden.

SHA-2 hingegen ist heutigen Anforderungen durchaus gewachsen, und liegt wiederum in drei Varianten vor, die sich durch die Länge des erzeugten Hash-Werts unterscheiden: SHA-256 erzeugt 256 Bit lange Hash-Werte, SHA-384 und SHA-512 entsprechend 384 und 512 Bit lange. Alle diese Varianten sind für den Einsatz noch geeignet, wobei man für eine hohe Zukunftssicherheit primär auf SHA-512 setzen sollte.

Der ganz neue Stern am Horizont schließlich ist SHA-3, der allerdings derzeit nur von den wenigsten Plattformen und Frameworks unterstützt wird, und daher noch nicht unbedingt für den Alltagseinsatz geeignet ist. Dennoch ist klar, dass diesem Algorithmus die Zukunft gehört.

Welchen Algorithmus man schlussendlich wählt, ist aber auch eine Frage des Einsatzgebietes: Braucht man wirklich hundertprozentige Sicherheit, oder geht es zum Beispiel nur darum, Übertragungsfehler zu erkennen? Im zweiten Fall genügt gegebenenfalls auch ein älterer Algorithmus, der kürzere Hash-Werte produziert und damit weniger Speicher verbraucht.

So hat beispielsweise die verteilte Versionsverwaltung Git lange Zeit auf SHA-1 gesetzt, obwohl die Schwächen dieser Hash-Funktion bereits bekannt waren. Sehr ausführlich ist die Migration von Git auf eine neuere Version von SHA in der Antwort auf die StackOverflow-Frage „Why doesn’t Git use more modern SHA?“ beschrieben.

Lösen Hash-Funktionen das Problem?

Verwendet man eine moderne Hash-Funktion, könnte man nun annehmen, das Problem der Nachrichtenintegrität sei gelöst. Und tatsächlich gibt es Anwendungsfälle, in denen das Berechnen eines Hash-Wertes genügt: Will man zum Beispiel die Integrität einer zum Download angebotenen Datei sicherstellen, legt man auf dem Webserver neben dem eigentlichen Download auch eine Datei ab, die den berechneten Hash-Wert enthält. Der Konsument kann dann beide Dateien herunterladen, den Hash-Wert lokal neu berechnen und mit dem online angegebenen Wert vergleichen. Stimmen die Werte überein, kann man davon ausgehen, dass der Download erfolgreich war und es keine Übertragungsfehler gab.

Trotzdem lösen Hash-Funktionen das Problem der Nachrichtenintegrität nicht: Gelingt es nämlich einem Angreifer, einen Geheimtext abzufangen und zu manipulieren, kann er auch den dazugehörigen Hash-Wert abfangen, ihn nach der Manipulation neu berechnen und ihn anschließend gemeinsam mit der manipulierten Nachricht weiterreichen. Der Empfänger erhält nun die Nachricht, berechnet ihren Hash-Wert und vergleicht diesen Wert mit dem erhaltenen – vom Angreifer neu berechneten – Hash-Wert: Da beide übereinstimmen, geht der Empfänger davon aus, dass die Nachricht ohne Manipulation übermittelt wurde. Das Problem an dieser Stelle ist also, dass es für jedermann problemlos möglich ist, zu einer gegebenen Nachricht einen passenden Hash-Wert zu berechnen. Kann man der Nachricht selbst nicht trauen, kann man dementsprechend auch dem Hash-Wert nicht trauen. Das ist leider ein herber Rückschlag.

Message-Authentication-Codes

Zum Glück gibt es für dieses Problem eine einfache Lösung, nämlich die sogenannten Message-Authentication-Codes (MACs), von denen es auch eine Hash-basierte Variante gibt: Dabei handelt es sich um den sogenannten HMAC (Hash-based-Message-Authentication-Code). Das Grundprinzip von HMACs ist simpel: Genau wie bei den normalen Hash-Funktionen wird auch beim HMAC ein Hash-Wert über eine Eingabe berechnet, allerdings wird diese vor dem Hashen noch um einen geheimen Schlüssel ergänzt.

Berechnet man mit SHA-256 den Hash-Wert des Textes „the native web“, erhält man folgendes Ergebnis:

$ echo -n "the native web" | shasum -a 256 55a1f59420da66b2c4c87b565660054cff7c2aad5ebe5f56e04ae0f2a20f00a9 

Dieser Hashwert lässt sich von jedermann leicht neu berechnen. Fügt man der Nachricht vor dem Berechnen aber noch den geheimen Schlüssel secret hinzu, ergibt sich ein gänzlich anderer Hash-Wert:

$ echo -n "secret the native web" | shasum -a 256 846116259a627ccdd7bc50348dd4538f41ee2569bee7b73693305630d20828ce 

Diesen Hash-Wert kann man nun nicht berechnen, ohne den geheimen Schlüssel zu kennen, und da Hash-Funktionen nicht umkehrbar sind, ist es auch unmöglich, aus dem Hash-Wert den geheimen Schlüssel zu errechnen. Man könnte höchstens versuchen, eine Kollision zu konstruieren, was aber bei den modernen Algorithmen bislang als unmöglich angesehen werden kann.

Die tatsächliche Berechnung eines HMACs ist etwas aufwendiger, folgt aber prinzipiell dem gleichen Konzept wie das hier beschriebene Beispiel. Damit kann man nun tatsächlich die Integrität von Nachrichten sicherstellen, sofern Sender und Empfänger über einen gemeinsamen geheimen Schlüssel verfügen, und sie diesen vor dem potenziellen Angreifer geheim halten können. Da der Angreifer den Schlüssel nicht kennt, kann er zwar die Nachricht an sich manipulieren, aber keinen dazu passenden HMAC berechnen.

Der Haken an der Sache ist allerdings der gleiche wie bei der symmetrischen Verschlüsselung: Sender und Empfänger müssen über einen gemeinsamen geheimen Schlüssel verfügen, was mindestens die Frage aufwirft, wie sie diesen initial auf sicherem Wege austauschen. Das offenbart wieder das klassische Dilemma: Existiert ein solcher sicherer Weg für den Schlüsselaustausch, könnte man die Nachrichten auch direkt auf diesem Weg übermitteln. Existiert ein solcher Weg nicht, kann man auch dem ausgetauschten Schlüssel nicht trauen.

Fazit und Ausblick

Hash-Funktionen sind ein einfaches, aber extrem vielseitig einsetzbares Mittel, um die Integrität von Nachrichten sicherzustellen. In einigen Fällen genügt schon der Einsatz einer Hash-Funktion, in anderen Fällen müssen sie mit anderen Sicherheitsmechanismen kombiniert werden, wie beispielsweise für die Message-Authentication-Codes.

Das größte Problem dabei ist – wieder einmal – der sichere Austausch des Schlüssels. Daher widmet sich der nächste Teil genau diesem Problem und führt als Alternative zur symmetrischen dann auch die asymmetrische Verschlüsselung ein.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -