Convert Figma logo to code with AI

rurban logosmhasher

Hash function quality and speed tests

1,806
174
1,806
40

Top Related Projects

8,937

Extremely fast non-cryptographic hash algorithm

Quick Overview

SMHasher is a test suite designed to test the quality of hash functions. It provides a comprehensive set of tests to evaluate various properties of hash functions, including distribution, avalanche effect, and collision resistance. The project is maintained by Reini Urban and is a fork of the original SMHasher by Austin Appleby.

Pros

  • Comprehensive test suite for evaluating hash functions
  • Supports a wide range of hash algorithms
  • Actively maintained and updated
  • Useful for both cryptographic and non-cryptographic hash functions

Cons

  • Complex setup and compilation process
  • Limited documentation for new users
  • Requires understanding of hash function properties to interpret results
  • Resource-intensive for running full test suite on multiple hash functions

Code Examples

// Example 1: Using SMHasher to test a custom hash function
#include "Platform.h"
#include "Hashes.h"
#include "KeysetTest.h"
#include "SpeedTest.h"
#include "AvalancheTest.h"

void CustomHash(const void * key, int len, uint32_t seed, void * out) {
    // Your custom hash implementation here
}

int main(int argc, char ** argv) {
    HashInfo hi;
    hi.hash = CustomHash;
    hi.name = "CustomHash";
    hi.hashbits = 32;
    hi.verification = 0;  // Set this to the expected verification value

    test_hash(&hi);
    return 0;
}
// Example 2: Running specific tests on a hash function
#include "Platform.h"
#include "Hashes.h"
#include "KeysetTest.h"

int main(int argc, char ** argv) {
    HashInfo hi;
    hi.hash = MurmurHash3_x86_32;
    hi.name = "MurmurHash3_x86_32";
    hi.hashbits = 32;

    bool result = TinyKeyTest(&hi, 100000);
    printf("TinyKeyTest result: %s\n", result ? "PASS" : "FAIL");

    return 0;
}
// Example 3: Comparing speed of multiple hash functions
#include "Platform.h"
#include "Hashes.h"
#include "SpeedTest.h"

int main(int argc, char ** argv) {
    HashInfo hi1, hi2;
    hi1.hash = MurmurHash3_x86_32;
    hi1.name = "MurmurHash3_x86_32";
    hi1.hashbits = 32;

    hi2.hash = FNV1a;
    hi2.name = "FNV1a";
    hi2.hashbits = 32;

    BulkSpeedTest(&hi1, 1024);
    BulkSpeedTest(&hi2, 1024);

    return 0;
}

Getting Started

  1. Clone the repository:

    git clone https://github.com/rurban/smhasher.git
    
  2. Build the project:

    cd smhasher
    cmake .
    make
    
  3. Run the test suite:

    ./SMHasher
    
  4. To test a specific hash function:

    ./SMHasher MurmurHash3_x86_32
    

Competitor Comparisons

8,937

Extremely fast non-cryptographic hash algorithm

Pros of xxHash

  • Faster performance, especially for short inputs
  • Simpler implementation, focusing on speed and efficiency
  • Actively maintained with regular updates and improvements

Cons of xxHash

  • Limited to non-cryptographic hash functions
  • Fewer hash algorithm implementations compared to SMHasher

Code Comparison

xxHash (XXH64 function):

XXH_FORCE_INLINE XXH64_hash_t
XXH64_round(XXH64_hash_t acc, XXH64_hash_t input)
{
    acc += input * PRIME64_2;
    acc  = XXH_rotl64(acc, 31);
    acc *= PRIME64_1;
    return acc;
}

SMHasher (MurmurHash3 function):

inline uint64_t fmix64 ( uint64_t k )
{
  k ^= k >> 33;
  k *= BIG_CONSTANT(0xff51afd7ed558ccd);
  k ^= k >> 33;
  k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
  k ^= k >> 33;
  return k;
}

