Sim*_*mon 10 hash wolfram-mathematica
在线文档说
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.
Run Code Online (Sandbox Code Playgroud)
它还提供" 可能的哈希代码类型":
然而,这些都不对应于返回的默认值Hash[expr].
所以我的问题是:
Hash使用什么方法?默认的哈希算法或多或少是应用于底层表达式表示的基本32位哈希函数,但确切的代码是Mathematica内核的专有组件.它受Mathematica版本之间的(并且已经)更改,并且缺少许多令人满意的加密属性,因此我个人建议您使用MD5或其中一种SHA变体用于任何安全问题的严重应用程序.内置散列用于典型的数据结构使用(例如,在散列表中).
您从文档中列出的命名哈希算法是目前唯一可用的哈希算法.你特别想找另一个吗?
我一直在对Mathematica 10.4的32位和64位Windows版本进行反向工程,这就是我发现的:
它使用Fowler-Noll-Vo散列函数(FNV-1,之前有乘法),其中16777619作为FNV质数,而?84696351?作为抵消基础。此功能适用于Murmur3-32表达式数据地址的哈希值(MMA使用指针以保留每个数据的一个实例)。该地址最终被解析为该值-对于简单的机器整数,该值是立即数,对于其他机器,则有点棘手。实际上,Murmur3-32实现函数包含一个附加参数(默认值为4,在Wikipedia中具有特殊情况,其行为类似于Wikipedia),该参数从输入的表达式结构中选择要选择的位数。由于正则表达式在内部表示为指针数组,因此可以通过向表达式的基本指针重复添加4(字节= 32位)来获取第一个,第二个等。因此,将8传递给该函数将给第二个指针,给12赋予第三个指针,依此类推。由于内部结构(大整数,机器整数,机器实数,大实数等)具有不同的成员变量(例如,机器整数只有一个指向int的指针,一个复杂的2个指向数字的指针等。),对于每个表达式结构,都有一个“包装器”,将其内部成员组合为一个单个32位哈希(基本上是FNV-1轮次)。哈希最简单的表达式是整数。
该murmur3_32()函数具有1131470165作为种子,n = 0和其他参数,如Wikipedia中所述。
因此,我们有:
hash_of_number = 16777619 * (84696351? ^ murmur3_32( &number ))
Run Code Online (Sandbox Code Playgroud)
其中“ ^”表示异或。我真的没有尝试过-指针是使用编码的WINAPI EncodePointer(),因此无法在运行时加以利用。(可能值得在Wine的修改版本下在Linux上运行EncodePonter)
它使用FNV-1 64位哈希函数,以0xAF63BD4C8601B7DF作为偏移量基础,以0x100000001B3作为FNV主数,以及SIP64-24哈希(此处是参考代码),前64位0x0AE3F68FE7126BBF76F98EF7F39DE1521作为k0,最后64位如k1。该函数将应用于表达式的基本指针并在内部解析。就像在32位的murmur3中一样,还有一个附加参数(默认为8)选择从输入表达式struct中选择多少个指针。对于每种表达式类型,都有一个包装器,用于通过FNV-1 64位舍入将结构成员压缩为单个散列。
对于机器整数,我们有:
hash_number_64bit = 0x100000001B3 * (0xAF63BD4C8601B7DF ^ SIP64_24( &number ))
Run Code Online (Sandbox Code Playgroud)
同样,我没有真正尝试过。有人可以尝试吗?
如果您看一下有关内部实现的说明,他们会说:“每个表达式都包含一种特殊形式的哈希码,该哈希码可用于模式匹配和评估。”
他们所指的哈希码就是这些函数生成的-在正则表达式包装器函数中的某个时刻,有一个分配将计算的哈希值放入表达式结构本身中。
了解它们如何将这些散列用于模式匹配目的当然是很酷的。因此,我尝试通过bigInteger包装器运行,以查看会发生什么-这是最简单的复合表达式。它开始检查返回1的东西-不知道是什么。这样执行
var1 = 16777619 * (67918732 ^ hashMachineInteger(1));
Run Code Online (Sandbox Code Playgroud)
使用hashMachineInteger()就是我们之前所说的-包括值。
然后它从struct(bignum_length)中读取bigInt的长度(以字节为单位)并运行
result = 16777619 * (v10 ^ murmur3_32(v6, 4 * v4));
Run Code Online (Sandbox Code Playgroud)
请注意,murmur3_32()如果4 * bignum_length大于8(则可能与机器整数的最大值有关,而与$MaxMachineNumber 2^32^32bigInt的假定相反)则称为。
因此,最终的代码是
if (bignum_length > 8){
result = 16777619 * (16777619 * (67918732 ^ ( 16777619 * (84696351? ^ murmur3_32( 1, 4 )))) ^ murmur3_32( &bignum, 4 * bignum_length ));
}
Run Code Online (Sandbox Code Playgroud)
我对此构造的属性做了一些假设。许多XOR的存在以及16777619 + 67918732 = 84696351?可能使人认为某种循环结构被利用来检查模式的事实-即减去偏移并除以质数,或类似的东西。Cassandra软件使用Murmur哈希算法生成令牌-请参阅这些图片以了解我对“循环结构”的含义。也许每个表达式都使用了不同的质数-必须仍然检查。
希望能帮助到你