2010-07-08 89 views
4

我遇到了一個很大的問題。 我用這個C#函數來編碼我的留言:Java和C之間不同的SHA1哈希結果#

byte[] buffer = Encoding.ASCII.GetBytes(file_or_text); 
SHA1CryptoServiceProvider cryptoTransformSHA1 = new SHA1CryptoServiceProvider(); 
String hashText = BitConverter.ToString(cryptoTransformSHA1.ComputeHash(buffer)).Replace("-", ""); 

在Java方面,我用這個片段:

MessageDigest md = MessageDigest.getInstance("SHA-1"); 
byte[] sha1hash = new byte[40]; 
md.update(text.getBytes("iso-8859-1"), 0, text.length()); 
sha1hash = md.digest(); 

我的信息是:座|注意事項|文字£$%& /( ?)= ^€> < {} C°§;:_-,@#ùàòè+

我有這樣的結果:

(C#) 8EDC7F756BCECDB99B045FA3DEA2E36AA0BF0875 
(Java) 2a566428826539365bb2fe2197da91395c2b1b72 

你能幫我嗎? 謝謝...

+1

你爲什麼要使用ISO-8859-1編碼在Java代碼片段,而不是在C#代碼段? – Lazarus 2010-07-08 15:15:56

+1

計算哈希值之前的字節數組是什麼?他們可能不一樣(也許是因爲你使用ASCII和ISO-8850-1編碼) – Progman 2010-07-08 15:16:13

+0

看看http://stackoverflow.com/questions/4819794/sha1-c-sharp-equivalent-of-this-java – Koekiebox 2012-03-28 07:06:03

回答

4

我的猜測是你似乎在比較ASCII字節到Latin1字節。嘗試切換

md.update(text.getBytes("iso-8859-1"), 0, text.length()); 

這個

md.update(text.getBytes("ISO646-US"), 0, text.length()); 

這可能會解決你的問題。

(或交換機C#使用Latin1的)

什麼是發生在你的計劃中的GetBytes方法是相同的字符根據編碼返回不同的值,從而使我們的漂亮的SHA1哈希算法獲得通過不同的參數不同的回報值。

+0

我可以在C#端更改代碼嗎? 在Java方面對我來說更加困難...(我無法觸及Java方面) – CeccoCQ 2010-07-08 15:18:45

+1

Jon Skeet在他的帖子中解釋了它。 – Meiscooldude 2010-07-08 15:27:24

+0

謝謝,我已閱讀你的答案。你是我的C#神! :) – CeccoCQ 2010-07-08 15:27:27

4

的變化使用ISO-8859-1的C#方很簡單:

byte[] buffer = Encoding.GetEncoding(28591).GetBytes(file_or_text); 

然而,無論這一點,如果你的文本中包含上述U + 00FF的Unicode字符的ASCII數據就會丟失。理想情況下,如果您的源數據是真正的文本,您應該使用能夠處理任何內容(如UTF-8)的編碼,並且如果您的源數據實際上是二進制文件,則根本不應該經歷文本編碼。

0

試試下面的代碼:

public static string Sha1encode(string toEncrypt) { 
    // Produce an array of bytes which is the SHA1 hash 
    byte[] sha1Signature = new byte[40]; 

    byte[] sha = System.Text.Encoding.Default.GetBytes(toEncrypt); 
    SHA1 sha1 = SHA1Managed.Create(); 
    sha1Signature = sha1.ComputeHash(sha); 

    // The BASE64 encoding standard's 6-bit alphabet, from RFC 1521, 
    // plus the padding character at the end. 

    char[] Base64Chars = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 
      'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 
      'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 
      'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 
      't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', 
      '5', '6', '7', '8', '9', '+', '/', '=' }; 
    // Algorithm to encode the SHA1 hash using Base64 
    StringBuilder sb = new StringBuilder(); 
    int len = sha1Signature.Length; 
    int i = 0; 
    int ival; 
    while (len >= 3) { 
     ival = ((int) sha1Signature[i++] + 256) & 0xff; 
     ival <<= 8; 
     ival += ((int) sha1Signature[i++] + 256) & 0xff; 
     ival <<= 8; 
     ival += ((int) sha1Signature[i++] + 256) & 0xff; 
     len -= 3; 
     sb.Append(Base64Chars[(ival >> 18) & 63]); 
     sb.Append(Base64Chars[(ival >> 12) & 63]); 
     sb.Append(Base64Chars[(ival >> 6) & 63]); 
     sb.Append(Base64Chars[ival & 63]); 
    } 
    switch (len) { 
    case 0: // No pads needed. 
     break; 
    case 1: // Two more output bytes and two pads. 
     ival = ((int) sha1Signature[i++] + 256) & 0xff; 
     ival <<= 16; 
     sb.Append(Base64Chars[(ival >> 18) & 63]); 
     sb.Append(Base64Chars[(ival >> 12) & 63]); 
     sb.Append(Base64Chars[64]); 
     sb.Append(Base64Chars[64]); 
     break; 
    case 2: // Three more output bytes and one pad. 
     ival = ((int) sha1Signature[i++] + 256) & 0xff; 
     ival <<= 8; 
     ival += ((int) sha1Signature[i] + 256) & 0xff; 
     ival <<= 8; 
     sb.Append(Base64Chars[(ival >> 18) & 63]); 
     sb.Append(Base64Chars[(ival >> 12) & 63]); 
     sb.Append(Base64Chars[(ival >> 6) & 63]); 
     sb.Append(Base64Chars[64]); 
     break; 
    } 

    string base64Sha1Signature = sb.ToString(); 
    return base64Sha1Signature; 
} 
+0

你能說出他在做什麼來造成這種差異嗎? – 2012-10-10 20:06:08