Frage von Crysali, 38

Muss man einen Secure Hash Algorithm manuell eingeben?

Ja, ich weiß, die Frage macht so keinen Sinn, ich meine aber, ob ich etwas eingeben muss, um mir den SHA zu Nutze zu machen.

Auf Wikipedia steht, dass ein leerer Hash auch eine Verschlüsselung bietet. Ist es demnach egal, ob man etwas eingibt und der SHA von ("") generiert wird ? Oder ist es sicherer/ macht es einen Unterschied manuell einen String einzugeben ?

Antwort
von NoHumanBeing, 23

Die Frage macht so keinen Sinn. Ich fange mal mit den Grundlagen an. Eine Hashfunktion ordnet jeder Bitfolge beliebiger Länge eine Bitfolge fester Länge (den so genannten Hashwert) zu.

Im Bereich der Kryptographie unterscheidet man verschiedene Eigenschaften und verschiedene Angriffsmodelle mit klar definierten Eigenschaften.

Verschlüsselungsverfahren (z. B. Blockchiffren) sollen pseudozufällig sein. Insbesondere ist eine Blockchiffre eine pseudozufällige Permutation, das heißt der Ausgaberaum ist der Eingaberaum, pseudozufällig permutiert. Pseudozufällig bedeutet, dass man keinen so genannten "distinguisher" (etwa "Unterscheider") konstruieren kann, der ohne Kenntnis über den verwendeten Schlüssels, aber mit der Möglichkeit, Klartexte durch die Permutation jagen ("verschlüsseln") zu können, die Permutation nicht mit mehr als vernachlässigbar kleiner Wahrscheinlichkeit (widerum vernachlässigbar im Sicherheitsparameter) von einer echt zufällig gewählten Permutation unterscheiden kann. Man bezeichnet das als so genanntes "distinguishing experiment" und es ist im Prinzip die schärfste Sicherheitsforderung, die man an eine Blockchiffre stellen kann.

Kryptographische Hashfunktionen hingegen haben ein anderes Ziel. Sie sollen kollisionsresistent sein. Zu diesem Zweck geht man in der Regel von einer schlüsselbehafteten Hashfunktion aus, weil der Angreifer sonst nur ein Paar Nachrichten kennen muss, das den selben Hashwert erzeugt und dann sofort "gewonnen" hat. Ohne Randomisierung kann man keine Wahrscheinlichkeit definieren. Also konstruiert man aus der Hashfunktion zunächst in geeigneter Weise eine "keyed hash function". Dann wählt man widerum einen Schlüssel zufällig, hält ihn geheim, gibt aber einem Angreifer die Möglichkeit, zu beliebigen Nachrichten Hashwerte berechnen zu lassen. Die Hashfunktion ist sicher, wenn es dem Angreifer bei zufällig gewähltem Schlüssel nicht möglich ist, mit mehr als vernachlässigbarer Wahrscheinlichkeit ein paar Nachrichten zu finden, die den gleichen Hashwert erzeugen. Man bezeichnet die Hashfunktion dann als kollisionsresistent. Sichere MACs (diese sind Hashfunktionen sehr ähnlich, siehe unten) sind sicher gegen einen so genannten "adaptive chosen message attack". Hier kann ein Angreifer, der selbst widerum keine Kenntnis über den verwendeten Schlüssel hat, Nachrichten MAC-en lassen und den MAC-Wert erhalten. Ziel des Angreifers ist es, zwei Nachrichten zu generieren, die den selben MAC-Wert aufweisen. Gelingt dem Angreifer dies, so ist das MAC-Verfahren gebrochen.

