2012-02-24 39 views
7

Próbuję porównać dwa różne ciągi zakodowane przez sha512. Ale wynik jest inny. Może to być problem z kodowaniem. Mam nadzieję że możesz mi pomóc.String SHA-512 Kodowanie: C# i wynik JAVA jest inny

To jest mój kod Java:

MessageDigest digest = java.security.MessageDigest.getInstance("SHA-512"); 
    digest.update(MyString.getBytes()); 
    byte messageDigest[] = digest.digest(); 

    // Create Hex String 
    StringBuffer hexString = new StringBuffer(); 
    for (int i = 0; i < messageDigest.length; i++) { 
     String h = Integer.toHexString(0xFF & messageDigest[i]); 
     while (h.length() < 2) 
      h = "0" + h; 
     hexString.append(h); 
    } 
    return hexString.toString(); 

, a to jest mój kod C#:

 UnicodeEncoding UE = new UnicodeEncoding(); 
     byte[] hashValue; 
     byte[] message = UE.GetBytes(MyString); 

     SHA512Managed hashString = new SHA512Managed(); 
     string hex = ""; 

     hashValue = hashString.ComputeHash(message); 
     foreach (byte x in hashValue) 
     { 
      hex += String.Format("{0:x2}", x); 

     } 
     return hex; 

Gdzie jest problem? Thx dużo facetów

UPDATE

jeśli nie określić typ kodowania, to przypuszcza Unicode myślę. Wynik ten (bez określania czegokolwiek):

Java SHA: a99951079450e0bf3cf790872336b3269da580b62143af9cfa27aef42c44ea09faa83e1fbddfd1135e364ae62eb373c53ee4e89c69b54a7d4d268cc2274493a8 

C# SHA: 70e6eb559cbb062b0c865c345b5f6dbd7ae9c2d39169571b6908d7df04642544c0c4e6e896e6c750f9f135ad05280ed92b9ba349de12526a28e7642721a446aa 

Zamiast tego, jeśli mogę określić UTF-16 w Javie:

Java UTF-16: SHA f7a587d55916763551e9fcaafd24d0995066371c41499fcb04614325cd9d829d1246c89af44b98034b88436c8acbd82cd13ebb366d4ab81b4942b720f02b0d9b 

To zawsze inny !!!

+0

Co się stanie, gdy określisz kodowanie w 'MyString.getBytes()'? (Zła nazwa zmiennej, btw.) –

+1

Czy porównywałeś bajty 'MyString' przed obliczaniem skrótu? –

+0

Byłoby miło dostarczyć nam pełne próbki kodu oraz dane wejściowe/wyjściowe. – birryree

Odpowiedz

6

UnicodeEncoding in C# użyć odpowiada ostrokońcej UTF-16 kodującego, a "UTF-16" w Javie odpowiada kodowaniu UTF-16 w grubokońcej. Kolejną różnicą jest to, że C# nie wyprowadza znacznika kolejności bajtów (zwanego "preambułą" w API), jeśli nie pytasz o niego, podczas gdy "UTF-16" w Javie generuje go zawsze. Aby oba programy kompatybilne można zrobić Java używać również ostrokońcej UTF-16:

digest.update(MyString.getBytes("UTF-16LE")); 

Albo można przełączyć się do innego znanego kodowania, jak UTF-8.

+0

Masz rację! Thx, to działa :) – kinghomer

3

Powodem jest prawdopodobnie brak określenia kodowania do użycia podczas konwersji ciągu na bajty, java używa domyślnego kodowania platformy, a UnicodeEncoding wydaje się używać utf-16.

Edit:

documentation for UnicodeEncoding mówi

Ten konstruktor tworzy instancję, która używa Little Endian Byte Order, zapewnia Unicode bajtowy znacznik zamówienia, a nie rzucać wyjątek po wykryciu nieprawidłowego kodowania.

Javas "UTF-16" wydaje się jednak, aby domyślnie big endian Byte Order. Z kodowaniem znaków lepiej jest być naprawdę specyficznym, istnieje UnicodeEncoding constructor taking two boolean określanie kolejności bajtów, podczas gdy w java są również "utf-16le" i "utf-16be". Można spróbować wykonać następujące czynności w C#

new UnicodeEncoding(true, false) // big endian, no byte order mark 

i w java

myyString.getBytes("utf-16be") 

Albo jeszcze lepiej wykorzystać "UTF-8"/Encoding.UTF8 w obu przypadkach nie ponieważ jest dotkniętych różnymi byteorders .

+0

Nie. Inny wynik występuje jednak – kinghomer

6

Tutaj

digest.update(MyString.getBytes()); 

powinno być jednoznacznie określający kodowanie znaków w String#getBytes() pożądany sposób. W przeciwnym razie domyślny zestaw znaków platformy będzie taki sam jak w przypadku Charset#defaultCharset().

Fix to odpowiednio:

digest.update(MyString.getBytes("UTF-16LE")); 

Powinno być co najmniej taka sama jak UnicodeEncoding charset jest wewnętrznie użyciu.


Niepowiązany do konkretnego problemu, Java ma również zwiększoną for pętlę i String#format().

+0

Ten sam wynik. Oni są różni. Zaktualizowałem post – kinghomer

+0

'UnicodeEncoding' najwyraźniej używa UTF-16LE. Zaktualizowałem odpowiedź. – BalusC

Powiązane problemy