3

I have a specific problem about hashing algorithms in Java. I have 2 clients, one running python and the other running Java (I know, I could solve everything by using just python but right now I almost need to use java).

The clients need to compare the inserted passwords in the same way (i.e.: if a PIN generates an hash on the java clients the same hash needs to be generated by the python client.

I read here: Iterative hashing returns different values in Python and Java

And studied the official docs here: https://docs.oracle.com/javase/7/docs/api/java/security/MessageDigest.html

And found out that python allows a seamless iterative encoding, while java does not. I tried to solve the problem using the .clone() method in the following way (java code):

        // creation of SHA-1 instance:
        MessageDigest message = MessageDigest.getInstance("SHA-1");
        // construction of the string to hash:
        String secretMessage = "0" + myPassWord + mySalt;
        // updating the instance:
        message.update(secretMessage.getBytes());
        // cloning the instance:
        MessageDigest messageClone = (MessageDigest) message.clone();
        // digesting the clone: the result is of type byte[]:
        byteResult = messageClone.digest();
        // construction of the previousHash: this will be used in the 
        // next run of SHA-1 hashing. Python runs everything in lowercase.
        // the hash is rendered as HEX characters String:
        prevHash = (DatatypeConverter.printHexBinary(byteResult)).toLowerCase();
        secretMessage = prevHash + "1" + myPassWord + mySalt;
        message.update(secretMessage.getBytes());
        // compute the final digest:
        byteResult = message.digest();
        // print it:
        System.out.println(DatatypeConverter.printHexBinary(byteResult));

Now, by doing a System.out.println on the first iteration (index "0"), the hashes coincide.

Unfortunately, something wrong goes on the subsequent index and I can't, for the love of my, understand what is it. I suspect it's got something to do with how python converts strings and inserts it into the secretMessage variable.

For your information, here is the code in python:

digest2 = ""
for i in range (0, 2):
    digest2 = sha1(digest2 + str(i) + password_to_hash + salt).hexdigest()
    print digest2
3
  • Did you check the input values of digest2 + str(i) + password_to_hash + salt for both programs? Commented Mar 27, 2017 at 12:17
  • Also be careful with getBytes. Specify the charset you want to convert the String with (UTF-8 is a good bet). Make sure it matches the one Python uses. By default it uses the platforms default charset, which could be different on different machines (so that's bad). Commented Mar 27, 2017 at 12:21
  • Yeah I n-checked the inputs: they correctly match. The output from the 0th iteration correctly enters the 1st. So this could be something happening when java parses the input for the .update() method. I just tried specifying "UTF-8" and "ISO_8859_1" charsets: the output hash is exactly the same as before but still different from python's one. I'm leaving UTF-8 for now, your objection makes sense and I was incautious. Commented Mar 27, 2017 at 12:43

1 Answer 1

2

The problem is that in the Java implementation, you feed the MessageDigest first the iteration String, and then the second iteration String without resetting the MessageDigest, so in effect it is creating a single hash of a String like:

"0" + pw + salt + sha-of-data-so-far + "1" + pw + salt

The python implementation however starts a new hash for the second iteration and creates two hashes:

"0" + pw + salt

And then:

sha-of-iteration-1 + "1" + pw + salt
Sign up to request clarification or add additional context in comments.

4 Comments

I'm not a python expert, but the way you call it (without any kind of reference to an object that might still have information about the previous iteration) would suggest that the second iteration is just a hash of hex-of-previous-sha+"1"+pw+salt.
Are you sure Python starts a freshly initialized hash? I am using all that .clone() method to try to emulate python's behavior that, reading the linked thread in my question, should be exactly to concatenate the strings in the iterations in the exact way you pointed out. I know that to emulate this behavior in java I can simply run .digest(): it would automatically reset the instance.
I suppose it is easy to confirm this with a small test :)
Sir, I owe you a pint of beer: looks like I have been deceived by the aforementioned post. It indeed looks like python behaves in the exact same way as java.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.