C#:如何生成短MD5代码?

C#:如何生成短MD5代码?,c#,hash,cryptography,md5,C#,Hash,Cryptography,Md5,当我使用MD5加密对23进行加密时,我得到了37693cfc748049e45d87b8c7d8b9aacd这个32个字符长的字符串,它在23天内始终是静态的 我想要相同类型的机制,但应该生成18个或更少的字符(比如:122ff1e4883358b6)而不是32个长字符串 我如何在C#中做到这一点,C#中是否有MD5的较短版本?MD5总是创建128位哈希 其他较小的散列类型(取自维基百科) Fowler-Noll Vo哈希函数(32、64、128、256、512或1024位) Jenkins散列

当我使用MD5加密对
23
进行加密时,我得到了
37693cfc748049e45d87b8c7d8b9aacd
这个32个字符长的字符串,它在23天内始终是静态的

我想要相同类型的机制,但应该生成18个或更少的字符(比如:
122ff1e4883358b6
)而不是32个长字符串


我如何在C#中做到这一点,C#中是否有MD5的较短版本?

MD5总是创建128位哈希

其他较小的散列类型(取自维基百科)

Fowler-Noll Vo哈希函数(32、64、128、256、512或1024位)
Jenkins散列函数(32位)
杂音散列(32或64位)
皮尔逊散列(8位)


但是请记住

您可以根据需要获取尽可能多的MD5哈希值,然后丢弃其余的。所有的位都有相等的值,所以这样做和使用一些本机产生较少位的散列算法没有区别

(如果您是出于安全原因而这样做的,请记住,无论采用何种算法,更少的位都会使哈希更容易破解。即使在安全应用程序之外,更少的位也会增加冲突的风险。同时请记住,如今MD5相对不安全-SHA-1或SHA-2被认为更安全。)

使用FVNHash-


您可以设置哈希的长度,但出于安全原因,请勿使用它。

如果您希望能够将结果映射回其原始值而不发生冲突,我不会使用哈希函数

如果您的目标是将一个小的十进制数转换为一个长的模糊字符串,只需发明一些映射算法,并使用或类似的方法对结果进行编码

public string Obfuscate(long x)
{
    return ToZBase32(BitConverter.GetBytes(x * 63498398L));
}

public long Deobfuscate(string x)
{
    return BitConverter.ToInt64(FromZBase32(x)) / 63498398L;
}

23
编码为
“gmuyaiyyyyy”
。(63498398由公平掷骰选择。)

我喜欢@RichieHindle的答案。但是,如果您希望丢失更少的保真度位(从而降低冲突风险),则可以采用MD5哈希返回的128位值,并使用(也称为Base85编码)而不是基于十六进制的编码对其进行编码。这将在20个字节中生成整个哈希(这比您想要的要多,但是您可以切掉2个字节,这比使用十六进制编码删除32个字节中的14个字节所造成的损失要小得多)

编辑:Prashant说20个字符足够近了,并要求提供示例代码:

从MD5.ComputeHash调用获取MD5哈希后,可以使用:

屈服

2ebDPFFZsD?&,r1fX\$,

因此,您只需使用
hash85
编码器.EnforceMarks
确保编码不包括与ASCII85相关的一些典型前缀和后缀。

此32个字符长的字符串是十六进制数字:0-f
您可以通过将其十六进制值转换为36:0-z的基数来缩短它

最短的有用哈希算法是md5。生成16字节=128位哈希。如果您使用Base64编码…即每字节/字符6个有用位

u应该能够将md5减少到22个字符(ascii)。您拥有的是十六进制版本,其中2个字节表示一个实际字节

(保留b64引入的尾部填充)

还有一个额外的优点,就是对合法文件名使用相同的名称。(当然,您必须用任何其他符号替换默认/和+字符,这些符号不会与操作系统的文件命名约定冲突

base64(通过替换/和+)确保哈希不会用特殊字符扰乱url,这些字符对Web服务器可能意味着其他内容

ASCII85添加了在用作文件名和URL时难以处理的字符

md5('此字符串将被哈希') '37aa3296c523f6c5a7fd2102a9155dcc'(十六进制)(32字节)

原始md5('此字符串将被哈希') [55、170、50、150、197、35、246、197、167、253、33、2169、21、93、204]=(16字节)

原始md5字符串的base64 N6oylsUj9sWn_SECqRVdzA==

我的最后一道菜

N6oylsUj9sWn_SECqRVdzA这实际上是22个ascii字符的完整md5


([您可以去掉尾随的两个字符=md5将始终有两个,稍后在解码时添加它们。还可以将b64中的+和/字符替换为我更喜欢的任何其他字符-(破折号)和(下划线)]

SHA-1创建了一个160位的散列。这会不会增加冲突的可能性?我不是密码专家,但丢弃散列的一部分并仍然希望它保持其属性似乎是个坏主意。我也这么认为,只需从MD5中获取前18个字符
37693cfc748049e45d87b8c7d8b9aacd
,但MD5中的前18个字符不是与其他字符串相同吗?托马斯:无论如何都会发生这种情况。较短的散列固有的冲突几率较高。如果值总是小于散列大小,则可以轻松创建不会发生冲突的散列。只有当数据的大小大于n散列的大小,因为每个可能的输入不能一一映射到不同的散列值。你不能使它总是唯一的-它是一个散列,根据定义它有冲突。你做得越短,冲突的可能性就越大。MD5不是加密,它是一个散列算法。两者之间有很大的区别;最重要的是与加密不同的是,散列无法逆转,因为多个输入将产生相同的输出。嗨,Prashant。我看到了你关于在URL中使用字符串的新评论。我可以想出一些方法来再次实现这一点,但如果你扩展了你期望的输入类型,也许我们能够给出一个适合你问题的答案we,这就是为什么你要做MD5哈希,以及你想用URL最终完成什么。这样我们可以用新的解决方案来消除你的任何异议,甚至可以建议另一种方法,比如@tvanfosson的完美哈希函数想法。嗨@Blair:实际上,做URL这样没有什么特别之处,
2ebDPFFZsD?&,r1fX\$,