What may be causing conflicts in Whirlpool implementation versions?

I see by layman articles (e.g. at Wikipedia) that the Whirlpool hash function has seemingly three current versions. That is to say, they are referenced as Whirlpool-0 (original reference code), Whirlpool-T, an optimised for hardware version which was changed to whirlpool (let’s call it “current”) due to a somewhat weakening in a diffusion matrix (according to article).

Now, I see some python implementations do indeed use that “current” version. However, I have been using librhash on Linux (i.e. rhash -W \$file) and I’m verifying things with OpenSSL (openssl dgst -whirlpool \$file).

OpenSSL and rHash are consistent with each other, but different from the current version. I also noticed that OpenSSL and rHash do not seem to correlate to either of the previous versions.

Why is this so? Has there been some undocumented update to the default Whirlpool s-boxes or something? Is there a version conflict, or has there been a Whirlpool update I may have missed?

• Great, what I would think would be a fairly important hashing function seems to have a 'version 4' shared among openssl, rhash and perl , yet no one seems to have anything to add about this. This must obviously be entirely uninteresting to people in cryptography and my first ever question on here must have been an utter joke. – user33257 Apr 9 '16 at 4:51
• @Mal Not at all! Knowledge of crypto in general is relatively scarce compared to some other subjects, especially as the subjects get more specific. I doubt it's even been seen by enough people yet. I'll tell you what, if you don't get an answer, I'll put a bounty on your question to encourage someone to answer it. A bounty can be started on a question two days after the question was asked – Ella Rose Apr 9 '16 at 5:30
• Dear Mal, first of all: Welcome to Crypto.SE! Now, as you might have noticed, I have converted your "answer" into a comment (as it does not answer your question). Don’t get me wrong, but there is a difference between answers and comments – our help-center is pretty good at explaining how things work around here. You might want to check it out. If you have any questions related to the help center or this site, please feel invited to ask me or one of the other moderators via our chatroom. We’ll gladly help wherever we can. – e-sushi Apr 9 '16 at 9:49
• Are you sure there is no gremlin (like a rogue terminating byte) in the input you feed to OpenSSL and rHash? At least, check if the file size is what it should be. You would not be the first one to be caught by that. – fgrieu Apr 12 '16 at 14:11

There is no difference.

The wiki page you referred to contains examples of hashes for all three versions of Whirlpool. For string "The quick brown fox jumps over the lazy dog", the current version should produce the following hash:

    B97DE512E91E3828B40D2B0FDCE9CEB3C4A71F9BEA8D88E75C4FA854DF36725F


Let's create a file containing this string and test different implementations.

    $openssl dgst -whirlpool quick.txt whirlpool(quick.txt)= b97de512e91e3828b40d2b0fdce9ceb3c4a71f9bea8d88e75c4fa854df36725fd2b52eb6544edcacd6f8beddfea403cb55ae31f03ad62a5ef54e42ee82c3fb35$ rhash -W quick.txt


Both match the hash from the wiki. Let's test the python implementation using this script:

    import whirlpool

wp = whirlpool.new("The quick brown fox jumps over the lazy dog")
hashed_string = wp.hexdigest()

print(hashed_string)


The output is:

    b97de512e91e3828b40d2b0fdce9ceb3c4a71f9bea8d88e75c4fa854df36725fd2b52eb6544edcacd6f8beddfea403cb55ae31f03ad62a5ef54e42ee82c3fb35


Let's test the reference code from the Whirlpool home page by inserting the following lines at the end of makeISOTestVectors() function:

    const char* quick = "The quick brown fox jumps over the lazy dog";
NESSIEinit(&w);
NESSIEfinalize(&w, digest);
printf("The hash-code is the following 512-bit string.\n\n");
display(digest, DIGESTBYTES); printf("\n\n");
fflush(stdout);


The output is:

    B97DE512E91E3828 B40D2B0FDCE9CEB3 C4A71F9BEA8D88E7 5C4FA854DF36725F


All implementations produce the same hash. Where did you found a mismatching version?

• Please forgive my ignorance.. Are these your sources: cppcrypto on SourceForge. If so, would you email me at noloader, gmail account. I based an implementation of Kalyna on your gear. I want to get some information from you so I can cite your work. – user10496 May 5 '17 at 6:49

Ok. I think I will attempt answering this myself. Given that (at least on linux), perl, openssl have gone down the same path as the rhash author (I am not sure who in fact, implemented this first), the reason for a different digest, is that, due to restricting the input message from $2^{512}$ bits to $2^{64}$ bits max, the first $512$ rows of $4 \times 32$-bit hex words of the S-boxes have been kept, and the last $512$ rows of the tables have been truncated.

I am not in the position of evaluating the security implications of this, and thus do not wish to accept this answer by myself yet (hoping for more professional input).

If however, solid user bases such as perl and openssl use it, I am inclined to suppose this is a viable implementation.

As a sub-question then, I still wonder why this has not been 'updated' as a 'version 4' or a $64$-bit input version more clearly?

EDIT: The "latter half" of S-boxes I thought were truncated are in fact, obsoleted ones from the reference code. This leads to my assumption being wrong and now for sure, it seems there is this version 4 out in the wild.

Surely, with an important hash as whirlpool, someone would have some insight into this. reference code asserts python code != {perl,openssl,rhash}!

EDIT to Kerukuro: I can't comment?

on arch linux, (I also asked someone on another distro), I get :

cat quick.txt


The quick brown fox jumps over the lazy dog cat quick.txt | wc 1 9 44

openssl dgst -whirlpool quick.txt

same intel sandy bridge (arch 64 bit distro): rhash -W quick.txt

perl: whirlpoolsum quick.txt Possible precedence issue with control flow operator at /usr/bin/vendor_perl/whirlpoolsum line 227. 72687676756b91ad986f2e56df761b354b748bc20098354b017b924e82cc67ae059da85f009d1a17c0f12ec0e644c0c3a193f3fc0fee22f053edbfcd95cbf873 quick.txt

The other examples you mention produce the expected result (python, reference nessie source).

So, just to summarise: python does catch the newlines, and for rhash, openssl and echoing, one should do for correct hashing:

echo "The quick brown fox jumps over the lazy dog" | tr -d '\n' | openssl dgst -whirlpool

• "To add to answer above, as I can't comment on it?" - you could comment on it if you were logged in as the account which asked the question. You seem to have ended up with separate registered and unregistered accounts: a mod might be able to merge them for you. – Rup Apr 12 '16 at 22:15
• As for the discrepancy, try stripping the line break then hashing it, i.e. echo -n "The quick brown fox jumps over the lazy dog" > quick.txt. That'll give you wc = 0 9 43 and will match the reference hash. – Rup Apr 12 '16 at 22:22
• Yes, rup.. I thought I HAD.. and I have't , coupled with the fact I don't know python and python on the same files produced different hashes has led me on a wild goosechas. I am very sorry for that. Accidents almost never occcur due to a single point of failure!! :) I wuld just accept the answer of Keruko or so but I can't as I don't think the question realises I am the OP. PS> Sorry about the noise e-rose! :) – Mali Apr 12 '16 at 22:33
• @Mali Do we agree that Keruko should be given the bounty? – Ella Rose Apr 12 '16 at 23:32
• Sure. If you are fine with it. :) [About the accounts. Well, no, it seemed to link my 'mal' with some (guest) mal who posted eons ago. So when I registered, whilst asking this, it thinks I am not OP :) ]. The answer was a mix of openssl channel, keruko and rup. I thought I had removed the trailing \n, but I had been removing \0 and it didn't add up. So sorry for any inconvenience! – Mali Apr 13 '16 at 2:11