MurmurHash
MurmurHash — це проста і швидка некриптографічна хеш-функція, яка підходить для загального пошуку на основі хешування. [1] [2] [3] Вона був створений Остіном Епплбі в 2008 році [4] і зараз розміщена на GitHub разом із набором тестів під назвою «SMHasher». Вона існує в декількох варіантах [5], усі з яких опубліковані у відкритому доступі. Назва походить від двох основних операцій, множення (MU-ltiply) і повороту (R-otate), які використовуються у її внутрішньому циклі.
На відміну від криптографічних хеш-функцій, вона не розроблена спеціально для того, щоб її було важко відмінити зловмисником, що робить її непридатною для криптографічних цілей.
Із переваг функції автори виділяють простоту, хороший розподіл, хороший лавиновий ефект, висока швидкість и доволі висока стійкість до колізій.
Поточна версія — MurmurHash3 [6] [7], яка повертає 32- або 128-бітове хеш-значення. При використанні 128-бітів версії x86 і x64 не видають однакові значення, оскільки алгоритми оптимізовано для відповідних платформ. MurmurHash3 було випущено разом із SMHasher — пакетом для тестування хеш-функцій.
MurmurHash2 [8] видає 32- або 64-бітне значення. Він випускався в кількох варіантах, включаючи такі, які дозволяють використовувати інкрементальне хешування.
- MurmurHash2 (32-розрядний, x86) - Оригінальна версія; містить недолік, який у деяких випадках призводить до більшої частоти колізій. [9]
- MurmurHash2A (32-розрядний, x86) – фіксований варіант із використанням конструкції Меркла–Дамгорда . Трохи повільніший.
- CMurmurHash2A (32-розрядний, x86) - MurmurHash2A, але працює інкрементально.
- MurmurHashNeutral2 (32-розрядний, x86) - повільніше, але endian і нейтральний до вирівнювання.
- MurmurHashAligned2 (32-розрядний, x86) — повільніше, але виконує вирівняне читання (що безпечніше на деяких платформах).
- MurmurHash64A (64-розрядна, x64) - оригінальна 64-bit версія. Оптимізована для 64-розрядної арифметики.
- MurmurHash64B (64-розрядна, x86) - 64-розрядна версія, оптимізована для 32-розрядних платформ. Це не справжній 64-бітний хеш через недостатнє змішування смуг. [10]
Оригінальний MurmurHash був створений як спроба створити швидшу функцію, ніж Lookup3 . [11] Незважаючи на успіх, він не був ретельно протестований і не міг забезпечити створення 64-розрядних хешів, як у Lookup3. Вона мала досить елегантний дизайн, який пізніше буде перенесений на MurmurHash2, поєднуючи мультиплікативний хеш (схожий на хеш-функцію Фаулера–Нолла–Во ) та Xorshift .
Канонічна реалізація в C++, але функція була портована для багатьох популярних мов, включаючи Python, [12] C, [13] Go, [14] C#, [7] [15] D, [16] Lua, Perl, [17] Ruby, [18] Rust, [19] PHP, [20] [21] Common Lisp, [22] Haskell, [13] Elm, [23] [24] Clojure, [ [25] Scala, [26] Java, [27] [28] Erlang, [29] Swift, [30] Object Pascal, [31] Kotlin, [32] і JavaScript . [33]
Вона використовується у ряді проектів з відкритим вихідним кодом, зокрема libstdc++ (версія 4.6), nginx (версія 1.0.1), [34] Rubinius, [35] libmemcached (драйвер C для Memcached ), [36] npm (менеджер пакетів nodejs), [37] maatkit, [38] Hadoop, [1] Kyoto Cabinet, [39] Cassandra, [40] [41] Solr, [42] vowpal wabbit, [43] Elasticsearch, [44] Guava, [45] Kafka [46] і RedHat Virtual Data Optimizer (VDO) . [47]
Хеш-функції можуть бути вразливими до колізійних атак, коли користувач може вибрати вхідні дані таким чином, щоб навмисно спричинити хеш-колізії. Жан-Філіп Омассон і Деніел Дж. Бернштейн змогли показати, що навіть реалізації MurmurHash із використанням рандомізованого початкового числа вразливі до так званих атак HashDoS. [48] За допомогою диференціального криптоаналізу вони змогли згенерувати вхідні дані, які призвели б до хеш-колізії. Автори атаки рекомендують замість цього використовувати власну функцію SipHash .
є алгоритм Murmur3_32
// Примітка: у цій версії вся арифметика виконується з 32-розрядними беззнаковими цілими числами.
// У разі переповнення результат обрізається за модулем 232 .
input: key, len, seed
c1 ← 0xcc9e2d51
c2 ← 0x1b873593
r1 ← 15
r2 ← 13
м ← 5
n ← 0xe6546b64
hash← seed
for each fourByteChunk of key do
k ← fourByteChunk k ← k × c1 k ← k ROL r1 k ← k × c2 hash ← hash XOR k hash ← hash ROL r2 hash ← (hash × m) + n with any remainingBytesInKey do remainingBytes ← SwapToLittleEndian(remainingBytesInKey) // Примітка: зміна порядку байтів необхідна лише на машинах з непрямим порядком байтів (big-endian). remainingBytes ← remainingBytes × c1 remainingBytes ← remainingBytes ROL r1 remainingBytes ← remainingBytes × c2 hash ← hash XOR remainingBytes hash ← hash XOR len hash ← hash XOR (hash >> 16) hash ← hash × 0x85ebca6b hash ← hash XOR (hash >> 13) hash ← hash × 0xc2b2ae35 hash ← hash XOR (hash >> 16)
Нижче наведено зразок реалізації C (для ЦП з прямим порядком байтів):
static inline uint32_t murmur_32_scramble(uint32_t k) {
k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17);
k *= 0x1b873593;
return k;
}
uint32_t murmur3_32(const uint8_t* key, size_t len, uint32_t seed)
{
uint32_t h = seed;
uint32_t k;
/* Read in groups of 4. */
for (size_t i = len >> 2; i; i--) {
// Here is a source of differing results across endiannesses.
// A swap here has no effects on hash properties though.
memcpy(&k, key, sizeof(uint32_t));
key += sizeof(uint32_t);
h ^= murmur_32_scramble(k);
h = (h << 13) | (h >> 19);
h = h * 5 + 0xe6546b64;
}
/* Read the rest. */
k = 0;
for (size_t i = len & 3; i; i--) {
k <<= 8;
k |= key[i - 1];
}
// A swap is *not* necessary here because the preceding loop already
// places the low bytes in the low places according to whatever endianness
// we use. Swaps only apply when the memory is copied in a chunk.
h ^= murmur_32_scramble(k);
/* Finalize. */
h ^= len;
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
- Некриптографічні хеш-функції
- ↑ а б Hadoop in Java. Hbase.apache.org. 24 липня 2011. Архів оригіналу за 12 січня 2012. Процитовано 13 січня 2012. [Архівовано 2012-01-12 у Wayback Machine.]
- ↑ Chouza et al [Архівовано 2022-03-31 у Wayback Machine.].
- ↑ Couceiro et al (PDF) (порт.). с. 14. Процитовано 13 січня 2012.
- ↑ Tanjent (tanjent) wrote,3 March 2008 13:31:00. MurmurHash first announcement. Tanjent.livejournal.com. Процитовано 13 січня 2012.
- ↑ MurmurHash2-160. Simonhf.wordpress.com. 25 вересня 2010. Процитовано 13 січня 2012.
- ↑ MurmurHash3 on Github.
- ↑ а б Horvath, Adam (10 серпня 2012). MurMurHash3, an ultra fast hash algorithm for C# / .NET.
- ↑ MurmurHash2 on Github.
- ↑ MurmurHash2Flaw. Процитовано 15 січня 2019.
- ↑ MurmurHash3 (see note on MurmurHash2_x86_64). Процитовано 15 січня 2019.
- ↑ MurmurHash1. Процитовано 12 січня 2019.
- ↑ pyfasthash in Python. Процитовано 13 січня 2012.
- ↑ C implementation in qLibc by Seungyoung Kim.
- ↑ murmur3 in Go.
- ↑ Landman, Davy. Davy Landman in C#. Landman-code.blogspot.com. Процитовано 13 січня 2012.
- ↑ std.digest.murmurhash - D Programming Language. dlang.org. Процитовано 5 листопада 2016.
- ↑ Toru Maesaka in Perl. metacpan.org. Процитовано 13 січня 2012.
- ↑ Yuki Kurihara (16 жовтня 2014). Digest::MurmurHash. GitHub.com. Процитовано 18 березня 2015.
- ↑ stusmall/murmur3. GitHub. Процитовано 29 листопада 2015.
- ↑ PHP userland implementation of MurmurHash3. github.com. Процитовано 18 грудня 2017.
- ↑ PHP 8.1 with MurmurHash3 support.
- ↑ tarballs_are_good / murmurhash3. Процитовано 7 лютого 2015.
- ↑ Haskell. Hackage.haskell.org. Процитовано 13 січня 2012.
- ↑ Elm. package.elm-lang.org. Процитовано 12 червня 2019.
- ↑ Murmur3.java in Clojure source code on Github. clojure.org. Процитовано 11 березня 2014.
- ↑ Scala standard library implementation. 26 вересня 2014.
- ↑ Murmur3, part of Guava
- ↑ Murmur3A and Murmur3F Java classes on Github. greenrobot. Процитовано 5 листопада 2014.
- ↑ bipthelin/murmerl3. GitHub. Процитовано 21 жовтня 2015.
- ↑ Daisuke T (7 лютого 2019). MurmurHash-Swift. GitHub.com. Процитовано 10 лютого 2019.
- ↑ GitHub - Xor-el/HashLib4Pascal: Hashing for Modern Object Pascal
- ↑ goncalossilva/kotlinx-murmurhash. GitHub.com. 10 грудня 2021. Процитовано 14 грудня 2021.
- ↑ raycmorgan (owner). Javascript implementation by Ray Morgan. Gist.github.com. Процитовано 13 січня 2012.
- ↑ nginx. Процитовано 13 січня 2012.
- ↑ Rubinius. Процитовано 29 лютого 2012.
- ↑ libMemcached. libmemcached.org. Процитовано 21 жовтня 2015.
- ↑ switch from MD5 to murmur.
- ↑ maatkit. 24 березня 2009. Процитовано 13 січня 2012.
- ↑ Kyoto Cabinet specification. Fallabs.com. 4 березня 2011. Архів оригіналу за 28 грудня 2018. Процитовано 13 січня 2012. [Архівовано 2018-12-28 у Wayback Machine.]
- ↑ Partitioners. apache.org. 15 листопада 2013. Архів оригіналу за 18 грудня 2013. Процитовано 19 грудня 2013. [Архівовано 2013-12-18 у Wayback Machine.]
- ↑ Introduction to Apache Cassandra™ + What’s New in 4.0 by Patrick McFadin. DataStax Presents. YouTube. 10 квітня 2019.
- ↑ Solr MurmurHash2 Javadoc. Архів оригіналу за 24 червня 2022. Процитовано 4 березня 2023.
- ↑ hash.cc in vowpalwabbit source code.
- ↑ Elasticsearch 2.0 - CRUD and routing changes.
- ↑ Guava Hashing.java.
- ↑ Kafka DefaultPartitioner.java.
- ↑ Virtual Data Optimizer source code
- ↑ Breaking Murmur: Hash-flooding DoS Reloaded.