Wichtig ist, zu erkennen, dass dass die Eigenschaften Pseudozufälligkeit ("kann man nicht effizient von Zufall unterscheiden") und Kollisionsresistenz ("man kann nicht effizient zwei Eingaben finden, die die selbe Ausgabe erzeugen") nichts, aber auch gar nichts miteinander zu tun haben. Eine Hashfunktion "verschlüsselt" somit nicht und wurde auch nicht dafür designed. Eine Blockchiffre muss Vertraulichkeit gewährleisten, eine Hashfunktion hingegen nicht. Aus diesem Grund sollte man bei der Kombination von MAC-Verfahren (im Grunde gleich "keyed hash") und Verschlüsselungsverfahren den MAC auch immer über den Ciphertext berechnen (Encrypt-then-MAC) und nicht über den Klartext (MAC-and-Encrypt). Eine Hashfunktion und auch eine MAC muss nur kollisionsresistent sein, sonst nichts. Das heißt sie muss keinerlei "Geheimhaltung" oder "Vertraulichkeit" gewährleisten. Deswegen immer nur Inhalte MAC-en, die nicht geheim sind, d. h. nicht den Klartext MAC-en, sondern das Chiffrat MAC-en. Dann kann die MAC an Information "preisgeben", was sie möchte. Das Chiffrat kennt der Angreifer ja ohnehin bereits.

Kommentar von Crysali ,

Vielen Dank für die ausführliche Antwort!

Verstehe ich das richtig: Wenn ich etwas eingebe in einem Feld, das mit SHA1 gekennzeichnet ist, dann wird, was ich in das Feld eingebe, zufällig verschlüsselt, um Kollisionen zu verhindern.

Sozusagen wie eine Postmarke an einem Brief. Kein anderer Brief kann diese Postmarke dann haben. Falls jedoch jemand Böswilliges diese Postmarke kennt, dann kann er Sachen in den Brief hineinlegen.

Wenn der SHA1 immer ("") wäre, wäre es dann immer dieselbe Verschlüsselung oder findet dann die pseudozufällige Permutation statt, die einen Bereich aufspannt, um zu vermeiden, dass ein Angreifer zufällig oder durch extremes Versuchen den Eingabebereich herausfindet ? Falls letzteres stimmt wäre es doch egal, was und wie lange etwas ist, das im Eingabebereich steht, oder nicht ?

Kommentar von NoHumanBeing ,

Also grundsätzlich "verschlüsselt" eine Hashfunktion nicht. ;-)

Etwas, das verschlüsselt, bezeichnet man trivialerweise als Verschlüsselungsverfahren. Was ein Verschlüsselungsverfahren im Einzelnen ist, ist widerum exakt definiert, nämlich ein Tupel aus den sechs Elementen (M, C, K, Gen, Enc, Dec).

Hierbei ist M die Menge aller Klartexte (der so genannte "Nachrichtenraum"), C die Menge aller Chiffrate (der so genannte "Schlüsseltextraum"), K die Menge aller Schlüssel (der so genannte "Schlüsselraum").

Gen ist widerum eine Funktion, die unter bei Eingabe von 1^n (einem Bitstring von n Einsen - die Eingabe braucht man, sonst kann man das Laufzeitverhalten nicht definieren - Polynomialzeit bedeutet ja, die Laufzeit ist polynomiell in der Länge der Eingabe) einen zufälligen Schlüssel aus erzeugt, der in K liegt, in der Regel, indem sie ihn tatsächlich zufällig gleichverteilt aus K wählt.

Enc ist eine Funktion, die eine Eingabe aus der Menge M x K (Kreuzprodukt zwischen dem Nachrichten- und dem Schlüsselraum) auf eine Ausgabe aus der Menge C (Schlüsseltextraum) abbildet.

Dec ist eine Funktion, die eine Eingabe aus der Menge C x K (Kreuzprodukt zwischen dem Schlüsseltext- und dem Schlüsselraum) auf eine Ausgabe aus der Menge M (Nachrichtenraum) abbildet.

