La función hash en Python 3.3 devuelve resultados diferentes entre sesiones

He implementado un BloomFilter en python 3.3 y obtuve diferentes resultados en cada sesión. La profundización de este extraño comportamiento me llevó a la función hash () interna: devuelve diferentes valores de hash para la misma cadena en cada sesión.

Ejemplo:

>>> hash("235") -310569535015251310 

—– abriendo una nueva consola de python —–

 >>> hash("235") -1900164331622581997 

¿Por qué está pasando esto? ¿Por qué es esto útil?

Python utiliza un valor aleatorio de hash para evitar que los atacantes ataquen tu aplicación al enviarte claves diseñadas para colisionar. Ver la divulgación de vulnerabilidad original . Al compensar el hash con una semilla aleatoria (establecida una vez en el inicio), los atacantes ya no pueden predecir qué claves colisionarán.

Puede establecer una semilla fija o deshabilitar la característica configurando la variable de entorno PYTHONHASHSEED ; el valor predeterminado es random pero puede establecerlo en un valor entero positivo fijo, con 0 deshabilitando la función por completo.

Las versiones 2.7 y 3.2 de Python tienen la función deshabilitada de forma predeterminada (use el interruptor -R o configure PYTHONHASHSEED=random para habilitarlo); está habilitado de forma predeterminada en Python 3.3 y superior.

Si dependía del orden de las claves en un diccionario o conjunto de Python, no lo haga. Python utiliza una tabla hash para implementar estos tipos y su orden depende del historial de inserción y eliminación , así como del valor aleatorio de hash.

También vea la documentación del método especial object.__hash__() :

Nota : De forma predeterminada, los __hash__() de los objetos str, bytes y datetime están “saleados” con un valor aleatorio impredecible. Aunque permanecen constantes dentro de un proceso individual de Python, no son predecibles entre invocaciones repetidas de Python.
El objective es proporcionar protección contra una denegación de servicio causada por entradas cuidadosamente seleccionadas que explotan el peor caso de desempeño de una inserción de dict, complejidad O (n ^ 2). Consulte http://www.ocert.org/advisories/ocert-2011-003.html para obtener más información.
Cambiar los valores de hash afecta el orden de iteración de los dictados, conjuntos y otras asignaciones. Python nunca ha hecho garantías sobre este pedido (y normalmente varía entre las comstackciones de 32 y 64 bits).
Ver también PYTHONHASHSEED .

Si necesita una implementación de hash estable, probablemente desee consultar el módulo hashlib ; Esto implementa funciones hash criptográficas. El proyecto pybloom utiliza este enfoque .

Como el desplazamiento consta de un prefijo y un sufijo (valor de inicio y valor final de XOR, respectivamente), desafortunadamente no se puede almacenar el desplazamiento. En el lado positivo, esto significa que los atacantes tampoco pueden determinar fácilmente el desplazamiento con ataques de tiempo.

La asignación aleatoria de hash está activada de forma predeterminada en Python 3 . Esta es una característica de seguridad:

La asignación aleatoria de elementos aleatorios está diseñada para proporcionar protección contra una denegación de servicio causada por entradas cuidadosamente seleccionadas que explotan el peor caso de desempeño de una construcción dict.

En versiones anteriores a la 2.6.8, podría activarlo en la línea de comandos con -R, o la opción de entorno PYTHONHASHSEED .

Puede apagarlo configurando PYTHONHASHSEED en cero.

hash () es una función incorporada de Python y la usa para calcular un valor de hash para un objeto , no para una cadena o un número.

Puede ver los detalles en esta página: https://docs.python.org/3.3/library/functions.html#hash .

y los valores de hash () provienen del método __hash__ del objeto. El doc dice lo siguiente:

De forma predeterminada, los valores hash () de los objetos str, bytes y datetime están “sal” con un valor aleatorio impredecible. Aunque permanecen constantes dentro de un proceso individual de Python, no son predecibles entre invocaciones repetidas de Python.

Es por eso que tiene un valor hash diferente para la misma cadena en una consola diferente.

Lo que implementas no es una buena manera.

Cuando desee calcular un valor hash de cadena, simplemente use hashlib

hash () es el objective de obtener un valor de hash de objeto, no una agitación.