具有最小冲突的短Python字母数字哈希

ens*_*are 26 python hash

我想使用某种哈希函数为表设置非整数主键.md5()似乎有点长(32个字符).

什么是一些替代哈希函数,可能使用字母表中的每个字母以及字符串长度较短且碰撞率较低的整数?

谢谢!

Mat*_*hen 28

你为什么不截断SHA1或MD5?如果你没有截断,你会有更多的碰撞,但它仍然比设计你自己更好.请注意,您可以对截断的哈希进行base64编码,而不是使用十六进制.例如

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

只要你理解权衡,你就可以截断尽可能少(包括根本没有)或尽可能多的截断.

编辑:既然你提到的网址安全,你可以使用urlsafe_b64encodeurlsafe_b64decode,使用-_,而不是+/.

  • @speedplane很小的东西,但`.rstrip('=')`使意图更清晰一点 (4认同)
  • 你为什么不想截断? (3认同)
  • 您可能还想删除添加到结尾的所有`=`字符.它们基本上不会降低碰撞率,但它们会增加两个字符.所以可能是这样的:`base64.urlsafe_b64encode(hasher.digest()[0:10]).replace('=','')` (2认同)

Joh*_*ooy 25

我所知道的最小的内置哈希是md5

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

b'S27ylES0wiLdFAGdUpFgCQ=='
Run Code Online (Sandbox Code Playgroud)

由于生日悖论,低碰撞和短暂有些相互排斥

要使其成为urlsafe,您需要使用base64模块中的函数

>>> import base64
>>> base64.urlsafe_b64encode(hashlib.md5("hello world").digest())
'XrY7u-Ae7tCTyyK7j1rNww=='
Run Code Online (Sandbox Code Playgroud)

但是,以二进制形式将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'
Run Code Online (Sandbox Code Playgroud)

Python 2

>>> base64.urlsafe_b64encode(md5bytes)
'XrY7u-Ae7tCTyyK7j1rNww=='
Run Code Online (Sandbox Code Playgroud)

Python 3

>>> base64.urlsafe_b64encode(md5bytes).decode('ascii')
'XrY7u-Ae7tCTyyK7j1rNww=='
Run Code Online (Sandbox Code Playgroud)

您可以选择的quote_plus还是urlsafe_b64encode你的网址,然后用相应的功能进行解码unquote_plus或者urlsafe_b64decode你看看他们在数据库之前.