Hierbei fordert man in der Regel noch "correctness", d. h. Dec(Enc(m, k), k) = m für alle m aus M und alle k aus K. Bei symmetrischen Verfahren fordert man dies in der Regel strikt. Bei asymmetrischen Verfahren (die immer randomisiert sind - sind sie es nicht, kann man relativ trivial zeigen, dass sie dann auch nicht sicher gegen Known-Plaintext-Angriffe sein können) "darf" es unter Umständen eine geringe Wahrscheinlichkeit geben, dass dieser Zusammenhang nicht erfüllt ist.

Bei einem Hash wird überhaupt nichts "verschlüsselt". Eine Hashfunktion ist kein Verschlüsselungsverfahren. Das siehst Du schon daran, dass Du einen Hash nicht (effizient) umkehren ("entschlüsseln") kannst. Außerdem haben "normale" ("unkeyed") Hashfunktionen ja nicht einmal einen Parameter für einen "Schlüssel".

Eine "pseudozufällige Permutation" ist das, was man gemeinhin als "Blockchiffre" bezeichnet. AES beispielsweise ist eine pseudozufällige Permutation. Das bedeutet, wenn ich Dir einen "gekeyten" AES gebe, ohne dass Du den Schlüssel herausfinden kannst und ich gebe Dir eine beliebige bijektive Funktion, die ich echt zufällig aus der Menge aller möglichen bijektiven Funktionen gewählt habe, und Du kannst nicht "hinein gucken", sondern nur Werte "durchjagen", dann kannst Du nicht entscheiden, welches der AES ist und welches die zufällige Permutation. Deswegen ist AES eine pseudozufällige Permutation. Der AES sollte keine Eigenschaften haben, die erlauben würden, ihn ohne Kenntnis des Schlüssels von einer zufälligen Permutation zu unterscheiden.

(In diesem Zusammenhang meint Permutation = Bijektion. In der Kryptographie bezeichnet man in der Regel jede bijektive Funktion als Permutation, nicht weil die Ausgabebits eine Permutation der Eingabebits wären, sondern weil die Menge aller Ausgaben bei einer Bijektion eine Permutation der Menge aller Eingaben ist. Das ist manchmal verwirrend, weil der Begriff auch anders belegt ist, teilweise auch in der Kryptographie, siehe "P-Box", wo mit "Permutation" wirklich eine "Vertauschung von Bits" gemeint ist.)

Deine Frage ist irgendwie "unzureichend definiert". Der SHA-1 von "" ist natürlich immer der selbe. Man benutzt Hashfunktionen auch häufig, um Schlüssel aus einem Passwort abzuleiten, obwohl es speziell für diesen Zweck nochmals eigene Konstruktionen (so genannte "key derivation functions", etwa PBKDF2) gibt, die allerdings widerum auf Hashfunktionen, wie SHA-1, basieren. Die Hashfunktion dient dann dazu, das Passwort weiter zu "randomisieren", obwohl natürlich darauf zu achten ist, dass sie an sich den Suchraum nicht vergrößert. Wenn ich als Passwort drei Kleinbuchstaben verwende, und daraus per SHA-256 einen Schlüssel für AES-256 errechne, dann ist das natürlich trotzdem nicht sehr sicher, auch wenn der SHA-256 Wert irgendwie "zufällig" aussieht. (Er ist aber deterministisch errechnet. SHA-256 wird unter der selben Eingabe immer die selbe Ausgabe erzeugen.)

Kommentar von Crysali ,

Erneut danke für die ausführliche Antwort!

Um mit meiner Frage etwas aufzuräumen: Wir haben auf der Arbeit ein Programm, welches die Verschiebung von großen Datenmengen unterstützt, indem es beispielsweise eine Datei in Segmente unterteilt und diesen eine SHA-1 .. Signatur (?) zuordnet. Diese ist allerdings immer (""), wobei man manuell auch etwas anderes eingeben könnte.

SHA-1 ordnet also den Segmenten eine Signatur zu, um die verschobenen Segmente später sinnvoll zusammenzuführen, oder ?

