Algorithms

HAVAL

Fifteen hashes under one name from 1992. Three pass counts times five lengths and the name alone never says which
IDhaval30 / 46HAVAL · 128-bit
Hash / Legacy

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
6 options, 0 required

Sample

hex
906c1df7cbe6d318f36ab172f95e89c0
base64
kGwd98vm0xjzarFy+V6JwA==

Options

encodingstring
default hex
Output encoding: hex, base64, base64url, binary
keystring
optional
HMAC key; enables HMAC mode
passesnumber
default 3
Passes over each block, 3, 4 or 5, as the reference haval.h numbers them
bitsnumber
default 128
Fingerprint length in bits, 128 to 256 in steps of 32
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("haval")
CLIhashes 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.

ts
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?

passesBest 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)
4Practical. 2^36 (Yu, Wang, Yun and Park, 2006)
52^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.