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

Короткий алфавитно-цифровой хэш-код Python с минимальными коллизиями

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

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

Спасибо!

4b9b3361

Ответ 1

Почему бы вам просто не обрезать 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, который использует - и _ вместо + и /.

Ответ 2

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

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

b'S27ylES0wiLdFAGdUpFgCQ=='

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

Чтобы сделать это urlsafe, вам нужно использовать функцию из модуля 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=='

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

Ответ 3

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

import binascii, struct

def myhash(s):
    return binascii.b2a_base64(struct.pack('i', hash(s)))

Ответ 4

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

http://hashids.org/python/

Ответ 5

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

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

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