Im Gegensatz zu dem, was die meist upvoted Antworten hier betonen, das nicht-injectivity (dh , dass es mehrere Saiten auf den gleichen Wert Hashing) durch die Differenz zwischen großer (potentiell unendlichen) Eingangsgröße und fester Ausgangsgröße einer verschlüsselten Hash - Funktion verursacht ist nicht Der wichtige Punkt - eigentlich bevorzugen wir Hash-Funktionen, bei denen diese Kollisionen so selten wie möglich auftreten.
Betrachten Sie diese Funktion (in PHP-Notation als Frage):
function simple_hash($input) {
return bin2hex(substr(str_pad($input, 16), 0, 16));
}
Dies fügt einige Leerzeichen an, wenn die Zeichenfolge zu kurz ist, nimmt dann die ersten 16 Bytes der Zeichenfolge und codiert sie dann als hexadezimal. Es hat die gleiche Ausgabegröße wie ein MD5-Hash (32 hexadezimale Zeichen oder 16 Byte, wenn der bin2hex-Teil weggelassen wird).
print simple_hash("stackoverflow.com");
Dies wird Folgendes ausgeben:
737461636b6f766572666c6f772e636f6d
Diese Funktion hat auch die gleiche Nicht-Injektivitätseigenschaft wie in Codys Antwort für MD5 hervorgehoben: Wir können Zeichenfolgen beliebiger Größe übergeben (solange sie in unseren Computer passen) und es werden nur 32 hexadezimale Ziffern ausgegeben. Natürlich kann es nicht injektiv sein.
In diesem Fall ist es jedoch trivial, eine Zeichenfolge zu finden, die demselben Hash zugeordnet ist (wenden hex2bin
Sie sie einfach auf Ihren Hash an, und Sie haben sie). Wenn Ihre ursprüngliche Zeichenfolge die Länge 16 hatte (als unser Beispiel), erhalten Sie sogar diese ursprüngliche Zeichenfolge. Für MD5 sollte nichts dergleichen möglich sein, selbst wenn Sie wissen, dass die Länge der Eingabe ziemlich kurz war (außer indem Sie alle möglichen Eingaben ausprobieren, bis wir eine passende finden, z. B. einen Brute-Force-Angriff).
Die wichtigen Annahmen für eine kryptografische Hash-Funktion sind:
- Es ist schwer, eine Zeichenfolge zu finden, die einen bestimmten Hash erzeugt (Vorbildwiderstand).
- Es ist schwierig, eine andere Zeichenfolge zu finden, die denselben Hash wie eine bestimmte Zeichenfolge erzeugt (zweiter Vorbildwiderstand).
- Es ist schwierig, ein Saitenpaar mit demselben Hash zu finden (Kollisionsbeständigkeit).
Offensichtlich meine simple_hash
erfüllt Funktion keine dieser Bedingungen. (Wenn wir den Eingaberaum auf "16-Byte-Strings" beschränken, wird meine Funktion injektiv und ist somit sogar nachweisbar resistent gegen Zweitvorbilder und kollisionssicher.)
Es gibt jetzt Kollisionsangriffe gegen MD5 (z. B. ist es möglich, ein Paar von Zeichenfolgen zu erzeugen, selbst mit einem bestimmten Präfix, die denselben Hash haben, mit ziemlich viel Arbeit, aber nicht unmöglich viel Arbeit), daher sollten Sie diese nicht verwenden MD5 für alles Kritische. Es gibt noch keinen Preimage-Angriff, aber die Angriffe werden besser.
Um die eigentliche Frage zu beantworten:
Was ist mit diesen Funktionen, das es unmöglich macht, die resultierenden Zeichenfolgen zurückzuverfolgen?
MD5 (und andere Hash-Funktionen, die auf der Merkle-Damgard-Konstruktion aufbauen) wenden effektiv einen Verschlüsselungsalgorithmus mit der Nachricht als Schlüssel und einem festen Wert als "Klartext" an, wobei der resultierende Chiffretext als Hash verwendet wird. (Vorher wird die Eingabe aufgefüllt und in Blöcke aufgeteilt. Jeder dieser Blöcke wird verwendet, um die Ausgabe des vorherigen Blocks zu verschlüsseln. XORed mit seiner Eingabe, um umgekehrte Berechnungen zu verhindern.)
Moderne Verschlüsselungsalgorithmen (einschließlich der in Hash-Funktionen verwendeten) sind so konzipiert, dass es schwierig ist, den Schlüssel wiederherzustellen, selbst wenn sowohl Klartext als auch Chiffretext vorliegen (oder selbst wenn der Gegner einen von ihnen auswählt). Sie tun dies im Allgemeinen, indem sie viele Bit-Shuffling-Operationen so ausführen, dass jedes Ausgangsbit durch jedes Schlüsselbit (mehrmals) und auch jedes Eingangsbit bestimmt wird. Auf diese Weise können Sie nur dann leicht nachvollziehen, was im Inneren passiert, wenn Sie den vollständigen Schlüssel und entweder die Eingabe oder die Ausgabe kennen.
Für MD5-ähnliche Hash-Funktionen und einen Preimage-Angriff (zur Vereinfachung mit einem Single-Block-Hash-String) haben Sie nur die Eingabe und Ausgabe Ihrer Verschlüsselungsfunktion, nicht jedoch den Schlüssel (dies ist das, wonach Sie suchen).