Summary

xxHash focuses on speed and simplicity, making it ideal for non-cryptographic hashing tasks. SMHasher provides a broader range of hash algorithms and testing tools, making it more suitable for hash function analysis and comparison. Both projects have their strengths, with xxHash excelling in performance and SMHasher offering more comprehensive testing capabilities.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

SMhasher

Linux Build status Windows Build status FreeBSD Build status

Hash functionMiB/seccycl./hashcycl./mapsizeQuality problems
donothing3211149460.064.00-13bad seed 0, test NOP
donothing6411787676.424.00-13bad seed 0, test NOP
donothing12811745060.764.06-13bad seed 0, test NOP
NOP_OAAT_read6411372846.3714.00-47test NOP
BadHash769.9473.97-47bad seed 0, test FAIL
sumhash10699.5729.53-363bad seed 0, test FAIL
sumhash3242877.7923.12-863UB, test FAIL
multiply_shift8026.7726.05226.80 (8)345bad seeds & 0xfffffff0, fails most tests
pair_multiply_shift3716.9540.22186.34 (3)609fails most tests
--------------------------
crc32383.12134.21257.50 (11)422insecure, 8590x collisions, distrib, PerlinNoise
md5_32350.53644.31894.12 (10)4419
md5_64351.01656.67897.43 (12)4419
md5-128350.89681.88894.03 (13)4419
sha1_32353.031385.801759.94 (5)5126Sanity, Cyclic low32, 36.6% distrib
sha1_64353.031385.801759.94 (5)5126Sanity, Cyclic low32, 36.6% distrib
sha1-160364.951470.551794.16 (13)5126Comb/Cyclic low32
sha2-224147.131354.811589.92 (12)Comb low32
sha2-224_64147.601360.101620.93 (13)Cyclic low32
sha2-256147.801374.901606.06 (16)
sha2-256_64148.011376.341624.71 (16)
sha1ni1601.21174.16397.28 (6)989insecure,sanity, Permutation, Zeroes, machine-specific
sha1ni_321576.17174.04405.56 (6)989machine-specific
sha2ni-2561527.38184.35404.40 (4)4241insecure,sanity, Permutation, Zeroes, machine-specific
sha2ni-256_641501.85186.20407.96 (5)4241Zeroes, machine-specific
blake3_c1288.84357.69582.89 (6)no 32bit portability
rmd128290.90710.49965.55 (6)
rmd160202.161045.791287.74 (16)Cyclic hi32
rmd256364.81584.86835.02 (11)
edonr224864.69303.42526.94 (6)
edonr256847.85305.79510.01 (4)
blake2s-128295.30698.091059.24 (51)
blake2s-160215.011026.741239.54 (11)
blake2s-224207.061063.861236.50 (20)
blake2s-256215.281014.881230.38 (28)
blake2s-256_64211.521044.221228.43 (8)
blake2b-160356.081236.841458.15 (12)
blake2b-224356.591228.501425.87 (16)
blake2b-256355.971232.221443.31 (19)
blake2b-256_64356.971222.761435.03 (9)
asconhashv12144.98885.021324.23 (38)4341
asconhashv12_64159.68386.90480.86 (4)6490
sha3-256100.583877.184159.79 (37)PerlinNoise
sha3-256_64100.573909.004174.63 (16)PerlinNoise
hasshe22773.8964.35282.30 (3)445Permutation,TwoBytes,Zeroes,Seed
poly_1_mersenne1369.2161.59248.86 (4)479fails most tests
poly_2_mersenne1364.0370.30261.00 (6)479
poly_3_mersenne1342.8280.22268.79 (2)479
poly_4_mersenne1343.1989.13277.52 (3)479
tabulation325781.1640.00241.79 (10)848collisions
tabulation7875.0139.95249.49 (3)554
crc32_hw6244.3841.23226.80 (2)653insecure, 100% bias, collisions, distrib, BIC, machine-specific (SSE4.2/NEON)
crc32_hw17569.2949.07233.75 (3)671insecure, 100% bias, collisions, distrib, BIC, machine-specific (x86 SSE4.2)
crc64_hw6143.6240.48223.13 (2)652insecure, 100% bias, collisions, distrib, BIC, machine-specific (SSE4.2/NEON)
crc32_pclmul---insecure, 100% bias, collisions, distrib, BIC, machine-specific (x86 SSE4.2+PCLMUL)
o1hash11629440.5718.15199.35 (2)101insecure, no seed, zeros, fails all tests
fibonacci16878.3222.94803.18 (15)1692UB, zeros, fails all tests
FNV1a760.5273.83254.29 (5)204bad seed, zeros, fails all tests
FNV1A_Totenschiff6274.7826.23251.13 (2)270UB, zeros, fails all tests
FNV1A_Pippip_Yurii6172.1427.55244.80 (2)147UB, sanity, fails all tests
FNV1a_YT13486.4930.50237.43 (4)321bad seed, UB, fails all tests
FNV26171.6032.20208.59 (4)278fails all tests
FNV64774.3772.43201.15 (2)79fails all tests
FNV128390.14136.42289.00 (3)171fails all tests
k-hash322230.4253.05264.64 (3)808insecure, zeros, UB, bad seeds, fails all tests
k-hash642451.8848.66249.44 (2)609insecure, zeros, UB, bad seeds, fails all tests
fletcher215552.6120.61335.31 (3)248bad seed 0, UB, fails all tests
fletcher415556.9320.60358.60 (3)371bad seed 0, UB, fails all tests
bernstein1045.9758.31225.78 (3)41bad seed 0, fails all tests
sdbm784.8368.57222.68 (5)41bad seed 0, fails all tests
x17748.7574.13236.00 (10)7999.98% bias, fails all tests
libiberty628.6684.95225.07 (4)37insecure, 100% bias, fails all tests, bad seed
gcc611.6986.47231.51 (5)39insecure, 100% bias, fails all tests, bad seed
JenkinsOOAT627.64107.04252.79 (3)153bad seed 0, 53.5% bias, fails all tests
JenkinsOOAT_perl608.1094.17254.09 (4)65bad seed 0, 1.5-11.5% bias, 7.2x collisions, BIC, LongNeighbors
MicroOAAT701.3576.68251.01 (3)68100% bias, distrib, BIC
pearsonhash64434.17124.14230.79 (4)Avalanche, Seed, SSSE3 only. broken MSVC
pearsonhash128434.23121.34221.03 (7)Avalanche, Seed, SSSE3 only. broken MSVC
pearsonhash256444.08119.11229.75 (4)Avalanche, Seed, SSSE3 only. broken MSVC
VHASH_3213053.4065.84289.86 (3)1231sanity, Seed, MomentChi2
VHASH_6413465.5063.88286.38 (5)1231sanity, Seed, Sparse
farsh3227038.2366.88278.89 (5)944insecure: AppendedZeroes, collisions+bias, MomentChi2, LongNeighbors
farsh6413829.32112.46332.59 (3)944insecure: AppendedZeroes, collisions+bias, MomentChi2, LongNeighbors
farsh1286878.88233.35384.85 (3)944insecure: AppendedZeroes, collisions+bias, permut,combin,2bytes,zeroes,PerlinNoise
farsh2563467.37440.40593.57 (5)944insecure: AppendedZeroes, collisions+bias, permut,combin,2bytes,zeroes,PerlinNoise
jodyhash321794.3441.12235.12 (4)102bias, collisions, distr, BIC LongNeighbors
jodyhash644813.1040.72239.22 (6)118bias, collisions, distr, BIC, LongNeighbors
lookup32475.3539.65240.10 (3)341UB, 28% bias, collisions, 30% distr, BIC
superfast2058.2249.56254.12 (3)210UB, bad seed 0, 91% bias, 5273.01x collisions, 37% distr, BIC
MurmurOAAT506.66103.33236.89 (3)47bad seed 0, collisions, 99.998% distr., BIC, LongNeighbors
Crap83041.1437.25247.87 (4)342UB, 2.42% bias, collisions, 2% distrib
Murmur12027.8548.51253.34 (3)358UB, 1 bad seed, 511x collisions, Diff, BIC
Murmur23089.1841.22238.42 (4)358UB, 1 bad seed, 1.7% bias, 81x coll, 1.7% distrib, BIC
Murmur2A3087.9845.90238.54 (4)407UB, 1 bad seed, 12.7% bias, LongNeighbors
Murmur2B5919.3838.18215.96 (3)433UB, 1.8% bias, collisions, 3.4% distrib, BIC
Murmur2C3810.9849.09218.51 (3)444UB, 2^32 bad seeds, 91% bias, collisions, distr, BIC, LongNeighbors
Murmur3A2982.6749.08245.78 (4)351UB, 1 bad seed, Moment Chi2 69
PMurHash323005.8548.88242.38 (3)18621 bad seed, Moment Chi2 69
Murmur3C4833.1856.87250.47 (6)859UB, LongNeighbors, Text, DiffDist
mirhash32low6145.3936.95235.09 (4)1112UB, 4 bad seeds, Cyclic, LongNeighbors, machine-specific (32/64 differs)
PMPML_326639.6845.33257.45 (3)1084Avalanche >512, unseeded: Seed, BIC, MomentChi2, PerlinNoise
PMPML_649833.7750.00251.64 (6)1305unseeded: Seed, MomentChi2, BIC
xxHash325865.1749.20242.74 (3)738LongNeighbors, collisions with 4bit diff, MomentChi2 220
metrohash6414741.5639.44215.76 (2)624UB, LongNeighbors, BIC
metrohash64_114298.7740.31223.25 (4)624UB, LongNeighbors, BIC, MomentChi2
metrohash64crc_16929.6944.65223.68 (3)632UB, Cyclic 8/8 byte, DiffDist, BIC, MomentChi2, machine-specific (SSE4.2/NEON)
metrohash64crc_28150.6543.72219.45 (5)632UB, Cyclic 8/8 byte, DiffDist, BIC, machine-specific (SSE4.2/NEON)
cmetrohash64_1o14921.7338.95213.25 (2)3506UB, LongNeighbors, BIC, MomentChi2
cmetrohash64_114151.7340.90211.89 (2)652UB, LongNeighbors, BIC, MomentChi2
City64noSeed14209.1931.80225.90 (5)1038Avalanche, Sparse, TwoBytes, MomentChi2, Seed
City6413887.8446.32239.77 (3)1120Sparse, TwoBytes
t1ha1_64le13442.6431.41219.58 (3)517Avalanche
t1ha1_64be11586.0232.74232.55 (3)555Avalanche
t1ha0_32le7401.2148.27238.99 (3)509Sparse, LongNeighbors
t1ha0_32be6217.3750.66244.51 (3)533Sparse, LongNeighbors
t1ha2_stream14011.6380.72275.17 (3)1665Sparse, Permutation, LongNeighbors
t1ha2_stream12813136.0697.80306.11 (7)1665Sparse, Permutation, LongNeighbors
aesnihash5579.3256.83258.71 (5)1209fails many tests, machine-specific (x64 AES-NI)
falkhash50631.69123.02322.14 (7)264Sparse, LongNeighbors, machine-specific (x64 AES-NI)
MeowHash29969.4064.96274.29 (4)1764Sparse, invertible, machine-specific (x64 AES-NI)
MeowHash64low29485.5965.98278.05 (3)1764Sparse, invertible, machine-specific (x64 AES-NI)
MeowHash32low26944.5865.95292.79 (9)1764Sparse, invertible, machine-specific (x64 AES-NI)
--------------------------------------
tifuhash_6435.601679.521212.75 (15)276Cyclic low32
floppsyhash35.721868.921411.07 (7)623
beamsplitter789.22682.451150.33 (26)4203UB
discohash14131.12199.00398.35 (5)1294
discohash1-1284072.95234.17438.43 (5)1294
discohash23986.52207.52421.99 (2)1294
discohash2-1284094.73236.61433.35 (4)1294
discoNONG3698.45399.67597.78 (9)bad seeds
chaskey1143.05113.70294.43 (4)1609PerlinNoise
SipHash943.53147.15338.74 (4)1071
HalfSipHash1141.5779.65263.96 (3)700zeroes
GoodOAAT743.8185.62231.22 (3)237
pearsonbhash641794.8397.80268.90 (8)683
pearsonbhash1281691.62104.57272.38 (4)1134
pearsonbhash2561442.59126.04309.34 (4)844
prvhash64_64m3077.1847.31241.92 (3)349
prvhash64_643015.0848.03240.64 (3)384
prvhash64_1283353.8167.64266.32 (2)718
prvhash64s_646591.34273.50464.65 (3)2640
prvhash64s_1286581.40333.83528.07 (5)2799
SipHash131812.75106.56310.76 (5)7780.9% bias
TSip4233.1753.31249.19 (3)519!msvc
seahash8261.8058.94256.08 (4)871PerlinNoise, !msvc
seahash32low8266.1758.90290.21 (16)871PerlinNoise 32, !msvc
clhash18703.0470.19282.12 (6)1809PerlinNoise, machine-specific (x64 SSE4.2)
HighwayHash646242.5899.55248.41 (3)2546
Murmur3F7623.4452.69221.87 (3)699UB
MUM9563.9934.99228.55 (5)1912UB, too many bad seeds, machine-specific (32/64 differs)
MUMlow9261.8936.17247.66 (4)1912UB, 5 bad seeds
xmsx322039.1046.39249.30 (7)1922 bad seeds
mirhash6139.0737.02209.47 (3)1112UB, 2^36 bad seeds, LongNeighbors, machine-specific (32/64 differs)
mirhashstrict3549.0149.99224.91 (2)1112
mirhashstrict32low3441.3550.60247.19 (3)11121 bad seed, MomentChi2 9
fasthash326128.2840.30241.64 (4)566UB
fasthash645818.9238.70220.74 (2)509UB
aesni31232.3429.21230.14 (4)519machine-specific (x64 AES-NI)
aesni-low31221.1429.64226.18 (3)519machine-specific (x64 AES-NI)
mx39034.9048.71227.89 (2)734UB
pengyhash13428.8074.24275.42 (5)421
City325551.2854.40261.64 (2)1319
City64low13904.1046.24260.08 (3)1120
City12814031.9689.09290.05 (10)1841
CityCrc1287916.4455.50240.79 (2)295
FarmHash3221755.5847.54258.35 (3)11489machine-specific (x64 SSE4/AVX)
FarmHash6412845.5347.11251.58 (3)3758
FarmHash12813913.6570.25263.06 (3)163
farmhash32_c21601.8647.38273.00 (3)762machine-specific (x64 SSE4/AVX)
farmhash64_c12834.1047.23246.20 (2)3688
farmhash128_c13753.2468.96263.76 (3)1890
metrohash64_214316.3740.23218.28 (3)627UB, LongNeighbors
cmetrohash64_214294.2640.76221.40 (4)655LongNeighbors
metrohash12815634.6673.28261.23 (4)773UB, LongNeighbors
metrohash128_115806.9772.30260.90 (4)773UB, LongNeighbors
metrohash128_215822.6072.30255.34 (3)773UB, LongNeighbors
metrohash128crc_18009.2378.72281.55 (13)723UB, machine-specific (SSE4.2/NEON)
metrohash128crc_27878.2279.90275.22 (4)723UB, machine-specific (SSE4.2/NEON)
xxHash6412108.8749.78228.83 (2)1999
Spooky3213108.9556.27255.36 (3)2221UB
Spooky6413529.3658.76236.31 (3)2221UB
Spooky12811781.3558.91242.91 (3)2221UB
SpookyV2_3213529.1655.55248.37 (4)2069
SpookyV2_6412678.8256.71243.21 (4)2069
SpookyV2_12813512.8258.33244.56 (5)2069
ahash649862.6227.32181.68 (1)412rust
xxh321033.5529.48226.77 (4)744DiffDist bit 7 w. 36 bits, BIC
xxh3low17093.1930.57242.07 (7)756
xxh12818802.1632.37234.30 (4)1012
xxh128low18833.0532.30234.68 (3)1012
t1ha2_atonce13854.4437.92233.54 (2)541Zeroes low3
t1ha2_atonce12814148.4255.70253.74 (6)613LongNeighbors
t1ha0_aes_noavx27231.5937.70236.10 (3)925LongNeighbors, machine-specific (x86 AES-NI)
t1ha0_aes_avx122714.8548.12226.52 (16)843LongNeighbors, machine-specific (x64 AVX.txt)
t1ha0_aes_avx256919.4636.70233.14 (2)792LongNeighbors, machine-specific (x64 AVX2)
wyhash322532.8948.40484.57 (1)4264 bad and broken seeds, 32-bit
wyhash32low22393.7729.04243.40 (3)4745 bad seeds
wyhash22540.2328.87236.16 (8)474
rapidhash23789.7922.80138.71 (7)574
rapidhash_unrolled23892.8823.41139.47 (12)782
umash3221427.5742.12255.55 (5)1530
umash32_hi21483.1242.65251.09 (4)1530
umash6421690.0841.67238.01 (4)1530
umash12813211.8843.37237.40 (3)1530
halftime_hash644735.6399.90315.34 (3)2911
halftime_hash12817534.5397.97311.10 (4)2462
halftime_hash25618003.3999.46315.09 (3)2622
halftime_hash51210890.15118.05333.45 (3)3550
nmhash3212969.6255.88265.69 (4)2445
nmhash32x12775.0842.66246.05 (3)1494
k-hashv329181.8752.76245.14 (3)1280
k-hashv647850.9246.94193.94 (1)1279
komihash12242.7833.02236.07 (2)1323
polymur9676.3342.70246.53 (3)1128

