Algorithms

Whirlpool

Rijmen and Barreto's 512-bit hash from 2000. The final 2003 revision that ISO/IEC 10118-3 and VeraCrypt use
IDwhirlpool21 / 46Whirlpool · 512-bit
Hash / Cryptographic

Whirlpool

An AES designer's 512-bit hash, named after a galaxy.

Digest
512-bit · 64 bytes
HMAC
takes a key
Security
No attack on the full hash
Used by
VeraCrypt
4 options, 0 required

Sample

hex
8d8309ca6af848095bcabaf9a53b1b6ce7f594c1434fd6e5177e7e5c20e76cd30936d8606e7f36acbef8978fea008e6400a975d51abe6ba4923178c7cf90c802
base64
jYMJymr4SAlbyrr5pTsbbOf1lMFDT9blF35+XCDnbNMJNthgbn82rL74l4/qAI5kAKl11Rq+a6SSMXjHz5DIAg==

Options

encodingstring
default hex
Output encoding: hex, base64, base64url, binary
keystring
optional
HMAC key; enables HMAC mode
roundsnumber
default 1
How many times to hash, each round hashing the previous digest
chainstring
default bytes
What each round after the first hashes: bytes of the digest, or its lowercase hex

Access

Createcreate("whirlpool")
CLIhashes whirlpool 'hello world'
Tryplayground with the sample above

What do you get when an AES designer builds a hash? Whirlpool. Vincent Rijmen and Paulo Barreto published it in 2000 and named it after a galaxy, M51. Inside sits W, a cipher that looks a lot like AES pumped up to 512 bits. An 8x8 grid of bytes, ten rounds, S-box, shift, mix, add key. Each block keys W with the state, and the result goes back in with the block and the old state. That's the Miyaguchi-Preneel mode.

ts
create("whirlpool").hash("abc").digest;
// "4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c7181eebdb6c57e277d0e34957114cbd6c797fc9d95d8b582d225292076d4eef5"
create("whirlpool").hash("").digest;
// "19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3"

Its S-box is small Lego. Three 4-bit boxes, E, its inverse and R, snap together into the 8-bit one. So this package ships 32 nibbles, not 256 bytes. The first block Whirlpool hashes builds the S-box, the eight lookup tables and the round constants. The constants are just rows of the S-box. Nothing up its sleeve.

Which Whirlpool is this?

The final one. Whirlpool changed twice after 2000, and every revision prints 64 bytes:

NameWhat changedThe quick brown fox starts with
Whirlpool-0 (2000)the original, with a random S-box4f8f5cb5
Whirlpool-T (2001)the S-box built from 4-bit boxes3ccf8252
Whirlpool (2003, this one)the mix matrix, now cir(1, 1, 4, 1, 8, 5, 2, 9)b97de512

The sentence is "The quick brown fox jumps over the lazy dog". Three answers, and only the last is the one ISO/IEC 10118-3 calls Whirlpool. The 2003 fix was a single row of numbers. Put cir(1, 1, 3, 1, 5, 8, 9, 5) back and you're holding Whirlpool-T again. One row, a whole new hash.

So create("whirlpool-t") throws instead of guessing. identifyDigest computes Whirlpool for a 64-byte digest and names the two older ones as hashes it can't compute. A digest that matches nothing here might be one of them. PHP's hash("whirlpool") and RHash give the final one too.

Is it broken?

No. Collisions on the hash reach 5.5 of its 10 rounds, and 8 on the compression function alone. A distinguisher covers all ten rounds of that compression function. Even the people attacking it call its impact on the hash limited. It sits in ISO/IEC 10118-3, and NESSIE picked it. VeraCrypt still offers it for deriving volume header keys. So pbkdf2 and hkdf take it as their digest. VeraCrypt's own PBKDF2 test vector matches byte for byte.

Its digest is the whole state, though. So Whirlpool(secret + message) extends like SHA-256. Same 0x80, only the length field takes 32 bytes, not 8. extendDigest forges it without the secret. Want a MAC? HMAC runs over its 64-byte blocks and matches PHP's hash_hmac.

It isn't fast. Expect a bit under half of SHA-512's speed here. Every 64 bytes cost ten AES-style rounds, twice. Got old Whirlpool digests to check? This is your hash. Starting fresh? SHA-512 or BLAKE2b.