2012-02-24 50 views
7

Tôi đang cố gắng so sánh hai chuỗi khác nhau được mã hóa bởi sha512. Nhưng, kết quả là khác nhau. Nó có thể là một vấn đề mã hóa tôi có nghĩa là. Tôi hy vọng bạn có thể giúp tôi.Chuỗi SHA-512 Mã hóa: C# và kết quả JAVA khác nhau

Đây là mã Java của tôi:

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

và, đây là mã C# của tôi:

 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; 

đâu là vấn đề? Thx nhiều kẻ

CẬP NHẬT

Nếu tôi không chỉ định kiểu mã hóa, nó giả Unicode tôi nghĩ. Kết quả là thế này (mà không chỉ định bất cứ điều gì):

Java SHA: a99951079450e0bf3cf790872336b3269da580b62143af9cfa27aef42c44ea09faa83e1fbddfd1135e364ae62eb373c53ee4e89c69b54a7d4d268cc2274493a8 

C# SHA: 70e6eb559cbb062b0c865c345b5f6dbd7ae9c2d39169571b6908d7df04642544c0c4e6e896e6c750f9f135ad05280ed92b9ba349de12526a28e7642721a446aa 

Thay vào đó, nếu tôi chỉ định UTF-16 trong Java:

Java UTF-16: SHA f7a587d55916763551e9fcaafd24d0995066371c41499fcb04614325cd9d829d1246c89af44b98034b88436c8acbd82cd13ebb366d4ab81b4942b720f02b0d9b 

Đó là luôn luôn khác nhau !!!

+0

Điều gì sẽ xảy ra khi bạn chỉ định mã hóa trong 'MyString.getBytes()'? (Bad variable name, btw.) –

+1

Bạn đã so sánh các byte của 'MyString' trước khi tính toán băm? –

+0

Nó sẽ là tốt đẹp để cung cấp cho chúng tôi mã mẫu đầy đủ và đầu vào/đầu ra của bạn là tốt. – birryree

Trả lời

6

Các UnicodeEncoding in C# bạn sử dụng tương ứng với UTF-16 mã hóa ít về cuối nhỏ, trong khi "UTF-16" trong Java tương ứng với lớn về cuối nhỏ UTF-16 mã hóa. Một sự khác biệt khác là C# không xuất ra Dấu ngoặc đơn Byte (được gọi là "lời mở đầu" trong API) nếu bạn không yêu cầu, trong khi "UTF-16" trong Java tạo ra nó luôn luôn. Để làm cho hai chương trình tương thích, bạn có thể làm cho Java cũng sử dụng số nhỏ UTF-16:

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

Hoặc bạn có thể chuyển sang một số mã hóa nổi tiếng khác, như UTF-8.

+0

Bạn đã đúng! Thx, nó hoạt động :) – kinghomer

3

Lý do có thể là bạn không chỉ định mã hóa để sử dụng khi chuyển đổi chuỗi thành byte, java sử dụng mã hóa mặc định nền tảng, trong khi UnicodeEncoding dường như sử dụng utf-16.

Edit:

Các documentation for UnicodeEncoding nói

constructor Điều này tạo ra một trường hợp mà sử dụng little endian byte để, cung cấp một Unicode Byte Order Mark, và không ném một ngoại lệ khi phát hiện mã hóa không hợp lệ.

Tuy nhiên, "utf-16" của Javas có vẻ như mặc định là đơn đặt hàng lớn là thứ tự byte. Với mã hóa ký tự của nó tốt hơn để thực sự cụ thể, có một thứ tự byte UnicodeEncoding constructor taking two boolean specifiyng, trong khi trong java cũng có "utf-16le" và "utf-16be". Bạn có thể thử những điều sau đây trong C#

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

và trong java

myyString.getBytes("utf-16be") 

Hoặc thậm chí tốt hơn sử dụng "utf-8"/Encoding.UTF8 trong cả hai trường hợp vì nó là không bị ảnh hưởng bởi byteorders khác nhau .

+0

Không. Kết quả khác nhau xảy ra tuy nhiên – kinghomer

6

Ở đây,

digest.update(MyString.getBytes()); 

bạn sẽ có một cách rõ ràng quy định cụ thể mã hóa ký tự mong muốn trong String#getBytes() phương pháp. Nó sẽ mặc định khác với bộ mã mặc định nền tảng như được lấy bởi Charset#defaultCharset().

Khắc phục sự cố cho phù hợp:

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

Nó ít nhất phải là charset giống như UnicodeEncoding được nội sử dụng.


Không liên quan cho vấn đề cụ thể, Java cũng có một cải tiến for vòng lặp và một String#format().

+0

Kết quả tương tự. Họ khác nhau. Tôi đã cập nhật bài đăng – kinghomer

+0

'UnicodeEncoding' rõ ràng đang sử dụng UTF-16LE. Tôi đã cập nhật câu trả lời. – BalusC

Các vấn đề liên quan