我必须将一个人的姓氏、名字和出生日期的组合保存为哈希。此哈希稍后用于搜索具有完全相同属性的同一个人。我的问题是,如果 SHA-1 是一个有意义的算法。
据我了解 SHA-1,两个不同的人(具有不同属性)几乎不可能获得相同的哈希值。这是正确的吗?
我必须将一个人的姓氏、名字和出生日期的组合保存为哈希。此哈希稍后用于搜索具有完全相同属性的同一个人。我的问题是,如果 SHA-1 是一个有意义的算法。
据我了解 SHA-1,两个不同的人(具有不同属性)几乎不可能获得相同的哈希值。这是正确的吗?
如果您想搜索一个只知道这些凭据的人,您可以将 SHA-1 存储在数据库中(或 MD5 以提高速度,除非您有数亿人需要采样)。
散列将毫无价值,因为它不存储有关此人的信息,但它可以用于搜索数据库。您只想确保这三条信息匹配,因此将它们连接起来是安全的:
user.hash = SHA1(user.firstName + user.DOB + user.lastName)
当您查询时,您可以检查两者是否匹配:
hash = SHA1(query.firstName + query.DOB + query.lastName)
for user in database:
if user.hash == hash:
return user
我放在query.DOB
中间是因为名字和姓氏可能会发生冲突,就像JohnDoe Bob
出生在同一天一样John DoeBob
。我不知道数字名称,所以我认为这将阻止像这样的碰撞;)
但如果这是一个大数据库,我会尝试 MD5。它更快,但有可能发生碰撞(在你的情况下,我可以保证不会发生碰撞)。但是,发生碰撞的可能性非常小。
从这个角度来看,碰撞是一种1 / 2^128
事件,即:
1
---------------------------------------------------
340,282,366,920,938,463,463,374,607,431,768,211,456
这比:
0.0000000000000000000000000000000000000293873 %
我很确定你不会发生碰撞;)
哈希冲突是不可避免的。无论发生碰撞的机会多么小,如果您真的想要 100% 的识别,您不应该只依赖哈希。
如果使用散列来加速数据库搜索,则无需使用 SHA256。使用系统具有最小大小的任何散列函数(MySQL 的 MD5() 或者如果您的数据库不是那么大,您甚至可以尝试 CRC32)。就在您查询表时,您需要提供您正在搜索的所有条件:
SELECT * from user WHERE hash="AABBCCDD" AND firstname="Pavel" AND surname="Sokolov"
数据库维护一个值,称为索引基数。它是给定索引上数据唯一性的度量。因此,您可以将所需的字段与哈希字段一起索引,并且数据库将为查询自己选择最具选择性的索引。添加附加条件不会对性能产生负面影响,因为大多数数据库在从表中选择数据时只能使用一个索引,并且它们会选择具有最大基数值的那个。
数据库将需要首先选择与索引匹配的所有行,然后扫描它们以丢弃与其他条件不匹配的行。
如果你不能使用我描述的方法,那么,我认为即使是 MD5 碰撞概率也很低,在人名数据库上发生。
PS我希望你知道,你知道“一个人的姓氏,名字和出生日期的组合”不足以100%识别一个人吗?并且这种组合将比一些哈希冲突更快地匹配。