Search code examples
javapythonhashiterationsha1

Java iterative SHA-1 hashing vs Python


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

Solution

  • 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