HAVAL
HAVAL
Fifteen hashes under one name, 3 passes and 128 bits unless asked.
- Digest
- 128-bit · 16 bytes
- HMAC
- takes a key
- Security
- BROKEN: practical collisions with 3 passes (2^29
- Family
- 1 in HAVAL
Sample
- hex
- 906c1df7cbe6d318f36ab172f95e89c0
- base64
- kGwd98vm0xjzarFy+V6JwA==
Options
Access
- Create
create("haval") - CLI
hashes haval 'hello world' - Tryplayground with the sample above
HAVAL isn't one hash. It's fifteen. Zheng, Pieprzyk and Seberry brought it to AUSCRYPT '92 with two dials. One sets 3, 4 or 5 passes over each 128-byte block. The other picks 128, 160, 192, 224 or 256 bits. The name alone tells you neither.
So which one is plain haval? The one the authors' haval.h builds when nobody touches it: 3 passes, 128 bits. Anything else you ask for out loud.
create("haval").hash("abc").digest; // "9e40ed883fb63e985d299b40cda2b8f2"
create("haval").hash("abc").options; // { encoding: "hex", passes: 3, bits: 128 }
create("haval").hash("abc", { passes: 5, bits: 256 }).digest;
// "976cd6254c337969e5913b158392a2921af16fca51f5601d486e0a9de01156e7"
Every result names its passes and bits, defaults too. A HAVAL digest without them is a guess. And a wrong guess still looks like a perfectly good hash.
Don't cut HAVAL-256 down to get HAVAL-128 either. The last block carries the pass count and the length. The spare words get folded into the kept ones, not dropped. HAVAL-256 of abc starts with 8699f1e3, HAVAL-128 is 9e40ed88. Nothing in common.
Where do the constants come from? π. The eight starting words and the 128 step constants are its hex digits after the point, the same ones Blowfish opens with. This package works them out the first time you ask, like it does for bcrypt.
How broken is it?
passes | Best collision attack |
|---|---|
| 3 (default) | Practical. 2^29 compressions (Van Rompay and others, 2003), and HAVAL-128 in about 2^6 hashes (Wang and others, 2004) |
| 4 | Practical. 2^36 (Yu, Wang, Yun and Park, 2006) |
| 5 | 2^123 for HAVAL-256 (same paper), the first attack under its birthday bound |
More passes buy time, not safety.
And HAVAL-256 has the MD5 problem on top. Its digest is the whole state, so HAVAL-256(secret + message) extends in every pass count. extendDigest forges it once its parameters name the passes and bits: 256. The shorter ones fold the state and dodge that. Only that, though.
Why keep it?
PHP's hash() still lists all fifteen, haval128,3 through haval256,5. Tripwire still ships the authors' C code. HMAC runs over the 128-byte blocks and matches PHP's hash_hmac in every variant. identifyDigest lists HAVAL three times at each of its lengths, once per pass count, since a 16-byte digest could be any of them.
Got an old haval160,4 column somewhere? That's what this page is for. Anything new gets SHA-256.