Какой хеш-код по умолчанию используется Mathematica? - PullRequest
10 голосов
/ 28 октября 2010

Онлайновая документация гласит:

Hash[expr] 
  gives an integer hash code for the expression expr.
Hash[expr,"type"]
  gives an integer hash code of the specified type for expr.

В ней также указано " возможные типы хеш-кодов":

  • "Adler32" Adler 32-битная циклическая избыточностьпроверка
  • "CRC32" 32-битная циклическая избыточность проверка
  • "MD2" 128-битный код MD2
  • "MD5" 128-битный код MD5
  • "SHA" 160-битный код SHA-1
  • "SHA256" 256-битный код SHA
  • "SHA384" 384-битный код SHA
  • "SHA512" 512-битныйКод SHA

Тем не менее, ни один из них не соответствует значению по умолчанию, возвращаемому Hash[expr].

Итак, мои вопросы:

  • Какой метод используется по умолчанию Hash?
  • Существуют ли еще встроенные хэш-коды?

Ответы [ 3 ]

9 голосов
/ 29 октября 2010

Алгоритм хеширования по умолчанию, более или менее, является базовой 32-битной хеш-функцией, применяемой к базовому представлению выражения, но точный код является проприетарным компонентом ядра Mathematica.Он подвержен (и имеет) изменения между версиями Mathematica, и в нем отсутствует ряд желаемых криптографических свойств, поэтому я лично рекомендую использовать MD5 или один из вариантов SHA для любого серьезного приложения, где важна безопасность.Встроенный хеш предназначен для типичного использования структуры данных (например, в хеш-таблице).

Названные алгоритмы хэширования, перечисленные вами в документации, являются единственными доступными в настоящее время.Вы ищете другой, в частности?

5 голосов
/ 19 августа 2016

Я занимался реверс-инжинирингом 32- и 64-битной версии Windows Mathematica 10.4 для Windows, и вот что я нашел:

32 BIT

Используется Хеш-функция Фаулера-Нолла-Во (FNV-1, с умножением до) с 16777619 в качестве простого числа FNV и 84696351 в качестве смещения.Эта функция применяется к Murmur3-32 хэшированным значениям адреса данных выражения (MMA использует указатель для сохранения одного экземпляра каждого из данных).Адрес в конечном итоге преобразуется в значение - для простых целых чисел машины значение является немедленным, для других - немного хитрее.Реализующая функция Murmur3-32 фактически содержит дополнительный параметр (по умолчанию 4, особый случай, ведущий себя как в Википедии), который выбирает, сколько битов выбрать из структуры выражения во входных данных.Поскольку нормальное выражение внутренне представлено в виде массива указателей, можно взять первый, второй и т. Д. Путем многократного добавления 4 (байт = 32 бита) к базовому указателю выражения.Таким образом, передача 8 в функцию даст второй указатель, 12 третий и так далее.Поскольку внутренние структуры (большие целые числа, целые числа машин, вещественные числа, большие числа и т. Д.) Имеют разные переменные-члены (например, целое число машины имеет только указатель на int, сложные 2 указателя на числа и т. Д.), Для каждой структуры выраженияесть «обертка», которая объединяет свои внутренние члены в один 32-битный хэш (в основном с раундами FNV-1).Самым простым выражением для хэша является целое число.

Функция murmur3_32() имеет начальное значение 1131470165, n = 0 и другие параметры, как в Википедии.

Итак, мы имеем:

  hash_of_number = 16777619 * (84696351‬ ^ murmur3_32( &number ))

со значением «^»XOR.Я действительно не пробовал - указатели кодируются с использованием WINAPI EncodePointer(), поэтому они не могут быть использованы во время выполнения.(Может быть, стоит запустить в Linux под Wine с измененной версией EncodePonter?)


64 BIT

Используется 64-битный FNV-1хеш-функция с 0xAF63BD4C8601B7DF в качестве основы смещения и 0x100000001B3 в качестве простого FNV, вместе с хешем SIP64-24 ( здесь '- ссылочный код) с первым 64-битным битом 0x0AE3F68FE7126BBF76F0214 как BFF76F021F7последние 64 бита как k1.Функция применяется к базовому указателю выражения и разрешается внутри.Как и в 32-битном murmur3, есть дополнительный параметр (по умолчанию 8) для выбора количества указателей для выбора из структуры входного выражения.Для каждого типа выражения есть оболочка для конденсации членов структуры в один хеш с помощью 64-битных циклов FNV-1.

Для целого числа машины у нас есть:

    hash_number_64bit = 0x100000001B3 * (0xAF63BD4C8601B7DF ^ SIP64_24( &number ))

Опять же, я действительно не пробовал.Кто-нибудь может попробовать?


Не для слабонервных

Если вы посмотрите на их заметки о внутренней реализации , онискажем, что «Каждое выражение содержит особую форму хеш-кода, которая используется как при сопоставлении с образцом, так и при оценке».

Хеш-код, на который они ссылаются, это тот, который генерируется этими функциями - в какой-то момент вВ функции-обертке нормального выражения есть присваивание, которое помещает вычисленный хеш в саму структуру выражения.

Было бы здорово понять, КАК они могут использовать эти хеши для сопоставления с образцом.Поэтому я попытался запустить оболочку bigInteger, чтобы посмотреть, что произойдет - это простейшее составное выражение.Он начинает проверять что-то, что возвращает 1 - не знаю, что.Таким образом, он выполняет

    var1 = 16777619 * (67918732 ^ hashMachineInteger(1));

с помощью hashMachineInteger (), о чем мы говорили ранее, включая значения.

Затем он считывает длину в байтах bigInt из структуры (bignum_length) изапуски

    result = 16777619 * (v10 ^ murmur3_32(v6, 4 * v4));

Обратите внимание, что murmur3_32() вызывается, если 4 * bignum_length больше 8 (может быть связано с максимальным значением целых чисел машины $MaxMachineNumber 2^32^32 и, наоборот, с значением bigIntдолжен быть).

Итак, окончательный код:

    if (bignum_length > 8){

    result = 16777619 * (16777619 * (67918732 ^ ( 16777619 * (84696351‬ ^ murmur3_32( 1, 4 )))) ^ murmur3_32( &bignum, 4 * bignum_length ));
    }

I 'Мы сделали несколько предположений о свойствах этой конструкции.Наличие множества XOR и тот факт, что 16777619 + 67918732 = 84696351‬ может заставить задуматься о том, что какая-то циклическая структура используется для проверки шаблонов - то есть вычитание смещения и деление на простое число, или что-то в этом роде.Программное обеспечение Cassandra использует алгоритм хеширования Murmur для генерации токенов - см. эти изображения , что я имею в виду под «циклической структурой».Может быть, для каждого выражения используются разные простые числа - все равно нужно проверить.


Надеюсь, это поможет

2 голосов
/ 21 июля 2016

Кажется, что Hash вызывает внутреннюю функцию Data`HashCode, затем делит ее на 2, берет первые 20 цифр N [..], а затем IntegerPart плюс одну, то есть:

    IntegerPart[N[Data`HashCode[expr]/2, 20]] + 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...