Короткий алфавитно-цифровой хэш Python с минимальными коллизиями - PullRequest
23 голосов
/ 24 марта 2010

Я бы хотел установить нецелые первичные ключи для таблицы, используя какую-то хэш-функцию. md5 () кажется длинным (32 символа).

Какие есть альтернативные хеш-функции, которые, возможно, используют каждую букву в алфавите, а также целые числа, которые, возможно, короче длины строки и имеют низкую частоту столкновений?

Спасибо!

Ответы [ 5 ]

25 голосов
/ 24 марта 2010

Почему бы вам просто не обрезать SHA1 или MD5? У вас будет больше коллизий, чем если бы вы не усекались, но это все же лучше, чем создавать свои собственные. Обратите внимание, что вы можете base64-кодировать усеченный хэш, вместо использования шестнадцатеричного. Э.Г.

import base64
import hashlib
hasher = hashlib.sha1("The quick brown fox")
base64.urlsafe_b64encode(hasher.digest()[:10])

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

РЕДАКТИРОВАТЬ: Поскольку вы упомянули URL-безопасный, вы можете использовать urlsafe_b64encode и urlsafe_b64decode , который использует - и _ вместо + и /.

22 голосов
/ 24 марта 2010

Самый маленький встроенный хеш, который я знаю, это md5

>>> import hashlib, base64
>>> d=hashlib.md5(b"hello worlds").digest(); d=base64.b64encode(d); 
>>> print(d)

b'S27ylES0wiLdFAGdUpFgCQ=='

Низкие столкновения и короткие являются несколько взаимоисключающими из-за парадокса дня рождения

Чтобы сделать его безопасным, вам нужно использовать функцию из модуля base64

>>> import base64
>>> base64.urlsafe_b64encode(hashlib.md5("hello world").digest())
'XrY7u-Ae7tCTyyK7j1rNww=='

Однако не должно возникнуть проблем с сохранением 16-байтового дайджеста md5 в базе данных в двоичном виде.

>>> md5bytes=hashlib.md5("hello world").digest()
>>> len(md5bytes)
16
>>> urllib.quote_plus(md5bytes)
'%5E%B6%3B%BB%E0%1E%EE%D0%93%CB%22%BB%8FZ%CD%C3'

Python 2

>>> base64.urlsafe_b64encode(md5bytes)
'XrY7u-Ae7tCTyyK7j1rNww=='

Python 3

>>> base64.urlsafe_b64encode(md5bytes).decode('ascii')
'XrY7u-Ae7tCTyyK7j1rNww=='

Вы можете выбрать quote_plus или urlsafe_b64encode для вашего URL, затем декодировать с помощью соответствующей функции unquote_plus или urlsafe_b64decode, прежде чем искать их в базе данных.

3 голосов
/ 17 июля 2015

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

http://hashids.org/python/

3 голосов
/ 24 марта 2010

Ниже приведено решение, в котором используются буквенно-цифровые символы и несколько знаков пунктуации.Возвращает очень короткие строки (около 8 символов).

import binascii, struct

def myhash(s):
    return binascii.b2a_base64(struct.pack('i', hash(s)))
0 голосов
/ 10 сентября 2010

Вы можете использовать что-то вроде обозначения базы 32. Он более компактен, чем десятичная запись, без учета регистра и без столкновений. Просто закодируйте обычный старый порядковый номер, чтобы сгенерировать короткий хэш-подобный код.

Если ключ не для потребления человеком, вы можете использовать нотацию base 64, которая чувствительна к регистру, но немного более компактна.

См. http://code.google.com/p/py-cupom/ для примера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...