简体   繁体   English

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

[英]Different SHA1 Hash result between Java and C#

I've a big problem.我有一个大问题。 I using this C# function to encode my message:我使用这个 C# 函数来编码我的消息:

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

On java side, I use this snippet:在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();

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

I have this result:我有这个结果:

(C#)   8EDC7F756BCECDB99B045FA3DEA2E36AA0BF0875
(Java) 2a566428826539365bb2fe2197da91395c2b1b72

Can you help me please??你能帮我吗?? Thanks...谢谢...

My guess is you seem to be comparing ASCII bytes to Latin1 bytes.我的猜测是您似乎正在将 ASCII 字节与 Latin1 字节进行比较。 Try switching尝试切换

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

to this对此

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

That might solve your problem.那可能会解决您的问题。

(Or switch C# to use Latin1) (或将 C# 切换为使用 Latin1)

What is happening in your program your GetBytes method is returning different values for the same characters depending on encoding, so our nifty SHA1 hash algorithm is getting passed different parameters resulting in different return values.在您的程序中发生了什么,您的GetBytes方法根据编码为相同的字符返回不同的值,因此我们漂亮的 SHA1 哈希算法正在传递不同的参数,从而导致不同的返回值。

The change to use ISO-8859-1 on the C# side is easy:在 C# 端使用 ISO-8859-1 的更改很容易:

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

However, both this and ASCII will lose data if your text contains Unicode characters above U+00FF.但是,如果您的文本包含 U+00FF 以上的 Unicode 字符,则 this 和 ASCII 都会丢失数据。

Ideally if your source data is genuinely text, you should use an encoding which will cope with anything (eg UTF-8) and if your source data is actually binary, you shouldn't be going through text encoding at all.理想情况下,如果您的源数据是真正的文本,您应该使用可以处理任何内容的编码(例如 UTF-8),如果您的源数据实际上是二进制,则根本不应该进行文本编码。

Try the following code:试试下面的代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM