当我23
使用 MD5 加密进行加密时,我得到了37693cfc748049e45d87b8c7d8b9aacd
这个 32 个字符的长字符串,它对于 23 始终是静态的。
我想要相同的机制,但应该生成 18 个或更少(如:)122ff1e4883358b6
字符的长字符串,而不是 32 个。
我如何在 C# 中做到这一点,在 c# 中是否有任何更短版本的 MD5?
当我23
使用 MD5 加密进行加密时,我得到了37693cfc748049e45d87b8c7d8b9aacd
这个 32 个字符的长字符串,它对于 23 始终是静态的。
我想要相同的机制,但应该生成 18 个或更少(如:)122ff1e4883358b6
字符的长字符串,而不是 32 个。
我如何在 C# 中做到这一点,在 c# 中是否有任何更短版本的 MD5?
我喜欢@RichieHindle 的回答。但是,如果您对丢失更少的保真度感兴趣(从而降低冲突的风险),您可以取 MD5 哈希返回的 128 位值,并使用ASCII85(也称为 Base85 编码)对其进行编码,而不是基于十六进制的编码。这将为您提供 20 个字节的整个散列(这比您想要的要多,但您可以砍掉 2 个字节,与使用十六进制编码删除 32 个字节中的 14 个相比,损失要少得多)。
编辑: Prashant 说 20 个字符足够接近,并要求提供示例代码:
从 MD5.ComputeHash 调用中获取 MD5 哈希后,您可以使用Jeff Atwood 的 ASCII85 编码器:
MD5 m = MD5.Create();
byte[] hash = m.ComputeHash(System.Text.Encoding.ASCII.GetBytes("23"));
Ascii85 encoder = new Ascii85();
encoder.EnforceMarks = false;
string hash85 = encoder.Encode(hash);
Console.Out.WriteLine(hash85);
产量
2ebDPFFZsD?&,r1fX\$,
所以你可以使用hash85
. encoder.EnforceMarks
确保编码不包含一些与 ASCII85 相关的典型前缀和后缀。
您可以根据需要获取尽可能多的 MD5 哈希值,然后将其余部分丢弃。所有位都具有相同的值,因此这样做与使用一些本机产生较少位的散列算法没有区别。
(如果您出于安全原因这样做,请记住,无论算法如何,更少的位会使哈希更容易破解。即使在安全应用程序之外,更少的位也会增加冲突的风险。还要记住,MD5 相对不安全这些天 - SHA-1 或 SHA-2 被认为更安全。)
MD5 总是创建一个 128 位哈希。
其他较小的哈希类型(取自维基百科)
Fowler-Noll-Vo 散列函数(32、64、128、256、512 或 1024 位)
Jenkins 散列函数(32 位)
MurmurHash(32 或 64 位)
Pearson 散列(8 位)
但请记住哈希冲突
如果您希望能够将结果映射回其原始值而不会发生冲突,我不会使用哈希函数。
如果您的目标是将一个小的十进制数转换为一个长的混淆字符串,只需发明一些映射算法并使用zBase32或类似方法对结果进行编码。
public string Obfuscate(long x)
{
return ToZBase32(BitConverter.GetBytes(x * 63498398L));
}
public long Deobfuscate(string x)
{
return BitConverter.ToInt64(FromZBase32(x)) / 63498398L;
}
23
被编码为"gmuyaiayyyyyy"
. (63498398 由公平掷骰子选择。)
使用 FVNHash - http://www.codeproject.com/KB/security/FnvHash.aspx
您可以设置哈希的长度,出于安全原因不要使用它。
最短的有用哈希算法是 md5 。生成 16 字节 = 128 位哈希。如果您使用 base 64 编码 ...即每字节/字符 6 个有用位。
你应该能够将 md5 减少到 22 个字符(ascii)。你所拥有的是十六进制版本,其中 2 个字节代表一个实际字节
(留下 b64 引入的尾随填充)
具有将其用于合法文件名的额外优势。(当然,您必须将默认的 / 和 + 字符替换为不与操作系统的文件命名约定冲突的任何其他符号。
base64(通过替换 / 和 +)确保您的哈希不会用特殊字符弄乱 url,这可能对您的网络服务器意味着其他东西
ASCII85 添加了在用作文件名和 url 时难以处理的字符
'37aa3296c523f6c5a7fd2102a9155dcc'(十六进制)(32 字节)
[55, 170, 50, 150, 197, 35, 246, 197, 167, 253, 33, 2, 169, 21, 93, 204] = (16 字节)
N6oylsUj9sWn_SECqRVdzA==
我的最终哈希
N6oylsUj9sWn_SECqRVdzA这实际上是 22 个 ascii 字符中的完整 md5
([你可以去掉两个尾随 = 总是有两个用于 md5-稍后在解码时添加它们。也将 b64 中的 + 和 / 字符替换为我更喜欢的任何其他字符 -(破折号)和 _(下划线)]
这个 32 个字符的长字符串是十六进制的数字:0-f 您可以通过将其十六进制值转换为 36 的基数来使其更短:0-z