Wir wurden allerdings darauf aufmerksam gemacht, dass SHA-1 nicht sonderlich gut gegen Angreifer schützt. Da wir momentan keine Fachkraft für IT haben, sind wir nun in der Sorge um die Sicherheit des Verfahrens.

Ändert das manuelle Eingeben eines Strings für die SHA-1 etwas an der Sicherheit und wie gefährlich ist das Benutzen von SHA-1 anstelle von SHA-2 wirklich ? 

Kommentar von NoHumanBeing ,

Also, ich rate einmal, was ihr damit machen wollt. Ihr wollt eine große Datei in Blöcke unterteilen und diese Blöcke dann "signieren" (eigentlich "MAC-en" - Signaturverfahren sind asymmetrische Verfahren, die Integrität sicherstellen - die symmetrischen Verfahren nennt man MACs - "message authentication codes" - so viel zur Terminologie).

Diese "Signatur" kann nun zweierlei Zwecken dienen. Zum einen kann sie dazu dienen, fehlerhaft übertragene oder anderweitig korrumpierte Blöcke festzustellen. Dazu müsstet ihr den SHA-Wert über den jeweiligen Block berechnen und ihn dann irgendwie geeignet speichern, etwa an die Blöcke "anhängen" oder auch in einer separaten Datei ablegen. (Den SHA über "" zu berechnen macht keinen Sinn, denn das ist ja ein konstanter Wert und hängt ja auch nicht vom Blockinhalt ab.) Dann könnt ihr die Daten später zurücklesen, die SHA-Werte der einzelnen Blöcke berechnen und vergleichen. Wenn sich nun irgendwo ein Bitfehler oder ähnliches eingeschlichen hat, wird der errechnete SHA-Wert mit an Sicherheit grenzender Wahrscheinlichkeit nicht mehr mit dem gespeicherten übereinstimmen und ihr wisst, dass der Block beschädigt ist. Im Grunde macht ihr dann das, was eine Paritätsprüfung macht, nur mit sehr viel größerem Aufwand. Die kryptographische Sicherheit von SHA bringt euch in diesem Fall nichts.

Die andere Möglichkeit ist, dass der MAC tatsächlich ein MAC sein und den Inhalt authentifizieren soll, sodass ihr nicht nur feststellen könnt, wenn sich der Inhalt "zufällig" (etwa durch einen Defekt) geändert hat, sondern auch, wenn der Inhalt gezielt manipuliert wurde. Das ist ein sehr viel stärkere Anforderung, da ein Angreifer ja gezielt darauf aus sein wird, dass sein Vorgehen nicht entdeckt wird. Der einfache SHA über die Blöcke bringt Euch hier nichts, denn der Angreifer kann einen Block modifizieren, anschließend den SHA berechnen und diesen ebenfalls modifizieren. Danach wird aus eurer Sicht wieder alles "valide" sein.

Die einzige Möglichkeit, das zu verhindern, liegt darin, den Angreifer einen Wert berechnen zu lassen, zu dessen Berechnung er zusätzliches Wissen benötigt, das ihm nicht zur Verfügung steht, etwa einen Schlüssel. Das ist genau das Ziel eines MAC-Verfahrens. Ihr berechnet dazu eine MAC (z. B. eine HMAC, einen "hash-based message authentication code") über den Block. Der MAC-Algorithmus wird sowohl eine Nachricht (die zu "signierenden" Daten), als auch einen Schlüssel entgegennehmen. Nur unter Kenntnis dieses Schlüssels kann man gültige Tags (so bezeichnet man die "MAC-Werte") errechnen. Allerdings braucht ihr zur Überprüfung dieser Werte natürlich ebenfalls den geheimen Schlüssel. Jeder, der einen MAC überprüfen kann, kann ihn somit auch fälschen.

