C# 如果替换MD5散列中的字符,是否会增加冲突的可能性?
我们正在生成散列,为存储在RavenDB中的文档提供标识符。我们这样做是因为如果您希望像这样使用BulkInsert,DocumentID的长度(127个字符-)有一个限制:C# 如果替换MD5散列中的字符,是否会增加冲突的可能性?,c#,hash,md5,ravendb,C#,Hash,Md5,Ravendb,我们正在生成散列,为存储在RavenDB中的文档提供标识符。我们这样做是因为如果您希望像这样使用BulkInsert,DocumentID的长度(127个字符-)有一个限制: _documentStore.BulkInsert(options: new BulkInsertOptions { CheckForUpdates = true })) 为了使BulkInsert工作,DocumentID需要与被插入的行匹配;因此,我们需要一个可以从相同的源字符串一致地重新生成的DocumentID
_documentStore.BulkInsert(options: new BulkInsertOptions { CheckForUpdates = true }))
为了使BulkInsert工作,DocumentID需要与被插入的行匹配;因此,我们需要一个可以从相同的源字符串一致地重新生成的DocumentID
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不支持DocumentID中的“\”;所以我想用“/”来代替它。然而,我担心这样做会增加散列冲突的可能性
我要更改为的代码:
public static string GetMD5Hash(string inputString)
{
HashAlgorithm algorithm = MD5.Create();
var hashBytes = algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
return Encoding.UTF8.GetString(hashBytes).Replace('\\', '"');
}
这是否会增加散列冲突的可能性,并消除我们依赖DocumentID为“唯一”的能力?-
将随机字节数组读取为UTF8字符串将具有不可打印和0
字符,以及由于UTF8序列不正确而导致的随机故障
使用Base64(如果需要不区分大小写的字符串,则使用base32)。如果某些字符仍然不受支持-替换为其他唯一字符。即使用-
,-
和无填充来简化作为查询参数的编码
对原问题:
- 由于可能发生冲突,任何类型的散列都不能被视为文档的“唯一ID”
- 是的,将一个字符替换为字符串中已经可以使用的另一个字符将减少可能的组合数量,并增加冲突的可能性。我无法正确估计——如果你真的需要精确的答案,可能需要数学或统计学的具体问题
看一看。你增加了碰撞的概率,但只增加了一点点。输出哈希中的所有“/”类似于“通配符”,与原始哈希中的“/”或“\”匹配。如果散列中没有这些内容,则不会发生任何更改。如果在散列中有其中一个,那么现在可以匹配该散列的文档数量将增加一倍。如果一个散列中有两个,则其数量是原来的四倍。考虑到字母表和MD5散列的长度,不太可能有更多 碰撞的可能性仍然很小(除非您有大量文档等) 但是,您应该按照注释中的建议进行操作,并使用Base64或十六进制字符串来存储MD5
当你“推出你自己的”并尝试修改你没有从里到外理解的协议时,密码术中可能会发生一些不好的事情。你应该始终坚持做标准的事情,这些事情都经过了理论和实践的检验,并且被证明是合理的。Bruce Schneier在实用密码学和其他领域详细阐述了这一原则。是否可以基于
输入字符串重新计算相同的DocumentID
?也就是说,如果以后为inputString
提供相同的值,您希望返回相同的DocumentID
?或者,您只是想要一种机制来生成唯一的DocumentID
,而不管inputString
是什么?(也就是说,在以后传递相同的inputString
,可以获得一个新的DocumentID
?)如果您有127个字符,您就有足够的空间来存储a,这听起来与您想要的完全一样。使用Base64而不是UTF8,您将解决问题。重新计算相同的documnId。因此,DocumentID最初是基于先前值的串联,例如NetworkName\u LocationName\u AreaName
。但是,如果要使用BulkInsert
执行批量升级,则ID不能超过127个字符。请参阅上下文,然后我建议阅读。这将减少MD5上发生碰撞的机会(通常使用SHA1而不是MD5)。+1。如果有人决定计算碰撞概率的精确增长,这看起来是一个很好的起点。