хэш-функция в Python 3.3 возвращает различные результаты между сеансами

я реализовал BloomFilter в python 3.3 и получал разные результаты каждый сеанс. Сверление этого странного поведения привело меня к внутренней функции hash () - она возвращает разные хэш-значения для одной и той же строки каждый сеанс.

пример:

>>> hash("235")
-310569535015251310

- - - - - - открытие новой консоли python - - - - -

>>> hash("235")
-1900164331622581997

почему это происходит? Почему это полезно?

3 ответов


Python использует случайное хэш-семя, чтобы предотвратить злоумышленников от tar-pitting вашего приложения, отправив вам ключи, предназначенные для столкновения. Вижу оригинальный уязвимость, приводящая к раскрытию. Компенсируя хэш случайным семенем (установленным один раз при запуске), злоумышленники больше не могут предсказать, какие ключи столкнутся.

вы можете установить фиксированное семя или отключить функцию, установив PYTHONHASHSEED переменные среды по умолчанию:random но вы можете установить его на фиксированное положительное целое значение, с 0 отключение функции в целом.

Python версии 2.7 и 3.2 имеют функцию отключена по умолчанию (используйте -R переключатель или set PYTHONHASHSEED=random, чтобы включить его); он включен по умолчанию в Python 3.3 и выше.

если вы полагались на порядок ключей в словаре или наборе Python, то нет. Python использует хэш-таблицу для реализации этих типов и их порядка зависит от истории вставки и удаления as а также случайное семя хэша.

Смотрите также object.__hash__() специальная документация метода:

Примечание по умолчанию __hash__() значения объектов str, bytes и datetime "засаливаются" с непредсказуемым случайным значением. Хотя они остаются постоянными в рамках отдельного процесса Python, они не предсказуемы между повторными вызовами Python.
Это призвано обеспечить защиту от отказа в обслуживании вызвано тщательно подобранными входами, которые используют наихудшую производительность вставки dict, o (n^2) сложность. См.http://www.ocert.org/advisories/ocert-2011-003.html для деталей.
Изменение хэш-значений влияет на порядок итераций диктов, наборов и других сопоставлений. Python никогда не гарантировал этот порядок (и он обычно варьируется между 32-битными и 64-битными сборками).
См. также PYTHONHASHSEED.

Если вам нужен стабильный хэш реализации, вы, вероятно, хотите посмотреть на hashlib модуль; это реализует криптографические хэш-функции. The проект pybloom использует этот подход.

поскольку смещение состоит из префикса и суффикса (начальное значение и конечное значение XORed соответственно), вы не можете просто сохранить смещение, к сожалению. С положительной стороны, это означает, что атакующие также не могут легко определить смещение с атаками времени.


рандомизация хэша-это включен по умолчанию в Python 3. Это функция безопасности:

рандомизация хэша предназначена для обеспечения защиты от отказа в обслуживании, вызванного тщательно подобранными входами, которые используют худшую производительность конструкции dict

в предыдущих версиях с 2.6.8 вы можете включить его в командной строке с помощью-R или PYTHONHASHSEED окружающая среда выбор.

вы можете отключить его, установив PYTHONHASHSEED к нулю.


hash () является Python встроенная функция и использовать его для вычисления хэш-значения для объект, не для строки или num.

вы можете увидеть детали на этой странице:https://docs.python.org/3.3/library/functions.html#hash.

и значения hash () поступают из метода __hash__ объекта. Док говорит следующее:--7-->

по умолчанию хэш () значения str, байтов и объекты datetime "соленые" с непредсказуемым случайным значением. Хотя они остаются постоянными в рамках отдельного процесса Python, они не предсказуемы между повторными вызовами Python.

вот почему у вас есть различное хэш-значение для одной и той же строки в другой консоли.

то, что вы реализуете, не является хорошим способом.

Если вы хотите вычислить значение хэша строки, просто используйте hashlib

hash () нацелен на получите хэш-значение объекта, а не stirng.