la fonction de hachage en Python 3.3 renvoie des résultats différents entre les sessions

j'ai implémenté un BloomFilter en python 3.3, et j'ai obtenu des résultats différents à chaque session. Percer ce comportement bizarre m'a amené à la fonction de hachage interne () - il renvoie des valeurs de hachage différentes pour la même chaîne à chaque session.

exemple:

>>> hash("235")
-310569535015251310

----- ouverture d'une nouvelle console python -----

>>> hash("235")
-1900164331622581997

pourquoi cela se produit-il? Pourquoi est-ce utile?

33
demandé sur smci 2014-12-17 12:48:17

3 réponses

Python utilise une graine de hachage aléatoire pour empêcher les attaquants de tarir votre application en vous envoyant des clés conçues pour entrer en collision. Voir la divulgation de la vulnérabilité initiale . En compensant le hachage par une graine aléatoire (définie une fois au démarrage), les attaquants ne peuvent plus prédire quelles clés vont entrer en collision.

vous pouvez définir une graine fixe ou désactiver la fonctionnalité en définissant la PYTHONHASHSEED variable d'environnement ; la valeur par défaut est random mais vous pouvez le définir à une valeur entière positive fixe, avec 0 désactiver la fonctionnalité tout à fait.

Python les versions 2.7 et 3.2 ont désactivé la fonctionnalité par défaut (utilisez le commutateur -R ou mettez PYTHONHASHSEED=random pour l'activer); elle est activée par défaut dans Python 3.3 et up.

si vous comptiez sur l'ordre des clés dans un dictionnaire ou un jeu de Python, alors ne le faites pas. Python utilise une table de hachage pour implémenter ces types et leur ordre dépend de l'historique d'insertion et de suppression ainsi que de la graine de hash aléatoire.

Voir aussi object.__hash__() documentation sur les méthodes spéciales :

Note : par défaut, les valeurs __hash__() des objets str, bytes et datetime sont "salées" avec une valeur aléatoire imprévisible. Bien qu'ils restent constants dans un processus Python individuel, ils ne sont pas prévisibles entre invocations répétées de Python.

Ceci est destiné à fournir une protection contre un déni de service causé par des entrées soigneusement choisies qui exploitent la pire performance d'une insertion dict, O(N^2) complexité. Voir http://www.ocert.org/advisories/ocert-2011-003.html pour plus de détails.

Changer les valeurs de hachage affecte l'ordre d'itération des dicts, des ensembles et d'autres mappages. Python a jamais fait des garanties sur cette commande (et il varie généralement entre 32-bit et 64-bit construit).

Voir aussi PYTHONHASHSEED .

si vous avez besoin d'une implémentation de hachage stable, vous voulez probablement regarder le hashlib module ; ceci implémente les fonctions de hachage cryptographique. Le projet pybloom utilise cette approche .

étant donné que l'offset se compose d'un préfixe et Suffixe (valeur de départ et valeur finale Xorée, respectivement) vous ne pouvez pas simplement stocker l'offset, malheureusement. Du côté positif, cela signifie que les attaquants ne peuvent pas non plus déterminer facilement le décalage avec les attaques de synchronisation.

50
répondu Martijn Pieters 2017-05-23 11:54:55

la randomisation de hachage est activée par défaut en Python 3 . Ceci est une caractéristique de sécurité:

Hachage de la randomisation est destiné à fournir une protection contre une attaque en déni de service provoqué par un soigneusement choisi les entrées qui exploitent le pire des cas, la performance d'un dict construction

dans les versions précédentes de 2.6.8, vous pouvez l'activer à la ligne de commande avec -R, ou le Pythonhashseed option d'environnement.

vous pouvez l'éteindre en mettant PYTHONHASHSEED à zéro.

4
répondu Peter Wood 2014-12-17 10:17:02

hash () est un Python fonction intégrée et l'utiliser pour calculer une valeur de hash pour objet , pas pour la chaîne ou le num.

vous pouvez voir le détail dans cette page: https://docs.python.org/3.3/library/functions.html#hash .

et les valeurs de hash() proviennent de la méthode __hash__ de l'objet. Le doc dit ce qui suit:

par défaut, les valeurs hash () des objets str, bytes et datetime sont" salées " avec une valeur aléatoire imprévisible. Bien qu'ils restent constants dans un processus Python individuel, ils ne sont pas prévisibles entre invocations répétées de Python.

c'est pourquoi vous avez une valeur de hachage différente pour la même chaîne dans une console différente.

ce que vous mettez en œuvre n'est pas une bonne façon.

si vous voulez calculer une valeur de hachage de chaîne, il suffit d'utiliser hashlib

hash() est de viser à obtenir un objet de valeur de hachage, pas un stirng.

-3
répondu Adam Wen 2014-12-17 10:01:36