The sortable table variants:

Summary

I added some SSE assisted hashes and fast intel/arm CRC32-C, AES and SHA HW variants. See also the old https://github.com/aappleby/smhasher/wiki, the improved, but unmaintained fork https://github.com/demerphq/smhasher, and the new improved version SMHasher3 https://gitlab.com/fwojcik/smhasher3.

So the fastest hash functions on x86_64 without quality problems are:

  • rapidhash (an improved wyhash)
  • xxh3low
  • wyhash
  • umash (even universal!)
  • ahash64
  • t1ha2_atonce
  • komihash
  • FarmHash (not portable, too machine specific: 64 vs 32bit, old gcc, ...)
  • halftime_hash128
  • Spooky32
  • pengyhash
  • nmhash32
  • mx3
  • MUM/mir (different results on 32/64-bit archs, lots of bad seeds to filter out)
  • fasthash32

Hash functions for symbol tables or hash tables typically use 32 bit hashes, for databases, file systems and file checksums typically 64 or 128bit, for crypto now starting with 256 bit.

Typical median key size in perl5 is 20, the most common 4. Similar for all other dynamic languages. See github.com/rurban/perl-hash-stats

When used in a hash table the instruction cache will usually beat the CPU and throughput measured here. In my tests the smallest FNV1A beats the fastest crc32_hw1 with Perl 5 hash tables. Even if those worse hash functions will lead to more collisions, the overall speed advantage and inline-ability beats the slightly worse quality. See e.g. A Seven-Dimensional Analysis of Hashing Methods and its Implications on Query Processing for a concise overview of the best hash table strategies, confirming that the simplest Mult hashing (bernstein, FNV*, x17, sdbm) always beat "better" hash functions (Tabulation, Murmur, Farm, ...) when used in a hash table.

