什么是最短的哈希值(在文件名可用的形式,像hexdigest)在python可用? 我的应用程序要保存缓存文件的某些对象。 该对象必须具有独特的再版(),所以它们被用于“种子”文件名。 我想为每个对象(不是很多),一个可能是唯一的文件名。 他们不应该发生冲突,但如果他们这样做我的应用程序将只是缺乏缓存为对象(以及将要重新编制该对象的数据,应用小成本)。
所以,如果有一个碰撞,我们失去了一个缓存文件,但缓存中的所有对象的收集积蓄,使应用程序启动速度更快,所以也没有多大关系。
现在,我实际使用ABS(哈希(再版(OBJ))); 这是正确的,字符串哈希! 没有发现任何碰撞,但我想有一个更好的散列函数。 hashlib.md5在Python库可用,但hexdigest是很长的,如果放在一个文件名。 替代方案,以合理的抗碰撞性?
编辑:使用的情况是这样的:数据装载变得携带数据对象的新实例。 独特的类型都有独特的再版。 因此,如果一个缓存文件hash(repr(obj))
存在,我认为unpickle缓存文件和与拆封对象替换OBJ。 如果有冲突,并且缓存是一个虚假的比赛,我注意到。 所以,如果我们没有高速缓存或有虚假的比赛,我反而初始化OBJ(重装它的数据)。
结论(?)
该str
的蟒蛇哈希可能是不够好,我只是担心它的抗碰撞性。 但是,如果我可以散列2**16
的物体与它,它会比足够好了。
我发现了如何把一个十六进制哈希(从任何散列源)和使用Base64压缩存储它:
# 'h' is a string of hex digits
bytes = "".join(chr(int(h[i:i+2], 16)) for i in xrange(0, len(h), 2))
hashstr = base64.urlsafe_b64encode(bytes).rstrip("=")
的生日悖论适用:给出了良好的散列函数,在碰撞发生前散列的预期数量为约SQRT(N),其中N是哈希函数可以取不同的值的数目。 (维基百科的条目,我指着会给出确切的公式)。 因此,举例来说,如果你想使用不超过32位,您的碰撞的担心是严重的周边的64K对象(即2**16
对象-的平方根2**32
的不同值的散列函数可以采取)。 多少对象,你希望有,作为一个数量级?
既然你提到的冲突是一个小麻烦,我建议你瞄准的哈希长度是大约你有对象的数量,还是有点的平方较少,但并不比要少得多。
你想使一个文件名 - 是一个区分大小写的文件系统,在Unix典型的,或者你必须照顾不区分大小写的系统呢? 这一点很重要,因为你的目标是为短文件名,但每个字符,你可以用它来代表你的哈希值作为文件名的情况下,sensive VS不敏感的系统发生巨大变化的位数。
在区分大小写的系统,你可以使用标准库base64
模块(我建议编码的“urlsafe”版本,即此功能,避免了“/”字符,可能出现在平原Base64是重要的UNIX文件名) 。 这给你每个字符6位可用,比十六进制的4位/炭好得多。
即使是在不区分大小写的系统,你仍然可以做的比十六进制更好 - 使用base64.b32encode并获得每字符5位。
这些函数和返回字符串; 使用struct
模块把数字转换成字符串,如果你选择的散列函数生成的数字。
如果你有对象的几万,我认为你会带有内置的散列罚款(32位,这取决于你所选择的编码,以便6-7个字符)。 对于一百万对象你想要40位左右(7个或8个字符) - 可以折叠(XOR,不截断;-)一个SHA256下降到一个长有位合理数量的,说128左右,并用%
操作者在编码之前进一步削减它为所需的长度。
字符串的内置散列函数是自由公正的碰撞,也相当短。 它有2**32
的值,所以它是相当不可能的,你会遇到冲突(如果你使用它的ABS值,将只拥有2**31
值)。
你一直在问最短的散列函数。 这肯定会是
def hash(s):
return 0
但我想,你真的不意味着它这样...
您可以通过简单地截断它让你喜欢的任何短哈希。 MD5是总是32位十六进制数字,但它的一个任意子串(或任何其它散列)具有散列的适当品质:相等的值产生相等散列,并且这些值都是围绕一堆传播。
我敢肯定,有Python中的CRC32实现,但可能是太短(8个十六进制数字)。 从正面看,这是非常快的。
发现了它, binascii.crc32
如果你有一个碰撞,你怎么告诉它实际上发生了什么?
如果我是你,我会用hashlib到sha1()
的repr()
然后就得到了它有限的子串(前16个字符,例如)。
除非你是在谈论这些对象的庞大的数字,我会建议你只需要使用完整的哈希值。 然后碰撞的机会是如此,所以,所以,这么小,你永远活到看到它发生(可能)。
此外,如果你正在处理中的很多文件,我猜你的缓存技术应该被调整,以适应它。
我们使用hashlib.sha1.hexdigest(),它产生甚至更长的字符串,具有良好的成功缓存对象。 没有人真正看到缓存文件反正。
Condsidering你的使用情况,如果你没有你的心脏上使用单独的缓存文件中设置的,你是不是太远,发展路径做,你可能会考虑使用shelve
模块。
这会给你一个持久的字典(存储在一个单一的DBM文件),其中存储您的对象。 酸洗/透明地执行在unpickle,而你没有与哈希冲突,文件I / O等,担心自己
对于货架字典键,你只需使用再版(OBJ),并让shelve
处理积攒你的对象为您服务。 一个简单的例子:
import shelve
cache = shelve.open('cache')
t = (1,2,3)
i = 10
cache[repr(t)] = t
cache[repr(i)] = i
print cache
# {'(1, 2, 3)': (1, 2, 3), '10': 10}
cache.close()
cache = shelve.open('cache')
print cache
#>>> {'(1, 2, 3)': (1, 2, 3), '10': 10}
print cache[repr(10)]
#>>> 10
短哈希意味着你可以有两个不同的文件相同的哈希。 同样可能发生的大哈希太多,但其方式更为罕见。 也许这些文件名应有所不同根据其他文献,如microtime中(除非这些文件可能会创建太快)。