C# MD5 哈希函数 return 奇怪的结果?
C# MD5 hash function return weird result?
我刚刚尝试在 C# 中创建一个 MD5 哈希程序。我的朋友给了我一个关于这个的示例代码,但是当我尝试 运行 使用“123456”进行测试时,而不是返回正确的哈希结果
e10adc3949ba59abbe56e057f20f883e
它returns结果
ce0bfd15059b68d67688884d7a3d3e8c
我试图阅读主要代码,但仍然一无所获!
string value = textBox1.Text;
byte[] valueBytes = new byte[value.Length * 2];
Encoder encoder = Encoding.Unicode.GetEncoder();
encoder.GetBytes(value.ToCharArray(), 0, value.Length, valueBytes, 0, true);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(valueBytes);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
stringBuilder.Append(hashBytes[i].ToString("x2"));
}
textBox2.Text = stringBuilder.ToString();
你期待的是UTF8字符串,为什么要用Unicode编码?使用 UTF8,你会得到你期望的结果:
string value = "123456";
byte[] valueBytes = new byte[value.Length]; // <-- don't multiply by 2!
Encoder encoder = Encoding.UTF8.GetEncoder(); // <-- UTF8 here
encoder.GetBytes(value.ToCharArray(), 0, value.Length, valueBytes, 0, true);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(valueBytes);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
stringBuilder.Append(hashBytes[i].ToString("x2"));
}
Console.WriteLine(stringBuilder.ToString()); // "e10adc3949ba59abbe56e057f20f883e"
看起来你的朋友使用了 Encoding.Default
而不是 Encoding.Unicode
.NET 中的字符串是 UTF16。但是,哈希适用于 bytes,不适用于字符串。字符串必须转换为字节。为此,必须使用特定的编码。
如果使用 .NET 本机编码,即 UTF16,原始字节缓冲区将为 12 个字节长,哈希的十六进制表示将为 ce0bfd15059b68d67688884d7a3d3e8c
:
var valueBytes=Encoding.Unicode.GetBytes("123456");
Debug.Assert(valueBytes.Length==12);
var md5=System.Security.Cryptography.MD5.Create();
byte[] hashBytes = md5.ComputeHash(valueBytes);
var hexText=String.Join("",hashBytes.Select(c=>c.ToString("x2")));
如果使用 7 位 US-ASCII 编码,数组长度为 6 个字节,十六进制表示为 e10adc3949ba59abbe56e057f20f883e
:
var valueBytes=Encoding.ASCII.GetBytes("123456");
Debug.Assert(valueBytes.Length==6);
var md5=System.Security.Cryptography.MD5.Create();
byte[] hashBytes = md5.ComputeHash(valueBytes);
var hexText=String.Join("",hashBytes.Select(c=>c.ToString("x2")));
大多数代码页的前 127 个字节匹配 7 位 US-ASCII 字符,因此 most encodings,包括 UTF8,将 return e10adc3949ba59abbe56e057f20f883e
。以下编码将 return 相同的散列字符串:Encoding.GetEncoding(1251)
(西里尔文),Encoding.GetEncoding(20000)
(繁体中文)将产生相同的散列。
Encoding.Default
值 return 是与计算机系统区域设置相对应的编码。它是非 Unicode 应用程序使用的编码,例如使用 ANSI 字符串类型编译的 C++ 应用程序。
Encoding.GetEncoding(20273) 虽然会 return 一个不同的值 - 这是一个 IBM EBCDIC,即使对于英文字母和数字也使用不同的字节。这将 return : 73e00d17ee63efb9ae91d274baae2459
我刚刚尝试在 C# 中创建一个 MD5 哈希程序。我的朋友给了我一个关于这个的示例代码,但是当我尝试 运行 使用“123456”进行测试时,而不是返回正确的哈希结果
e10adc3949ba59abbe56e057f20f883e
它returns结果
ce0bfd15059b68d67688884d7a3d3e8c
我试图阅读主要代码,但仍然一无所获!
string value = textBox1.Text;
byte[] valueBytes = new byte[value.Length * 2];
Encoder encoder = Encoding.Unicode.GetEncoder();
encoder.GetBytes(value.ToCharArray(), 0, value.Length, valueBytes, 0, true);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(valueBytes);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
stringBuilder.Append(hashBytes[i].ToString("x2"));
}
textBox2.Text = stringBuilder.ToString();
你期待的是UTF8字符串,为什么要用Unicode编码?使用 UTF8,你会得到你期望的结果:
string value = "123456";
byte[] valueBytes = new byte[value.Length]; // <-- don't multiply by 2!
Encoder encoder = Encoding.UTF8.GetEncoder(); // <-- UTF8 here
encoder.GetBytes(value.ToCharArray(), 0, value.Length, valueBytes, 0, true);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(valueBytes);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
stringBuilder.Append(hashBytes[i].ToString("x2"));
}
Console.WriteLine(stringBuilder.ToString()); // "e10adc3949ba59abbe56e057f20f883e"
看起来你的朋友使用了 Encoding.Default
而不是 Encoding.Unicode
.NET 中的字符串是 UTF16。但是,哈希适用于 bytes,不适用于字符串。字符串必须转换为字节。为此,必须使用特定的编码。
如果使用 .NET 本机编码,即 UTF16,原始字节缓冲区将为 12 个字节长,哈希的十六进制表示将为 ce0bfd15059b68d67688884d7a3d3e8c
:
var valueBytes=Encoding.Unicode.GetBytes("123456");
Debug.Assert(valueBytes.Length==12);
var md5=System.Security.Cryptography.MD5.Create();
byte[] hashBytes = md5.ComputeHash(valueBytes);
var hexText=String.Join("",hashBytes.Select(c=>c.ToString("x2")));
如果使用 7 位 US-ASCII 编码,数组长度为 6 个字节,十六进制表示为 e10adc3949ba59abbe56e057f20f883e
:
var valueBytes=Encoding.ASCII.GetBytes("123456");
Debug.Assert(valueBytes.Length==6);
var md5=System.Security.Cryptography.MD5.Create();
byte[] hashBytes = md5.ComputeHash(valueBytes);
var hexText=String.Join("",hashBytes.Select(c=>c.ToString("x2")));
大多数代码页的前 127 个字节匹配 7 位 US-ASCII 字符,因此 most encodings,包括 UTF8,将 return e10adc3949ba59abbe56e057f20f883e
。以下编码将 return 相同的散列字符串:Encoding.GetEncoding(1251)
(西里尔文),Encoding.GetEncoding(20000)
(繁体中文)将产生相同的散列。
Encoding.Default
值 return 是与计算机系统区域设置相对应的编码。它是非 Unicode 应用程序使用的编码,例如使用 ANSI 字符串类型编译的 C++ 应用程序。
Encoding.GetEncoding(20273) 虽然会 return 一个不同的值 - 这是一个 IBM EBCDIC,即使对于英文字母和数字也使用不同的字节。这将 return : 73e00d17ee63efb9ae91d274baae2459