The fast hash functions tested here are recommendable as fast for file digests and maybe bigger databases, but not for 32bit hash tables. The "Quality problems" lead to less uniform distribution, i.e. more collisions and worse performance, but are rarely related to real security attacks, just the 2nd sanity AppendZeroes test against \0 invariance is security relevant.

Columns

MiB/sec: The average of the Bulk key speed test for alignments 0-7 with 262144-byte keys. The higher the better.

cycl./hash: The average of the Small key speed test for 1-31 byte keys. The smaller the better.

cycl./map: The result of the Hashmap test for /usr/dict/words with fast C++ hashmap get queries, with the standard deviation in brackets. This tests the inlinability of the hash function in practise (see size). The smaller the better.

size: The object size in byte on AMD64. This affects the inlinability in e.g. hash tables. The smaller the better.

Quality problems: See the failures in the linked doc. The less the better.

Other

SECURITY

The hash table attacks described in SipHash against City, Murmur or Perl JenkinsOAAT or at Hash Function Lounge are not included here. We list some known attacks at GH #186.

Such an attack avoidance cannot be the problem of the hash function, but only the hash table collision resolution scheme. You can attack every single hash function, even the best and most secure if you detect the seed, e.g. from language (mis-)features, side-channel attacks, collision timings and independly the sort-order, so you need to protect your collision handling scheme from the worst-case O(n), i.e. separate chaining with linked lists. Linked lists chaining allows high load factors, but is very cache-unfriendly. The only recommendable linked list scheme is inlining the key or hash into the array. Nowadays everybody uses fast open addressing, even if the load factor needs to be ~50%, unless you use Cuckoo Hashing.

