Подтвердить что ты не робот

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

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

Пример:

>>> hash("235")
-310569535015251310

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

>>> hash("235")
-1900164331622581997

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

4b9b3361

Ответ 1

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

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

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

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

Также см. документацию object.__hash__():

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

Значения

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

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

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

То, что вы реализуете, не очень хорошо.

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

hash() стремится получить значение хеш-объекта, а не стимул.