MurmurHash

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

MurmurHash — це проста і швидка некриптографічна хеш-функція, яка підходить для загального пошуку на основі хешування. [1] [2] [3] Вона був створений Остіном Епплбі в 2008 році [4] і зараз розміщена на GitHub разом із набором тестів під назвою «SMHasher». Вона існує в декількох варіантах [5], усі з яких опубліковані у відкритому доступі. Назва походить від двох основних операцій, множення (MU-ltiply) і повороту (R-otate), які використовуються у її внутрішньому циклі.

На відміну від криптографічних хеш-функцій, вона не розроблена спеціально для того, щоб її було важко відмінити зловмисником, що робить її непридатною для криптографічних цілей.


Із переваг функції автори виділяють простоту, хороший розподіл, хороший лавиновий ефект, висока швидкість и доволі висока стійкість до колізій.

Варіанти[ред. | ред. код]

MurmurHash3[ред. | ред. код]

Поточна версія — MurmurHash3 [6] [7], яка повертає 32- або 128-бітове хеш-значення. При використанні 128-бітів версії x86 і x64 не видають однакові значення, оскільки алгоритми оптимізовано для відповідних платформ. MurmurHash3 було випущено разом із SMHasher — пакетом для тестування хеш-функцій.

MurmurHash2[ред. | ред. код]

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]

MurmurHash1[ред. | ред. код]

Оригінальний 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;
}

Дивись також[ред. | ред. код]

  • Некриптографічні хеш-функції

Посилання[ред. | ред. код]

  1. а б Hadoop in Java. Hbase.apache.org. 24 липня 2011. Архів оригіналу за 12 січня 2012. Процитовано 13 січня 2012.
  2. Chouza et al [Архівовано 2022-03-31 у Wayback Machine.].
  3. Couceiro et al (PDF) (порт.). с. 14. Процитовано 13 січня 2012.
  4. Tanjent (tanjent) wrote,3 March 2008 13:31:00. MurmurHash first announcement. Tanjent.livejournal.com. Процитовано 13 січня 2012.
  5. MurmurHash2-160. Simonhf.wordpress.com. 25 вересня 2010. Процитовано 13 січня 2012.
  6. MurmurHash3 on Github.
  7. а б Horvath, Adam (10 серпня 2012). MurMurHash3, an ultra fast hash algorithm for C# / .NET.
  8. MurmurHash2 on Github.
  9. MurmurHash2Flaw. Процитовано 15 січня 2019.
  10. MurmurHash3 (see note on MurmurHash2_x86_64). Процитовано 15 січня 2019.
  11. MurmurHash1. Процитовано 12 січня 2019.
  12. pyfasthash in Python. Процитовано 13 січня 2012.
  13. C implementation in qLibc by Seungyoung Kim.
  14. murmur3 in Go.
  15. Landman, Davy. Davy Landman in C#. Landman-code.blogspot.com. Процитовано 13 січня 2012.
  16. std.digest.murmurhash - D Programming Language. dlang.org. Процитовано 5 листопада 2016.
  17. Toru Maesaka in Perl. metacpan.org. Процитовано 13 січня 2012.
  18. Yuki Kurihara (16 жовтня 2014). Digest::MurmurHash. GitHub.com. Процитовано 18 березня 2015.
  19. stusmall/murmur3. GitHub. Процитовано 29 листопада 2015.
  20. PHP userland implementation of MurmurHash3. github.com. Процитовано 18 грудня 2017.
  21. PHP 8.1 with MurmurHash3 support.
  22. tarballs_are_good / murmurhash3. Процитовано 7 лютого 2015.
  23. Haskell. Hackage.haskell.org. Процитовано 13 січня 2012.
  24. Elm. package.elm-lang.org. Процитовано 12 червня 2019.
  25. Murmur3.java in Clojure source code on Github. clojure.org. Процитовано 11 березня 2014.
  26. Scala standard library implementation. 26 вересня 2014.
  27. Murmur3, part of Guava
  28. Murmur3A and Murmur3F Java classes on Github. greenrobot. Процитовано 5 листопада 2014.
  29. bipthelin/murmerl3. GitHub. Процитовано 21 жовтня 2015.
  30. Daisuke T (7 лютого 2019). MurmurHash-Swift. GitHub.com. Процитовано 10 лютого 2019.
  31. GitHub - Xor-el/HashLib4Pascal: Hashing for Modern Object Pascal
  32. goncalossilva/kotlinx-murmurhash. GitHub.com. 10 грудня 2021. Процитовано 14 грудня 2021.
  33. raycmorgan (owner). Javascript implementation by Ray Morgan. Gist.github.com. Процитовано 13 січня 2012.
  34. nginx. Процитовано 13 січня 2012.
  35. Rubinius. Процитовано 29 лютого 2012.
  36. libMemcached. libmemcached.org. Процитовано 21 жовтня 2015.
  37. switch from MD5 to murmur.
  38. maatkit. 24 березня 2009. Процитовано 13 січня 2012.
  39. Kyoto Cabinet specification. Fallabs.com. 4 березня 2011. Архів оригіналу за 28 грудня 2018. Процитовано 13 січня 2012.
  40. Partitioners. apache.org. 15 листопада 2013. Архів оригіналу за 18 грудня 2013. Процитовано 19 грудня 2013.
  41. Introduction to Apache Cassandra™ + What’s New in 4.0 by Patrick McFadin. DataStax Presents. YouTube. 10 квітня 2019.
  42. Solr MurmurHash2 Javadoc. Архів оригіналу за 24 червня 2022. Процитовано 4 березня 2023.
  43. hash.cc in vowpalwabbit source code.
  44. Elasticsearch 2.0 - CRUD and routing changes.
  45. Guava Hashing.java.
  46. Kafka DefaultPartitioner.java.
  47. Virtual Data Optimizer source code
  48. Breaking Murmur: Hash-flooding DoS Reloaded.