I.e. the usage of SipHash for their hash table in Python 3.4, ruby, rust, systemd, OpenDNS, Haskell and OpenBSD is pure security theatre. SipHash is not secure enough for security purposes and not fast enough for general usage. Brute-force generation of ~32k collisions need 2-4m for all these hashes. siphash being the slowest needs max 4m, other typically max 2m30s, with <10s for practical 16k collision attacks with all hash functions. Using Murmur is usually slower than a simple Mult, even in the worst case. Provable secure is only uniform hashing, i.e. 2-5 independent Mult or Tabulation, or using a guaranteed logarithmic collision scheme (a tree) or a linear collision scheme, such as swisstable/folly-F14, Robin Hood or Cuckoo hashing with collision counting.

One more note regarding security: Nowadays even SHA1 can be solved in a solver, like Z3 (or faster ones) for practical hash table collision attacks (i.e. 14-20 bits). All hash functions with less than 160 bits tested here cannot be considered "secure" at all.

The '\0' vulnerability attack with binary keys is tested in the 2nd Sanity Zero test.

CRYPTO

Our crypto hashes are hardened with an added size_t seed, mixed into the initial state, and the versions which require zero-padding are hardened by adding the len also, to prevent from collisions with AppendedZeroes for the padding. The libtomcrypt implementations already provide for that, but others might not. Without, such crypto hash functions are unsuitable for normal tasks, as it's trivial to create collisions by padding or bad seeds.

