/*++ /* NAME /* hash_fnv 3 /* SUMMARY /* Fowler/Noll/Vo hash function /* SYNOPSIS /* #include /* /* HASH_FNV_T hash_fnv( /* const void *src, /* size_t len) /* DESCRIPTION /* hash_fnv() implements a modified FNV type 1a hash function. /* /* To thwart collision attacks, the hash function is seeded /* once from /dev/urandom, and if that is unavailable, from /* wallclock time, monotonic system clocks, and the process /* ID. To disable seeding (typically, for regression tests), /* specify the NORANDOMIZE environment variable; the value /* does not matter. /* /* This function implements a workaround for a "sticky state" /* problem with FNV hash functions: when an input produces a /* zero intermediate hash state, and the next input byte is /* zero, then the operations "hash ^= 0" and "hash *= FNV_prime" /* would not change the hash value. To avoid this, hash_fnv() /* adds 1 to each input byte. Compile with -DSTRICT_FNV1A to /* get the standard behavior. /* /* The default HASH_FNV_T result type is uint64_t. When compiled /* with -DUSE_FNV_32BIT, the result type is uint32_t. On ancient /* systems without , define HASH_FNV_T on the compiler /* command line as an unsigned 32-bit or 64-bit integer type, /* and specify -DUSE_FNV_32BIT when HASH_FNV_T is a 32-bit type. /* SEE ALSO /* http://www.isthe.com/chongo/tech/comp/fnv/index.html /* https://softwareengineering.stackexchange.com/questions/49550/ /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA /*--*/ /* * System library */ #include #include #include /* * Utility library. */ #include #include #include /* * Application-specific. */ #ifdef USE_FNV_32BIT #define FNV_prime 0x01000193UL #define FNV_offset_basis 0x811c9dc5UL #else #define FNV_prime 0x00000100000001B3ULL #define FNV_offset_basis 0xcbf29ce484222325ULL #endif /* hash_fnv - modified FNV 1a hash */ HASH_FNV_T hash_fnv(const void *src, size_t len) { static HASH_FNV_T basis = FNV_offset_basis; static int randomize = 1; HASH_FNV_T hash; /* * Initialize. */ if (randomize) { if (!getenv("NORANDOMIZE")) { HASH_FNV_T seed; ldseed(&seed, sizeof(seed)); basis ^= seed; } randomize = 0; } #ifdef STRICT_FNV1A #define FNV_NEXT_BYTE(s) ((HASH_FNV_T) * (const unsigned char *) s++) #else #define FNV_NEXT_BYTE(s) (1 + (HASH_FNV_T) * (const unsigned char *) s++) #endif hash = basis; while (len-- > 0) { hash ^= FNV_NEXT_BYTE(src); hash *= FNV_prime; } return (hash); }