如果我替换MD5散列中的一个字符,是否会增加冲突的可能性?

本文关键字:字符 一个 是否 可能性 冲突 增加 MD5 替换 如果 | 更新日期: 2023-09-27 18:08:22

我们生成哈希值,为存储在RavenDB中的文档提供标识符。我们这样做是因为如果您想使用BulkInsert,那么documententid的长度是有限制的(127个字符-元素限制):

 _documentStore.BulkInsert(options: new BulkInsertOptions { CheckForUpdates = true }))

为了使BulkInsert工作,documententid需要匹配被插入的行;所以我们需要一个可以从相同的源字符串一致地重新生成的文档id。

MD5哈希将为我们提供一个低碰撞概率的固定长度值,其代码用于生成以下哈希:

public static string GetMD5Hash(string inputString)
{
    HashAlgorithm algorithm = MD5.Create();
    var hashBytes = algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
    return Encoding.UTF8.GetString(hashBytes);
}
然而

;RavenDB不支持文档id中的"'";所以我想用"/"代替它。然而,我担心这样做会增加哈希冲突的可能性。

我想修改的代码:

public static string GetMD5Hash(string inputString)
{
    HashAlgorithm algorithm = MD5.Create();
    var hashBytes = algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
    return Encoding.UTF8.GetString(hashBytes).Replace('''', '"');
}

这会增加哈希冲突的可能性,并消除我们依赖documententid作为"唯一"的能力吗?

如果我替换MD5散列中的一个字符,是否会增加冲突的可能性?

X-Y问题-而不是将字节数组转换为已知可以正确处理为Base64(或类似)字符串的版本,您使用UTF8作为编码。

将随机字节数组读取为UTF8字符串将具有不可打印和0字符以及由于不正确的UTF8序列而导致的随机失败。

使用Base64(或base32,如果需要不区分大小写的字符串)。如果某些字符仍然不支持-替换为其他唯一的字符。即url友好的base64使用-, _和无填充来简化编码作为查询参数。

回复原问题:

  • 由于可能发生冲突,任何类型的哈希都不能被视为文档的"唯一ID"。
  • yes用字符串中已经可以使用的字符替换一个字符将减少可能的组合数量并增加碰撞的可能性。我无法准确估计——如果你真的需要精确的答案,可能需要数学或统计学方面的具体问题。

你增加了碰撞的概率,但只是一点点。输出散列中的所有"/"都类似于"通配符",它们与原始散列中的"/"或"'"匹配。如果你在哈希中没有这些元素,什么都不会改变。如果在散列中有其中一个,那么现在可以匹配该散列的文档的数量是原来的两倍。如果你在哈希中有两个,那就是四倍的数目。考虑到字母表和MD5散列的长度,不太可能有更多。

碰撞的概率仍然非常小(除非你有大量的文档等)。

但是,您应该按照注释中的建议使用Base64或HEX字符串来存储MD5。

在密码学中,当你"自己动手"并试图修改你没有从内到外理解的协议时,不好的事情就会发生。你应该始终坚持做那些经过理论和实践检验,并且被认为是合理的标准事情。Bruce Schneier在Practical Cryptography和其他地方详细阐述了这一原则。

使用Base64而不是UTF8,您将解决您的问题(不再/)。

看一下Convert.ToBase64String