The official NIST hash function testsuite does not do such extensive statistical tests, to search for weak ranges in the bits. Also crypto does not change the initial state, which we do here for our random 32bit seed. Crypto mostly cares about unreversable key -> hash functions without changing the initial fixed state and timings/sidechannel attacks.

The NIST "Cryptographic Algorithm Validation Program" (CAVP) involves the testing of the implementations of FIPS-approved and NIST-recommended cryptographic algorithms. During the NIST SHA-3 competition, the testing methodology was borrowed from the "CAVP", as the KATs and MCTs of the SHA-3 Competition Test Suite were based on the CAVP tests for SHA-2. In addition to this, the “Extremely Long Message Test,” not present in the CAVP for SHA-2, required the submitters to generate the hash value corresponding to a message with a length of 1 GiB. “NIST - Cryptographic Algorithm Validation Program (CAVP),” June 2017. Available: http://csrc.nist.gov/groups/STM/cavp (No testing source code provided, just high-level descriptions)

Two other independent third party testsuites found an extensive number of bugs and weaknesses in the SHA3 candidates. "Finding Bugs in Cryptographic Hash Function Implementations", Nicky Mouha, Mohammad S Raunak, D. Richard Kuhn, and Raghu Kacker, 2017. https://eprint.iacr.org/2017/891.pdf

