C # MD5 хеш-функция возвращает странный результат? - PullRequest
0 голосов
/ 01 марта 2019

Я только что попытался создать хеш-программу MD5 на C #.Мой друг дал мне пример кода об этом, но когда я пытаюсь запустить тест с "123456", вместо того, чтобы вернуть правильный результат хеширования

e10adc3949ba59abbe56e057f20f883e

, он возвращаетрезультат

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();

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Похоже, ваш друг использовал Encoding.Default вместо Encoding.Unicode

Строки в .NET имеют UTF16.Хеширование работает на байтах , но не на строках.Строка должна быть преобразована в байты.Для этого необходимо использовать определенную кодировку.

Если используется собственная кодировка .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, поэтому большинство кодировок , включая UTF8, вернет e10adc3949ba59abbe56e057f20f883e.Следующие кодировки будут возвращать одну и ту же хеш-строку: Encoding.GetEncoding(1251) (кириллица), Encoding.GetEncoding(20000) (китайская традиция) приведут к тому же хешу.

Значение Encoding.Default возвращает кодировку, соответствующую компьютеруязык системы.Это кодировка, используемая не-Unicode-приложениями, такими как приложения C ++, скомпилированные с строковыми типами ANSI.

Encoding.GetEncoding (20273) , хотя и возвращает другое значение - это IBM EBCDIC, который использовал другоебайты даже для английского алфавита и цифр.Это вернет: 73e00d17ee63efb9ae91d274baae2459

0 голосов
/ 01 марта 2019

Вы ожидаете получить строку 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"
...