I am looking for a cryptographic hash function optimized for speed on short inputs, in order to implement a pseudorandom generator with expansion factor 2 (e.g. takes 16 bytes of input and outputs 32 pseudorandom bytes).
Here are some natural candidates I tried:
- SHA256: good baseline
- Blake2: designed for speed on large inputs, does not perform as well on short inputs
- AES-CTR: faster than SHA256 when the hardware supports AES-NI. The input is used as a key for AES to encrypt a predefined byte array of the desired output length. However, re-initializing the cipher for each call to the hash function is costly.
I also found this interesting construction: STHash. It is a keyed cryptographic hash function optimized for speed on large inputs. I don't mind having a keyed hash function instead of a general-purpose one.
Is there any analogous construction for short inputs, or a more efficient way to leverage AES-NI than AES-CTR?
Some informal benchmarks
For each hash function, I hash an array of 16 bytes into a 32 bytes array, and I repeat 10 million times. For stream ciphers like AES and ChaCha, I create a new cipher at each iteration with the input as key on a public fixed plaintext and nonce. If the cipher needs a 32-bit key, I just pad the input with 0. If the hash function does not produce enough bits (e.g. SipHash outputs only 128 bits), I run it several times.
I am running Rust Nightly on an Intel® Core™ i7-1065G7 CPU @ 1.30GHz × 8, the experiments run on a single thread.
- SipHash 1-3: 476.9ms
- Chacha8: 590.4ms
- SipHash: 670.3ms
- AES-128: 665.3ms
- SHA256: 780.4ms
- Blake2s: 1413.9ms
For information, some results about Haraka (using a not well-known optimized implementation):
- Haraka-v2 256-5: 55.2ms
- Haraka-v2 256-6: 69.9ms