Der Wikipedia-Artikel über Hash-Funktionen ist sehr gut, aber ich werde hier mein Einverständnis geben.
Was ist ein Hash?
"Hash" ist wirklich ein weiter Begriff mit unterschiedlichen formalen Bedeutungen in unterschiedlichen Kontexten. Es gibt keine perfekte Antwort auf Ihre Frage. Ich werde das allgemeine Grundkonzept erläutern und einige der gebräuchlichsten Verwendungen des Begriffs erwähnen.
Ein "Hash" ist eine Funktion , die als Hash-Funktion bezeichnet
wird und als Eingabeobjekte eine Zeichenfolge oder Zahl ausgibt. Die Eingabeobjekte sind normalerweise Mitglieder grundlegender Datentypen wie Zeichenfolgen, Ganzzahlen oder größerer Datentypen, die aus anderen Objekten wie benutzerdefinierten Strukturen bestehen. Die Ausgabe ist normalerweise eine Zahl oder eine Zeichenfolge. Das Substantiv "Hash" bezieht sich oft auf diese Ausgabe. Das Verb "Hash" bedeutet oft "eine Hash-Funktion anwenden". Die wichtigsten Eigenschaften, die eine Hash-Funktion haben sollte, sind:h
- Es sollte einfach zu berechnen sein und
- Die Ausgänge sollten relativ klein sein.
Beispiel:
Angenommen, wir möchten Hash-Zahlen im Bereich von 0 bis 999.999.999 bis zu Zahlen zwischen 0 und 99 verwenden. Eine einfache Hash-Funktion kann .h ( x ) = xmod100
Gemeinsame zusätzliche Eigenschaften:
Je nach Anwendungsfall möchten wir, dass die Hash-Funktion zusätzliche Eigenschaften erfüllt. Hier sind einige übliche zusätzliche Eigenschaften:
Einheitlichkeit : Oft möchten wir, dass die Hashes von Objekten unterschiedlich sind. Außerdem möchten wir, dass die Hashes "ausgebreitet" werden. Wenn ich einige Objekte in 100 Buckets hacken möchte (die Ausgabe meiner Hash-Funktion ist also eine Zahl von 0-99), dann hoffe ich normalerweise, dass ungefähr 1/100 Objekte in Bucket 0 landen, ungefähr 1/100 in Eimer 1 und so weiter.
Widerstand gegen kryptografische Kollisionen : Manchmal wird dies sogar noch weiter vorangetrieben. In der Kryptografie möchte ich möglicherweise eine Hash-Funktion, sodass es für einen Gegner rechnerisch schwierig ist, zwei verschiedene Eingänge zu finden, die demselben Ausgang zugeordnet sind.
Komprimierung : Ich möchte häufig willkürlich große Eingaben in eine Ausgabe mit konstanter Größe oder eine feste Anzahl von Buckets zerlegen.
Determinismus : Möglicherweise möchte ich eine Hash-Funktion, deren Ausgabe sich zwischen den Durchläufen nicht ändert, dh die Ausgabe der Hash-Funktion für dasselbe Objekt bleibt immer gleich. Dies scheint im Widerspruch zur obigen Gleichförmigkeit zu stehen, aber eine Lösung besteht darin, die Hash-Funktion zufällig einmal auszuwählen und nicht zwischen den Durchläufen zu ändern.
Einige Anwendungen
Eine häufige Anwendung sind Datenstrukturen wie eine Hash-Tabelle, mit denen Wörterbücher implementiert werden können. Hier ordnen Sie Speicher zu, beispielsweise 100 "Buckets". Wenn Sie dann aufgefordert werden, ein (Schlüssel-, Wert-) Paar im Wörterbuch zu speichern, haben Sie den Schlüssel in eine Zahl von 0 bis 99 gehasht und das Paar im entsprechenden Bucket gespeichert. Wenn Sie dann aufgefordert werden, einen Schlüssel nachzuschlagen, wird der Schlüssel mit derselben Hash-Funktion in eine Zahl von 0 bis 99 gehasht und in diesem Bucket überprüft, ob sich der Schlüssel dort befindet. In diesem Fall geben Sie den Wert zurück.
Beachten Sie, dass Sie Wörterbücher auch auf andere Weise implementieren können, z. B. mit einem binären Suchbaum (wenn Ihre Objekte vergleichbar sind).
Eine weitere praktische Anwendung sind Prüfsummen, mit denen überprüft werden kann, ob zwei Dateien identisch sind (z. B. wurde die Datei gegenüber der vorherigen Version nicht beschädigt). Da es sehr unwahrscheinlich ist, dass Hash-Funktionen zwei Eingaben derselben Ausgabe zuordnen, berechnen und speichern Sie einen Hash der ersten Datei, der normalerweise als Zeichenfolge dargestellt wird. Dieser Hash ist sehr klein, vielleicht nur ein paar Dutzend ASCII-Zeichen. Wenn Sie dann die zweite Datei erhalten, prüfen Sie, ob die Ausgabe identisch ist. In diesem Fall handelt es sich mit ziemlicher Sicherheit Byte für Byte um dieselbe Datei.
Eine andere Anwendung ist die Kryptographie, bei der es schwierig sein sollte, diese Hashes zu "invertieren" - das heißt, angesichts der Ausgabe und der Hash-Funktion sollte es schwierig sein, die Eingaben zu ermitteln, die zu dieser Ausgabe geführt haben. Eine Verwendung davon ist für Kennwörter: Anstatt das Kennwort selbst zu speichern, speichern Sie einen kryptografischen Hash des Kennworts (möglicherweise mit einigen anderen Bestandteilen). Wenn ein Benutzer ein Kennwort eingibt, berechnen Sie seinen Hash und überprüfen, ob er mit dem richtigen Hash übereinstimmt. Wenn ja, sagen Sie, dass das Passwort korrekt ist. (Jetzt hat auch jemand, der den auf dem Server gespeicherten Hash nachsehen und herausfinden kann, nicht so leicht die Möglichkeit, sich als Benutzer auszugeben.) Bei dieser Anwendung ist die Ausgabe möglicherweise genauso lang oder länger als die Eingabe, da Die Eingabe ist so kurz.