Хеширование (скрытие) строк в Python

Мне нужно, чтобы хэш-строка. Он не должен быть безопасным, потому что он просто будет скрытой фразой в текстовом файле (он просто не должен быть узнаваем для человеческого глаза).

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

Что было бы лучше для этой цели? Можно ли это сделать со встроенными классами?

Ответ 1

Прежде всего, позвольте мне сказать, что вы не можете гарантировать уникальные результаты. Если вы хотите получить уникальные результаты для всех строк в юниверсе, вам лучше сохранить самую строку (или сжатую версию).

Подробнее об этом за секунду. Сначала сделаем хэши.

путь hashlib

Вы можете использовать любой из основных криптографических хэшей для хэша строки с несколькими шагами:

>>> import hashlib
>>> sha = hashlib.sha1("I am a cat")
>>> sha.hexdigest()
'576f38148ae68c924070538b45a8ef0f73ed8710'

У вас есть выбор между SHA1, SHA224, SHA256, SHA384, SHA512 и MD5 в отношении встроенных модулей.

Какая разница между этими хэш-алгоритмами?

Функция хеша работает, беря данные переменной длины и превращая их в данные фиксированной длины.

Фиксированная длина, в случае каждого из алгоритмов SHA, встроенных в hashlib, - это количество бит, указанное в имени (за исключением sha1, которое составляет 160 бит). Если вам нужна большая уверенность в том, что две строки не попадут в одно и то же ведро (то же значение хэша), выберите хеш с большим дайджестом (фиксированная длина).

В отсортированном порядке это размеры дайджеста, с которыми вы должны работать:

Algorithm  Digest Size (in bits)
md5        128
sha1       160
sha224     224
sha256     256
sha384     384
sha512     512

Чем больше дайджест, тем меньше вероятность столкновения, если ваша хеш-функция стоит соли.

Подождите, как насчет hash()?

Встроенная функция hash() возвращает целые числа, которые также могут быть просты в использовании для цели. Однако есть проблемы.

>>> hash('moo')
6387157653034356308
  • Если ваша программа будет запущена в разных системах, вы не можете быть уверены, что hash вернет ту же самую вещь. На самом деле, я работаю на 64-битном поле, используя 64-битный Python. Эти значения будут сильно отличаться от 32-битного Python.

  • Для Python 3.3+, как указано @gnibbler, hash() рандомизируется между прогонами. Он будет работать в течение одного прогона, но почти наверняка не будет работать в разных версиях вашей программы (вытаскивая из упомянутого текстового файла).

Почему hash() будет построен таким образом? Ну, встроенный хэш существует по одной конкретной причине. Хэш-таблицы/словари/поиск таблиц в памяти. Не для криптографического использования, а для дешевых поисков во время выполнения.

Не используйте hash(), используйте hashlib.

Ответ 2

Вы можете просто использовать модуль base64 для достижения своей цели:

>>> import base64
>>> a = 'helloworld'
>>> encoded_str = base64.encodestring(a)
>>> encoded_str
'aGVsbG93b3JsZA=='
>>> base64.decodestring(encoded_str)
'helloworld'
>>>

конечно, вы также можете использовать модуль hashlib, он более безопасен, потому что хешированная строка не может (или очень сильно) декодироваться последней, но для вашего вопроса base64 достаточно - "На самом деле это не обязательно быть безопасным"

Ответ 3

Обратите внимание, что хеш строки Python не "определен" - он может и зависит от версий и реализаций. Поэтому сохранение хеша строки Python создаст трудности. Хеш строчной строки CPython также не пытается "затушевать".

Стандартным подходом является использование хеш-функции, предназначенной для такого рода вещей. Вот так:

>>> import hashlib
>>> encoded = hashlib.sha1("abcdef") # "abcdef" is the password
>>> encoded.hexdigest()
'1f8ac10f23c5b5bc1167bda84b833e5c057a77d2'

Эта длинная строка шестнадцатеричных цифр является "хешем". SHA-1 - это "сильная" хэш-функция. Вы можете стать знаменитым, если найдете две строки, которые имеют хэш, с тем же значением;-) И с учетом того же ввода он вернет тот же самый "hexdigest" на всех платформах во всех выпусках и реализациях Python.

Ответ 4

Просто используйте hash() встроенную функцию, например:

s = 'a string'
hash(s)
=> -8411828025894108412