字符串的快速哈希

时间:2014-02-24 22:00:13

标签: python bash algorithm hash hashids

我有一组ASCII字符串,假设它们是文件路径。它们既短又长。

我正在寻找一种可以计算这种字符串散列的算法,这个散列也是一个字符串,但是会有一个固定的长度,就像youtube video id一样:

https://www.youtube.com/watch?v=-F-3E8pyjFo
                                ^^^^^^^^^^^

MD5似乎就是我所需要的,但对我来说,拥有一个简短的哈希字符串至关重要。

是否有shell命令或python库可以做到这一点?

5 个答案:

答案 0 :(得分:2)

我猜这个问题是偏离主题的,因为基于意见,但至少有一个提示,我知道FNV hash,因为 The Sims 3 使用它来查找资源基于他们在不同内容包之间的名称。它们使用64位版本,所以我想它足以避免相对较大的参考字符串集中的冲突。 The hash is easy to implement,如果没有模块满足您(例如pyfasthash有一个实现)。

要从中获取短字符串,我建议您使用base64编码。例如,这是base64编码的64位散列的大小:nsTYVQUag88=(你可以摆脱或填充=)。

编辑:我最终遇到了与您相同的问题,因此我实施了上述想法:https://gist.github.com/Cilyan/9424144

答案 1 :(得分:2)

另一种选择:hashids旨在解决这个问题,并已移植到许多语言,包括Python。它不是MD5或SHA1意义上的哈希,它是单向的; hashids“哈希”是可逆的。

您有责任使用机密值为库提供种子并选择最小哈希长度。

一旦完成,库就可以在整数之间进行双向映射(单个整数,如简单的主键或整数列表,以支持复合键和分片等)和配置长度的字符串(或微微多一点)。用于生成“哈希”的字母表是完全可配置的。

我在this other answer中提供了更多详细信息。

答案 2 :(得分:1)

您可以使用sum程序(假设您使用的是Linux),但请记住,哈希越短,您可能遇到的冲突就越多。您也可以随时截断MD5 / SHA哈希值。

编辑:这是一个哈希函数列表:List of hash functions

答案 3 :(得分:0)

需要记住的是,哈希码是单向函数 - 您不能将它们用于“视频ID”,因为您无法从哈希返回到原始路径。除了其他任何东西之外,很有可能发生哈希冲突,你最终会得到两个哈希指向同一个视频而不是不同的哈希。

要创建像youtube一样的Id,最简单的方法是创建一个唯一的ID,但通常这样做(例如数据库中的自动键列),然后以可逆的方式将其映射到唯一的字符串。 / p>

例如,您可以获取一个整数id并将其映射到基数为36的0-9a-z ...甚至是基数62中的0-9a-zA-Z,将生成的字符串填充到所需的长度,如果id本身并没有提供足够的字符。

答案 4 :(得分:0)

Python有一个内置的hash()函数,它非常快速且适用于大多数用途:

@EnableEurekaServer

然后,您可以将其转换为16字节的十六进制字符串:

>>> hash("dfds")
3591916071403198536

或N * 2字节字符串,其中N是< = 8:

>>> hash("dfds").to_bytes(8,"big").hex()

...等。如果你想要N大于8个字节,你可以只哈希两次。 Python的内置速度非常快,除非你需要安全性,否则永远不值得使用hashlib,而不仅仅是碰撞阻力。

>>> hashn=lambda word, N  : (hash(word)%(2**(N*8))).to_bytes(N,"big").hex()

最后,使用urlsafe base64编码制作比“hex”更好的字符串

>>> hashnbig=lambda word, N  : ((hash(word)+2**64*hash(word+"2"))%(2**(N*8))).to_bytes(N,"big").hex()

不要在实际代码中使用这种lambda样式......写出来!并且在代码中填充像2 ** 32这样的东西,而不是使它们成为常量会使事情变得很慢。

最后,对于较小的应用程序,8个字节的碰撞阻力是可以的....如果条目少于一百万,则碰撞的几率为< 0.0000001%。那是一个12字节的b64编码字符串。