Falls auch das ein Problem für euch ist, müsst ihr zwangsläufig auf asymmetrische Kryptographie ausweichen und digitale Signaturen verwenden. Hier kommt ein Schlüsselpaar, bestehend aus privatem und öffentlichem Schlüssel, zum Einsatz. Um eine Signatur zu erstellen wird der private Schlüssel benötigt. Um eine Signatur zu überprüfen, wird der öffentliche Schlüssel benötigt. Somit könnt ihr jemanden befähigen, die Signatur zu überprüfen, ohne dass dieser zugleich gültige Signaturen erstellen kann, indem ihr ihm lediglich den öffentlichen, nicht aber den privaten Signaturschlüssel aushändigt.

Zuletzt möchte ich noch vorsorglich darauf hinweisen, dass die einfache Konstruktion H(k . m), mit einem Hashverfahren "H" und "." als Konkatenationsoperator ("Bitfolgen hintereinanderhängen") mit den meisten Hashverfahren (so auch mit SHA-1/SHA-2) keine sichere MAC ist. Das liegt daran, dass SHA-1/-2 eine so genannte Merkle-Damgard-Konstruktion ist, bei der eine so genannte "length extension attack" möglich ist. Das bedeutet, dass man an eine Nachricht "geschickt" etwas anhängen kann, ohne dadurch den Hashwert zu verändern. Wenn die Nachrichten eine feste Länge haben und diese auch im Rahmen des Sicherheitsprotokolls überprüft wird, dann kann man "ausnahmsweise" eine einfache Konstruktion der Form K(k . m) verwenden. Ansonsten bitte in jedem Fall explizit ein MAC-Verfahren, etwa HMAC-SHA256, verwenden. Dort ist diese "length extension" nicht möglich. Auch wenn die Länge "irgendwo geprüft wird", ist es zumindest "guter Stil", trotzdem ein dezidiertes MAC-Verfahren zu verwenden, weil ein Entwickler die Längenprüfung eventuell nicht für sicherheitsrelevant hält und sie irgendwann entfernen wird oder weil durch "integer overflow" oder andere Dinge so eine Längenprüfung eventuell auch mal durch einen Angreifer "überwunden werden kann".

Kommentar von NoHumanBeing ,

Zur Verwendung von SHA-1 ist noch zu sagen: Auch wenn ihr nur einen 160-Bit-Hash verwenden könnt (etwa aus Gründen des Protokolls oder des Dateiformats), so wäre es grundsätzlich erheblich besser, einen SHA-2-Hash zu berechnen und diesen anschließend auf 160 Bit zu kürzen. Das würde man dann als SHA-256-160 oder SHA-512-160 oder ... oder ... oder ... je nachdem, von welcher SHA-Variante ihr eben ausgeht, bezeichnen. Bei SHA-1 wurden bereits Schwachstellen gefunden, die nichts mit der Länge des Hashes, sondern mit dem Verfahren an sich zu tun haben.

Das gilt, wenn euer Ziel wirklich Sicherheit ist. Ist euer Ziel hingegen lediglich "Fehlererkennung", dann tut es SHA-1 (oder gar MD5 oder gar MD4 oder gar MD2 - ja, das gibt es wirklich ^^) auch.

Kommentar von Crysali ,

Vielen dank für die ausführlichen Antworten, die haben mir sehr geholfen!

Kommentar von NoHumanBeing ,

Keine Ursache! :-)

Eine Sache noch: Wenn ihr wirklich etwas "sicherheitsrelevantes" damit macht, dann macht bitte erstens so wenig "Eigenbau" wie möglich und zweitens holt Euch bitte einen Experten ins Boot. Ich bin bald seit 7 Jahren an der Uni und forsche in diesem Bereich. Trotzdem würde ich mir (noch) nicht anmaßen, sehr sicherheitskritische Systeme zu entwickeln.

Keine passende Antwort gefunden?

Fragen Sie die Community