web-dev-qa-db-de.com

Hash-Funktion in Python 3.3 gibt unterschiedliche Ergebnisse zwischen Sitzungen zurück

Ich habe einen BloomFilter in python 3.3) implementiert und in jeder Sitzung andere Ergebnisse erzielt. Durch das Drilldown dieses seltsamen Verhaltens bin ich auf die interne hash () -Funktion gekommen - es werden verschiedene Hash-Werte für denselben String zurückgegeben jede Sitzung.

Beispiel:

>>> hash("235")
-310569535015251310

----- Öffnen einer neuen python Konsole -----

>>> hash("235")
-1900164331622581997

Warum passiert dies? Warum ist das nützlich?

51
redlus

Python verwendet einen zufälligen Hash-Startwert, um zu verhindern, dass Angreifer Ihre Anwendung ins Visier nehmen, indem Sie Schlüssel senden, die für eine Kollision vorgesehen sind. Siehe rsprüngliche Offenlegung der Sicherheitsanfälligkeit . Durch das Versetzen des Hashs mit einem zufälligen Startwert (einmalig beim Start festgelegt) können Angreifer nicht mehr vorhersagen, welche Schlüssel kollidieren werden.

Sie können einen festen Startwert festlegen oder die Funktion deaktivieren, indem Sie die Umgebungsvariable PYTHONHASHSEED ; Der Standardwert ist random, aber Sie können einen festen positiven ganzzahligen Wert festlegen, wobei 0 die Funktion insgesamt deaktiviert.

In den Python-Versionen 2.7 und 3.2 ist die Funktion standardmäßig deaktiviert (verwenden Sie den Schalter -R Oder setzen Sie PYTHONHASHSEED=random, Um sie zu aktivieren). Es ist standardmäßig in Python 3.3 und höher aktiviert.

Wenn Sie sich auf die Reihenfolge der Schlüssel in einem Python Dictionary oder Set verlassen, dann tun Sie das nicht. Python verwendet eine Hash-Tabelle, um diese Typen und ihre zu implementieren order hängt vom Einfüge- und Löschverlauf ab sowie vom zufälligen Hash-Seed.

Siehe auch object.__hash__() special method documentation :

Hinweis : Standardmäßig werden die __hash__() -Werte von str-, byte- und datetime-Objekten mit einem unvorhersehbaren Zufallswert "gesalzen". Obwohl sie innerhalb eines einzelnen Python - Prozesses konstant bleiben, sind sie zwischen wiederholten Aufrufen von Python nicht vorhersehbar.
Dies soll Schutz vor Denial-of-Service bieten, der durch sorgfältig ausgewählte Eingaben verursacht wird, bei denen die Leistung einer Diktateinfügung im ungünstigsten Fall (O (n ^ 2) -Komplexität) ausgenutzt wird. Weitere Informationen finden Sie unter http://www.ocert.org/advisories/ocert-2011-003.html .
Das Ändern von Hash-Werten wirkt sich auf die Iterationsreihenfolge von Dikten, Mengen und anderen Zuordnungen aus. Python hat niemals Garantien für diese Reihenfolge gegeben (und variiert normalerweise zwischen 32-Bit- und 64-Bit-Builds).
Siehe auch PYTHONHASHSEED.

Wenn Sie eine stabile Hash-Implementierung benötigen, sollten Sie sich das hashlib -Modul ansehen. Dadurch werden kryptografische Hash-Funktionen implementiert. Das Pybloom-Projekt verwendet diesen Ansatz .

Da der Versatz aus einem Präfix und einem Suffix (Startwert bzw. endgültiger XOR-Wert) besteht, können Sie den Versatz leider nicht einfach speichern. Auf der positiven Seite bedeutet dies, dass Angreifer den Versatz bei Timing-Angriffen ebenfalls nicht leicht bestimmen können.

77
Martijn Pieters

Die Hash-Randomisierung ist standardmäßig in Python aktiviert. Dies ist eine Sicherheitsfunktion:

Die Hash-Randomisierung soll Schutz vor Denial-of-Service bieten, der durch sorgfältig ausgewählte Eingaben verursacht wird, die die Leistung einer Diktatkonstruktion im ungünstigsten Fall ausnutzen

In früheren Versionen von 2.6.8 konnten Sie es über die Befehlszeile mit -R oder mit der Umgebungsoption PYTHONHASHSEED aktivieren.

Sie können es ausschalten, indem Sie PYTHONHASHSEED auf Null setzen.

5
Peter Wood