21

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

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

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

4

7 回答 7

30

我喜欢@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 相关的典型前缀和后缀。

于 2009-08-09T14:29:10.893 回答
10

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

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

于 2009-08-09T14:16:44.313 回答
7

MD5 总是创建一个 128 位哈希。

其他较小的哈希类型(取自维基百科)

Fowler-Noll-Vo 散列函数(32、64、128、256、512 或 1024 位)
Jenkins 散列函数(32 位)
MurmurHash(32 或 64 位)
Pearson 散列(8 位)

但请记住哈希冲突

于 2009-08-09T14:15:34.130 回答
4

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

如果您的目标是将一个小的十进制数转换为一个长的混淆字符串,只需发明一些映射算法并使用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 由公平掷骰子选择。)

于 2009-08-09T14:25:20.417 回答
3

使用 FVNHash - http://www.codeproject.com/KB/security/FnvHash.aspx

您可以设置哈希的长度,出于安全原因不要使用它

于 2009-08-09T14:18:59.333 回答
3

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

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

(留下 b64 引入的尾随填充)

具有将其用于合法文件名的额外优势。(当然,您必须将默认的 / 和 + 字符替换为不与操作系统的文件命名约定冲突的任何其他符号。

base64(通过替换 / 和 +)确保您的哈希不会用特殊字符弄乱 url,这可能对您的网络服务器意味着其他东西

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

md5 ('这个字符串将被散列')

'37aa3296c523f6c5a7fd2102a9155dcc'(十六进制)(32 字节)

raw md5 ('这个字符串将被散列')

[55, 170, 50, 150, 197, 35, 246, 197, 167, 253, 33, 2, 169, 21, 93, 204] = (16 字节)

原始 md5 字符串的 base64

N6oylsUj9sWn_SECqRVdzA==

我的最终哈希

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

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

于 2012-06-25T00:53:22.543 回答
1

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

于 2009-08-09T14:29:56.367 回答