我需要生成可在文件名中使用的唯一标识符,并且可以在给定相同输入值的情况下重现。我需要生成数百万个这样的标识符,因为源输入有数百万种组合。
为了简单起见,我将在示例中使用一个小集合,但实际集合可能相当大(数百个,也许数千个项目);大于可以手动编码到文件名中的值。
我注意到生成 UUID 的第 5 种方法允许您提供字符串输入。
> input_set = {'apple', 'banana', 'orange'}
> uuid.uuid5(uuid.NAMESPACE_URL, pickle.dumps(input_set)).hex
'f39926529ad45997984643816c1bc403'
文档说它在底层使用了
SHA1
。碰撞的风险是否太高?有没有更好的方法来可靠地散列唯一标识符?
字符串发生 SHA1 冲突的可能性非常低。目前 SHA1 的已知冲突少于 63 个。
首次计算 SHA-1 哈希冲突。所需要的只是五个聪明的大脑......和 6,610 年的处理器时间
SHA1 在密码学领域不再被认为是安全的,但肯定超出了您的期望。
加密哈希函数被设计为单向函数。这意味着函数的逆函数“很难”计算。 (即知道输出绝不能帮助您确定输入)正如 Blender 在评论中指出的那样,这与碰撞的可能性无关。
查看生日悖论,了解有关如何计算碰撞概率的一些基本信息。
如果发现冲突可以证明可以从问题 P 中进行多项式时间还原,而问题 P 应该在多项式时间内无法解决,那么加密哈希函数就具有可证明的针对冲突攻击的安全性。然后该函数被称为可证明安全的,或者只是可证明的。
这里是“安全”哈希算法的列表。
更新 您在评论中指出您的输入远大于 SHA1 的 160 位限制。在这种情况下,我建议您使用 SHA3,因为输入的大小没有限制。查看 Python 文档以获取更多信息。
这是一个基本示例:
import sha3
k = sha3.keccak_512()
k.update(b"data")
k.hexdigest()
'1065aceeded3a5e4412e2187e919bffeadf815f5bd73d37fe00d384fe29f55f08462fdabe1007b993ce5b8119630e7db93101d9425d6e352e22ffe3dcb56b825'
base64.urlsafe_b64encode
输出越小越好:
> import base64, hashlib
> base64.urlsafe_b64encode(hashlib.sha3_512('asdf'.encode()).digest())
b'jYjPWyD1Os164UebWzbcICF1OwSZAsdyR7snsTGzAL08qL7vKHVtzie4mQhnxFd6JTXn47dRQTmcoalMyEsOuQ=='
上面的输出长度为 88,而相应的十六进制长度为 128。