Próbuję haszować ciąg przy użyciu SHA256, używam następującego kodu:
using System;
using System.Security.Cryptography;
using System.Text;
public class Hash
{
public static string getHashSha256(string text)
{
byte[] bytes = Encoding.Unicode.GetBytes(text);
SHA256Managed hashstring = new SHA256Managed();
byte[] hash = hashstring.ComputeHash(bytes);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
}
Jednak ten kod daje znacznie inne wyniki w porównaniu do php moich znajomych, a także generatorów online (takich jak Ten generator )
Czy ktoś wie na czym polega błąd? Różne bazy?
Odpowiedzi:
Encoding.Unicode
to myląca nazwa Microsoft dla UTF-16 (kodowanie o podwójnej szerokości, używane w świecie Windows ze względów historycznych, ale nie używane przez nikogo innego). http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspxJeśli sprawdzisz swoją
bytes
tablicę, zobaczysz, że co drugi bajt to0x00
(z powodu kodowania o podwójnej szerokości).Zamiast tego powinieneś używać
Encoding.UTF8.GetBytes
.Ale również zobaczysz różne wyniki w zależności od tego, czy uważasz, że
'\0'
bajt kończący jest częścią haszowanych danych. Haszowanie dwóch bajtów"Hi"
da inny wynik mieszania trzech bajtów"Hi"
. Musisz zdecydować, co chcesz zrobić. (Prawdopodobnie chcesz zrobić to, co robi kod PHP twojego przyjaciela).Dla tekstu ASCII na
Encoding.UTF8
pewno będzie odpowiedni. Jeśli dążysz do idealnej zgodności z kodem przyjaciela, nawet na wejściach spoza ASCII, lepiej wypróbuj kilka przypadków testowych ze znakami spoza ASCII, takimi jaké
i,家
i sprawdź, czy wyniki nadal pasują. Jeśli nie, musisz dowiedzieć się, jakiego kodowania naprawdę używa twój przyjaciel; może to być jedna z 8-bitowych „stron kodowych”, które były popularne przed wynalezieniem Unicode. (Ponownie, myślę, że Windows jest głównym powodem, dla którego każdy musi się martwić o „strony kodowe”).źródło
short
s zakodowanych w UTF16 ”, ale nie „sortowanie według bajtów zakodowanych w UTF16”, chyba że jesteś w systemie big-endian, którym nie jest Windows.) Jednak „sortowanie” w Unicode jest tak naprawdę skomplikowany temat, który warto zachować na inny dzień.Miałem też ten problem z innym stylem realizacji, ale zapomniałem skąd go mam, bo to było 2 lata temu.
Kiedy
abcdefghi2013
z jakiegoś powodu wprowadzam coś podobnego , daje to inne wyniki i powoduje błędy w moim module logowania. Potem spróbowałem zmodyfikować kod w taki sam sposób, jak sugerował Quuxplusone i zmieniłem kodowanie odASCII
doUTF8
wtedy wreszcie zadziałało!Jeszcze raz dziękuję Quuxplusone za wspaniałą i szczegółową odpowiedź! :)
źródło
hash += bit.ToString("x2");
, mam tutaj pytanie: użyłemConvert.ToBase64String(byte[] encryptedBytes)
do konwersji z powrotem z bajtów na ciąg. to dawało mi inny wynik. więc jaka jest różnica między tymi dwiema metodami konwersji z bajtów na ciąg znaków ..?Przyczyną różnych wyników jest to, że nie używasz tego samego kodowania ciągów. Łącze, które umieściłeś do witryny internetowej, która oblicza algorytm SHA256, używa kodowania UTF8, podczas gdy w Twoim przykładzie zastosowano kodowanie Unicode. Są to dwa różne kodowania, więc nie uzyskasz tego samego wyniku. W powyższym przykładzie otrzymujesz ten sam skrót SHA256 z połączonej witryny internetowej. Musisz użyć tego samego kodowania również w PHP.
Absolutne minimum każdy programista Absolutnie, pozytywnie musi wiedzieć o Unicode i zestawach znaków (bez wymówek!)
https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
źródło
W wersji PHP można wysłać „true” w ostatnim parametrze, ale domyślną wartością jest „false”. Poniższy algorytm jest odpowiednikiem domyślnej funkcji haszującej PHP podczas przekazywania „sha256” jako pierwszego parametru:
źródło
ASCII
ibyte[] arrBytes = System.Text.Encoding.UTF8.GetBytes(strData)
zamiast tego robiłbym.źródło
Najkrótsza i najszybsza droga w historii. Tylko 1 linia!
źródło
Ta praca dla mnie w .NET Core 3.1.
Ale nie w .NET 5 w wersji zapoznawczej 7.
źródło