Java和C#之间SHA1哈希结果不同

4

我有一个大问题。 我正在使用这个C#函数来编码我的消息:

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

我的信息是:Block|Notes|Text !£$%&/()=?^€><{}ç°§;:_-.,@#ùàòè+

我得到的结果如下:

(C#)   8EDC7F756BCECDB99B045FA3DEA2E36AA0BF0875
(Java) 2a566428826539365bb2fe2197da91395c2b1b72

请问您需要帮忙吗?谢谢...


1
为什么在Java代码片段中使用iso-8859-1编码,而不在C#代码片段中使用? - Lazarus
1
在计算哈希之前,这些字节数组是什么?它们可能不相同(可能是因为您使用了ASCII和ISO-8850-1编码)。 - Progman
请查看https://dev59.com/gFPTa4cB1Zd3GeqPmclA。 - Koekiebox
3个回答

4

在C#方面使用ISO-8859-1的更改很容易:

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

然而,如果您的文本包含U+00FF以上的Unicode字符,则ASCII和此编码都会丢失数据。
理想情况下,如果您的源数据确实是文本,则应使用可以处理任何内容的编码(例如UTF-8),如果您的源数据实际上是二进制数据,则根本不应进行文本编码。

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哈希算法会传递不同的参数,导致返回不同的值。


我能在C#端更改代码吗? 对于Java端来说,这对我来说更加困难...(我不能触碰Java端) - CeccoCQ
1
Jon Skeet 在他的帖子中解释了这个问题。 - Meiscooldude

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;
}

你能说出他做了什么导致这种差异吗? - Austin Henley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接