Właśnie próbowałem utworzyć program MD5 Hash w C #. Mój przyjaciel daje mi przykładowy kod o tym, ale kiedy próbuję uruchomić test z "123456", zamiast zwrócić poprawny wynik Hash

E10DC3949BA59AGBE56E057F20F883e.

Zwraca wynik

CE0BFD15059B68D67688884D7A3D3E8C.

Próbowałem przeczytać główny kod, ale nadal nie mogę nic zrobić!

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();
0
ABCD 1 marzec 2019, 13:23

2 odpowiedzi

Najlepsza odpowiedź

Spodziewasz się mieć ciąg UTF8, więc dlaczego używasz kodowania Unicode? Użyj UTF8, a otrzymasz wynik, którego oczekujesz:

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"
0
Sergey Shevchenko 1 marzec 2019, 10:43

Wygląda jak twój przyjaciel użył Encoding.Default zamiast Encoding.Unicode

Struny w .NET są UTF16. Hashing pracuje na bajty , a nie sznurki. Ciąg musi zostać przekonwertowany na bajty. Aby to zrobić, należy użyć konkretnego kodowania.

Jeśli natywne kodowanie .NET jest użyte, tj. UTF16, oryginalny bufor bajtowy będzie 12 bajtów długości, a reprezentacja sześciokątna Hash będzie 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")));

Jeśli stosuje się 7-bitowe kodowanie US-ASCII , tablica będzie 6 bajtów, a reprezentacja sześciokątna będzie 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")));

Pięść 127 bajtów większości kodepagatek pasuje do 7-bitowych znaków US-ASCII, więc Większość zakodowania, w tym UTF8, zwróciłoby e10adc3949ba59abbe56e057f20f883e. Poniższe zakodowanie zwrócą ten sam ciąg mieszisk: Encoding.GetEncoding(1251) (Cyrylica), {X2}} (chińska Traditiona) spowodowałaby to samo Hash.

Wartość Encoding.Default zwraca kodowanie odpowiadające lokalizacji systemu komputera. Jest kodowanie stosowane przez aplikacje nie-Unicode, takie jak aplikacje C ++ skompilowane z typami ciągów ANSI.

encoding.getenCoding (20273) Choć zwróci inną wartość - to IBM EBCDIC, który wykorzystał różne bajty nawet dla alfabetu angielskiego i cyfry. Powróci: 73e00d17ee63efb9ae91d274baae2459

0
Panagiotis Kanavos 1 marzec 2019, 11:22