Calculating SHA-1 hashes in Java and C#

2019-03-20 17:22发布

问题:

Calculating SHA-1 hashes in Java and C#

I'm trying to replicate the logic of a Java application within a C# application. Part of this involves generating an SHA-1 hash of a password. Unfortunately I can't get the same results from Java and C#.

C# Output  : 64  0a  b2 ba e0 7b  ed c4 c1 63  f6 79  a7 46  f7 ab 7f  b5 d1 fa
Java Output: 164 10a b2 ba e0 17b ed c4 c1 163 f6 179 a7 146 f7 ab 17f b5 d1 fa 

To try and figure out what is happening I've been using the Debugger in Eclipse and Visual Studio.

1. Check values of byte[] key:

    Java: { 84, 101, 115, 116 }
    C#  : { 84, 101, 115, 116 }

2. Check value of byte[] hash:

    Java: { 100 10 -78 -70 -32 123 ... }
    C#  : { 100 10  78 186 224 123 ... }

I've read the other posts on this topic, which largely refer to input string encoding, but these don't seem to have helped me. My guess would be that this is something to do with signed vs. unsigned bytes but I'm not making much progress down this track. Any help will be greatly appreciated.

Thanks,

Karle


Java Version:

public void testHash() {

    String password = "Test";

    byte[] key = password.getBytes();

    MessageDigest md = MessageDigest.getInstance("SHA-1");

    byte[] hash = md.digest(key);

    String result = "";
    for ( byte b : hash ) {
        result += Integer.toHexString(b + 256) + " ";
    }

    System.out.println(result);

}

C# Version:

public void testHash() {

    String password = "Test";

    byte[] key = System.Text.Encoding.Default.GetBytes(password);

    SHA1 sha1 = SHA1Managed.Create();

    byte[] hash = sha1.ComputeHash(key);

    String result;
    foreach ( byte b in hash ) {
        result += Convert.ToInt32(b).ToString("x2") + " ";
    }

    Console.WriteLine(result);

}

回答1:

In the Java version, do not use b + 256; instead, use b & 255. The SHA-1 part is fine, this is just a matter of printing the output. Java's "byte" type is signed: it returns values between -128 and 127. To get the corresponding unsigned value, you must add 256 only if the value is negative.

A bitwise AND with 255 (that's what "& 255" does) operates the proper conversion, which, at the binary level, is truncation of the value to its 8 least significant bits.



回答2:

your question and the answer were very useful to me, but I noticed that when the password has the character "0" hash codes generated are different, so I changed a little the code (in Java).

for (int i = 0; i < hash.length; i++)
    {
        String hex = Integer.toHexString(hash[i]);
        if (hex.length() == 1) hex = "0" + hex;
        hex = hex.substring(hex.length() - 2);
        result += hex;
    }


标签: c# java hash sha1