Maybe independent researchers should come together to do a better public SHA-4 round, based on better and more testing methods, open source code for the tests, and using standard industry practices, such as valgrind, address-sanitizer and ubsan to detect obvious bugs.

PROBLEMS

  • Bad Seeds

    Hash functions are typically initialized with a random seed. But some seed values may lead to bad hash functions, regardless of the key. In the regular case with random seeds the probablity of such bad seeds is very low, like 2^32 or 2^64. A practical application needs to know if bad seeds exist and choose another one. See e.g. mirhash_seed_init() and mirhash_bad_seeds() in Hashes.h. Note that a bad seed is not really a problem when you skip this seed during initialization. It can still be a GOOD or recommended hash function. But a bad seed of 0 leading to collisions is considered a bug, a bad hash function.

    We test for internal secrets, if they will be multiplied with 0. This is also called "blinding multiplication". main.cpp lists some secrets for each hash function we test against. The function <hash>_bad_seeds() lists the confirmed bad seeds.

    Special care needs to be taken for crc, most FNV1 variants, fletcher, Jenkins. And with GOOD hashes most MUM variants, like mirhash, MUM, wyhash.

    Independently from this, when the attacker knows the seed it will lead to DDOS attacks. Even with crypto hashes in power2 hashtables.

Typical undefined behaviour (UB) problems:

  • Misaligned

    Many word-wise hashes (in opposite to safe byte-wise processing) don't check the input buffer for proper word alignment, which will fail with ubsan or Sparc. word being int32_t or int64_t or even more. On some old RISC hardware this will be a BUS error, you can even let Intel HW generate such a bus error by setting some CPU flag. But generally using misaligned accesses is fine.

    These are: mx3, Spooky, mirhash (but not strict), MUM, fasthash, Murmur3*, Murmur2*, metrohash* (all but cmetro*), Crap8, beamsplitter, lookup3, fletcher4, fletcher2, all sanmayce FNV1a_ variants (FNV1a_YT, FNV1A_Pippip_Yurii, FNV1A_Totenschiff, ...), fibonacci.

    The usual mitigation is to check the buffer alignment either in the caller, provide a pre-processing loop for the misaligned prefix, or copy the whole buffer into a fresh aligned area. Put that extra code inside #ifdef HAVE_ALIGNED_ACCESS_REQUIRED.

  • oob - Out of bounds

    Some hash function assume a padded input buffer which can be accessed past its length up to the word size. This allows for faster loop processing, as no 2nd loop or switch table for the rest is needed, but it requires a cooperative calling enviroment and is as such considered cheating.

  • Signed integer overflow

    A simple type error, this hash needs to use unsigned integer types internally, to avoid undefined and inconsistent behaviour. i.e. SuperFastHash: signed integer overflow: -2147483641 + -113 cannot be represented in type 'int'

  • shift exponent overflow

    With: FNV1A_Pippip_Yurii, FNV1A_Totenschiff, pair_multiply_shift, sumhash32 shift exponent 64 is too large for 64-bit type 'long unsigned int'