PHP 8.1: xxHash hash algorithms support

TypeNew Feature

xxHash is an extremely fast hashing algorithm that is not designed for cryptographic purposes, but provides excellent randomness and dispersion of output, and uniqueness of to minimize collisions. Some xxHash variants in fact, are faster than the RAM throughput provided CPU cache is sufficient and fits.

PHP 8.1 adds support for xxHash algorithm in following variants:

  • xxh32: 32-bit hash output
  • xxh64: 64-bit hash output
  • xxh3: 64-bit hash output
  • xxh128: 128-bit hash output
hash('xxh32',  ''); // cb729dd1
hash('xxh64',  ''); // 9c823891d744a55e
hash('xxh3',   ''); // f406cee14d73b176
hash('xxh128', ''); // 16c27099bd855aff3b3efe27980515ad

xxHash is a streaming hash, and can be used as such:

$context = hash_init('xxh3');
hash_update($context, 'php.');
hash_update($context, 'watch');
hash_final($context); // f406cee14d73b176

xxHash is not a cryptographic hashing algorithm. For password hashing, use password_hash and its friends. Furthermore, none of the xxHash variants are allowed in hash_hmac function.

In PHP 8.1, xxHash is the fastest hashing algorithm supported in PHP.

Algorithm PHP implementation speed (GB/s)
xxh3 15.19
xxh128 14.78
crc32c 14.12
xxh64 13.32
murmur3f 8.87
xxh32 7.47
sha2-256 0.25
sha1-160 0.70
md5-128 0.77

The results above are an excerpt from PHP Hash Algorithm Benchmarks.

xxHash Options

PHP 8.1 supports specifying algorithm-specific options with the new $options parameter. Along with this, xxh* hashing algorithms accept additional options:

Only one option is accepted at a time. For example, if a seed option is specified, it cannot use a secret option in the same hashing operation.

If both secret and seed options are passed, an Error will be thrown.

hash("xxh3", "", false, ["secret" => $secret, 'seed' => 43]);
xxh3: Only one of seed or secret is to be passed for initialization in ... on line ...

seed option

All xxHash variants accept a seed option through the third parameter ($options) of the hash function.

hash('xxh3', ''); // "f406cee14d73b176"

hash("xxh3", "", false, ["seed" => 42]); // de9956536d1e9543
hash("xxh3", "", options: ["seed" => 42]); // de9956536d1e9543

The third example uses named parameters introduced in PHP 8.0.

secret option

xxh3 and xxh128 variants of xxHash accept a secret value in the third parameter ($options array).

The required key must be larger than 135 bytes, and a key longer than 256 bytes will discarded with a warning emitted.

$secret = random_bytes(256);

hash("xxh3", "", false, ["secret" => $secret]);
// "a0dad59ce6341fb0"

It is important that the secret value has a sufficient entropy. PHP built-in random_bytes function is a cryptographically secure random-number generator.

xxh32 and xxh64 variants do not recognize a secret option, and if passed, it will be silently ignored.

  • Passing a secret value smaller than 136 bytes causes an error:

    hash("xxh3", "", false, ["secret" => 'ab'])
    xxh3: Secret length must be >= 136 bytes, ... bytes passed in ... code on line ...
  • Passing a secret value larger than 256 bytes makes PHP trim the value to 256 bytes with a warning:

    hash("xxh3", "", false, ["secret" => str_repeat('a', 257)]);
    hash(): xxh3: Secret content exceeding 256 bytes discarded in ... code on line ...

Backwards Compatibility Impact

xxHash is newly added to PHP 8.1, and older PHP versions will not be able to use xxHash algorithms via hash method.

Attempting to use xxHash algorithms in hash function results in a ValueError exception:

Fatal error: Uncaught ValueError: hash(): Argument #1 ($algo) must be a valid hashing algorithm in ...:...

On PHP versions prior to 8.0, a warning will be raised:

Warning: hash(): Unknown hashing algorithm: xxh3 in ... on line ...

Alternatives implementations include:

  • Megasaxon/php-xxhash - A PHP extension to add xxhash32 and xxhash64 for xxHash variants.
  • exussum12/xxhash - A pure-PHP implementation with FFI support. The pure-PHP implementation is ~600x slower than the native code, and the FFI implementation is only ~0.4x slower.

Related Changes