T1ha
Fast Positive Hash - just the fastest portable hash function.
Install / Use
/learn @PositiveTechnologies/T1haREADME
t1ha
Fast Positive Hash, aka "Позитивный Хэш" by Positive Technologies. Included in the Awesome C list of open source C software.
The Future will (be) Positive. Всё будет хорошо.
Briefly, it is a portable non-cryptographic 64-bit hash function:
-
Intended for 64-bit little-endian platforms, predominantly for Elbrus and x86_64, but portable and without penalties it can run on any 64-bit CPU.
-
In most cases up to 15% faster than xxHash, StadtX, MUM and others portable hash-functions (which do not use specific hardware tricks).
Currently wyhash outperforms t1ha on
x86_64. However next versiont1ha3_atonce()will be even faster on all platforms, especially on E2K, architectures with SIMD and most RISC-V implementations. In addition, it should be noted that wyhash have a "blinding multiplication" flaw and can lose entropy (similarly as described below). For instance, when data could be correlated with theseed ^ _wypNvalues or equal to it. Another case is where one of_wymum()multipliers becomes zero. In result of such blinding all previous data will not be influence to the hash value. -
Licensed under zlib License.
Also pay attention to Rust, Erlang and Golang implementations.
FAQ: Why t1ha don't follow NH-approach like FARSH, XXH3, HighwayHash and so on?
Okay, just for clarity, we should distinguish functions families: MMH (Multilinear-Modular-Hashing), NMH (Non-linear Modular-Hashing) and the next simplification step UMAC's NH.
Now take a look to NH hash-function family definition:
It is very SIMD-friendly, since SSE2's _mm_add_epi32() and
_mm_mul_epu32() is enough for .
On the other hand, the result of the inner multiplication becomes zero
when (m[2i] + k[2i]) mod 2^32 == 0 or (m[2i+1] + k[2i+1]) mod
2^32 == 0, in which case the opposite multiplier will not affect the
result of hashing, i.e. NH function just ignores part of the input data.
I called this an "blinding multiplication". That's all.
More useful related information can be googled by "UMAC NH key
recovery
attack".
The right NMH/NH code without entropy loss should be looking like this:
uint64_t proper_NH_block(const uint32_t *M /* message data */,
const uint64_t *K /* 64-bit primes */,
size_t N_even, uint64_t optional_weak_seed) {
uint64_t H = optional_weak_seed;
for (size_t i = 0; i < N_even / 2; ++i)
H += (uint64_t(M[i*2]) + K[i*2]) * (uint64_t(M[i*2+1]) + K[i*2+1]);
return H;
}
Usage
The t1ha library provides several terraced hash functions
with the dissimilar properties and for a different cases.
These functions briefly described below, see t1ha.h for more API details.
To use in your own project you may link with the t1ha-library,
or just add to your project corresponding source files from /src directory.
Please, feel free to fill an issue or make pull request.
t1ha0 = 64 bits, "Just Only Faster"
Provides fast-as-possible hashing for current CPU, including 32-bit systems and engaging the available hardware acceleration. You can rest assured that t1ha0 faster than all other fast hashes (with comparable quality) so, otherwise we will extend and refine it time-to-time.
On the other hand, without warranty that the hash result will be same for particular key on another machine or another version. Moreover, is deliberately known that the result will be different for systems with different bitness or endianness. Briefly, such hash-results and their derivatives, should be used only in runtime, but should not be persist or transferred over a network.
Also should be noted, the quality of t1ha0() hashing is a subject
for tradeoffs with performance. Therefore the quality and strength
of t1ha0() may be lower than t1ha1() and t1ha2(),
especially on 32-bit targets, but then much faster.
However, guaranteed that it passes all SMHasher tests.
Internally t1ha0() selects most faster implementation for current CPU,
for now these are includes:
| Implementation | Platform/CPU |
| :---------------------- | :------------------------------------- |
| t1ha0_ia32aes_avx() | x86 with AES-NI and AVX extensions |
| t1ha0_ia32aes_avx2() | x86 with AES-NI and AVX2 extensions |
| t1ha0_ia32aes_noavx() | x86 with AES-NI without AVX extensions |
| t1ha0_32le() | 32-bit little-endian |
| t1h0a_32be() | 32-bit big-endian |
| t1ha1_le() | 64-bit little-endian |
| t1ha1_be() | 64-bit big-endian |
| t1ha2_atonce() | 64-bit little-endian |
t1ha1 = 64 bits, baseline fast portable hash
The first version of "Fast Positive Hash" with reasonable quality for checksum, hash tables and thin fingerprinting. It is stable, e.g. returns same result on all architectures and CPUs.
- Speed with the reasonable quality of hashing.
- Efficiency on modern 64-bit CPUs, but not in a hardware.
- Strong as possible, until no penalties on performance.
Unfortunatelly, Yves Orton discovered
that t1ha1() family fails the strict avalanche criteria in some cases.
This flaw is insignificant for the t1ha1() purposes and imperceptible
from a practical point of view.
However, nowadays this issue has resolved in the next t1ha2() function,
that was initially planned to providing a bit more quality.
The basic version of t1ha1() intends for little-endian systems and will run
slowly on big-endian. Therefore a dedicated big-endian version is also
provided, but returns the different result than the basic version.
t1ha2 = 64 and 128 bits, slightly more attention for quality and strength
The recommended version of "Fast Positive Hash" with good quality for checksum, hash tables and fingerprinting. It is stable, e.g. returns same result on all architectures and CPUs.
- Portable and extremely efficiency on modern 64-bit CPUs.
- Great quality of hashing and still faster than other non-t1ha hashes.
- Provides streaming mode and 128-bit result.
The t1ha2() is intended for little-endian systems and will run
slightly slowly on big-endian systems.
t1ha3 = 128 and 256 bits, fast non-cryptographic fingerprinting
The next-step version of "Fast Positive Hash", but not yet finished and therefore not available.
Planned: t1ha4 = 128 and 256 bits, fast insecure fingerprinting
Planned: t1ha5 = 256 bits, fast Cryptographic, but with some limitations
Planned: t1ha6 = 256 and 512 bits, Cryptographic with reasonable resistance to acceleration on GPU and FPGA.
Planned: t1ha7 = 256, 512 and 1024 bits, Cryptographic, Strong Post-Quantum
Requirements and Portability:
- t1ha designed for modern 64-bit architectures.
But on the other hand, t1ha doesn't require
instructions specific to a particular architecture:
- therefore t1ha could be used on any CPU for which compiler provides support 64-bit arithmetic.
- but unfortunately t1ha could be dramatically slowly on architectures without native 64-bit operations.
- This implementation of t1ha requires modern GNU C compatible compiler, including Clang/LLVM, or Visual Studio 2013/2015/2017. For proper performance please use one of: GNU C 5.5 or later, CLANG 5.0 or later, Microsoft Visual Studio 2017 15
