最短的哈希?MD5 / SHA。首字符,Git。

10

我需要一个哈希函数。用户将把这些哈希值写入计算机,因此哈希值应该很短。我的数据库中将有大约5000万条记录,每个记录都必须有自己的哈希值。我希望拥有唯一的哈希值,但如果有一些记录具有相同的哈希值,我也可以接受。唯一的哈希值更好。

MD2对我来说很好,但哈希非常长:"8350e5a3e24c153df2275c9f80692773" - 32个字符。如果你不得不在键盘上写10个MD2哈希,你肯定不开心...

Git为每个提交使用SHA1(40个字符)。但在输出中只显示前7个字符:

$ git log
commit e2cfc89fae5b43594b2c649fd4c05bcc6d2d12ac
...
commit 56a8b4c50d4269dc3f88727472933fd81231f63b
...
commit ce2e9ddbe896b9592abbd5fcb6604b181809d523
...
commit 498c49833516ea33b6a40697634ea6e3cfd62328
...
commit b7d78aea415e64d8d441f9747fe6d5d48fe54ee5

$ git log --oneline | head -n 5
e2cfc89 commnit message...
56a8b4c commnit message...
ce2e9dd commnit message...
498c498 commnit message...
b7d78ae commnit message...

它如何保证安全性和独特性?例如,如果我使用MD5/SHA-1/SHA-256的前5或10个字符,是否足够安全?

谢谢。

2个回答

14

请查看hashids,它旨在从您的主键(或其他一些唯一数字集合)生成唯一的类YouTube哈希值。它并不像MD5和SHA-1那样是真正的哈希,因为它被设计成可逆的。

例如,如果要对单个整数主键进行“哈希”,则可能会得到以下关系:

(PK: 1) <=> (hashid: 8dY0qQ)

这是从你控制的秘密值开始生成的,因此用户无法确定他们实际引用的主键。如果你的数据库有点复杂,比如有多个分片和复杂的键,你仍然可以使用 hashids。它将整数列表作为输入:

(3, 171, 24) <=> (243j7Z)

作为开发人员,您负责定义哈希的最小长度。随着生成越来越多的哈希值,hashids 可能会生成略长的哈希值。

对于给定的输入(初始种子、最小哈希长度和要哈希的整数列表),哈希值保证是唯一的:

没有冲突。您生成的哈希值应该是唯一的。

支持以下语言:

  • JavaScript
  • Ruby
  • Python
  • Java
  • PHP
  • Perl
  • CoffeeScript
  • Objective-C
  • Go
  • Lua
  • Node.js
  • .NET

9
默认情况下,Git仅显示7个字符,因为它们很可能是唯一的,您可以只使用足够的字符将提交/ blob标识为唯一。但是,在内部,它仍然使用完整的哈希值。如果您的Git树有两个提交具有相同的前7个数字,则如果您只使用7个字符来标识其中一个提交,则会引发错误。
如果用户输入的哈希值系统已知,则允许用户输入尽可能多的字符,如果这不足以唯一地标识他所说的哈希值,则出现错误并提示用户再输入更多字符。
7个十六进制字符给出了大约2x10^7个可能的哈希值。假设您正在使用一个良好的哈希函数-即它在值之间具有均匀分布,则通过平方近似,您有50%的机会在约19k*之后重复。是否接受这种可能性取决于您要插入的数量。
*获取N十六进制字符的哈希碰撞的50%概率所需插入的数量是大约0.5+sqrt(0.25-(2xln(0.5)x16^N))

我知道,为了简化,git仅使用前7个字符。 对于唯一标识仍然使用完整的SHA-1哈希。是否存在相同前7个字符的相同哈希的更强概率? - martin
谢谢你的回复。如果我对“123”使用SHA256哈希,则为“a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3”。是更好地获取前8个字符,还是例如每隔8个字符获取一个字符?你是什么意思呢? - martin
2
你选择哪些字符都没有区别。 - Oliver Matthews

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接