简体   繁体   English

FNV“风味”和PHP实现

[英]FNV 'flavors' and PHP implementation

I'm trying to integrate FNV hashing algorithm on a PHP-based project as part of a requirement to produce hashes for a variety of data (eg URLs, keywords). 我正在尝试将FNV哈希算法集成到基于PHP的项目中,作为为各种数据(例如URL,关键字)生成哈希的要求的一部分。

I saw this implementation by Neven Boyanov. 我看到了Neven Boyanov的实现 He mentioned that due to arithmetic limitations in PHP, he was forced to use bitwise-shifting and addition instead of multiplication. 他提到由于PHP中的算术限制,他被迫使用按位移位和加法而不是乘法。 Is his implementation correct? 他的实现正确吗? My knowledge is somehow limited in this area of computer science so I can't verify it myself. 我的知识在某种程度上受限于计算机科学领域,因此我自己无法对其进行验证。

Another question that I have is about the different 'flavors' of FNV. 我还有一个问题是关于FNV的不同“风味”。 I saw that it offers 32-bit, 64-bit, and 128-bit variants but using the above implemention I always get 8-character hex hashes (I convert the integer result to hex using dechex()). 我看到它提供了32位,64位和128位变体,但是使用上述实现,我总是得到8个字符的十六进制散列(我使用dechex()将整数结果转换为十六进制)。

Given the input "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin at libero mi, quis luctus massa.", I get the following hex results: 给定输入“ Lorem ipsum dolor sit amet,consectetur adipiscing elit。Proin at libero mi,quis luctus massa。”,我得到以下十六进制结果:

  • (32-bit offset) 5b15c0f2 (32位偏移量)5b15c0f2
  • (64-bit offset) 6ea33cb5 (64位偏移)6ea33cb5

Why is this so? 为什么会这样呢? I'm expecting a 16-character hex result from the 64-bit FNV. 我期望64位FNV产生16个字符的十六进制结果。 Are the 'flavors' referring only to the kind of arithmetic operations and seeds that would be used and not to the length of the result? “风味”仅是指将要使用的算术运算和种子类型,而不是结果的长度吗? (ie if I say 64-bit FNV, the hashing function would use 64-bit operations and seed but the result would still be 32-bit) (即,如果我说的是64位FNV,则散列函数将使用64位操作和种子,但结果仍为32位)

A bit of enlightenment would be greatly appreciated :) 有点启发,将不胜感激:)

I wrote PHP FNV hash function long ago and it was for a particular purpose, so at that time the 32-bit implementation was sufficient. 我很早以前就编写了PHP FNV哈希函数,它是出于特定目的,因此当时的32位实现就足够了。

To answer your first question - the implementation was tested against other (C and C++) implementations by comparing the algorithm (code) and sample results. 要回答您的第一个问题-通过比较算法(代码)和示例结果,将该实现针对其他(C和C ++)实现进行了测试。 So for 32-bit results it works as it should. 因此,对于32位结果,它可以正常工作。

If you want to implement the 64-bit (or 128-bit) version yourself you should change first the FNV_offset_basis but also the expression on line 73 which currently is: 如果您想自己实现64位(或128位)版本,则应首先更改FNV_offset_basis,还应更改第73行上的表达式,该表达式当前为:

$hash += ($hash<<1) + ($hash<<4) + ($hash<<7) + ($hash<<8) + ($hash<<24);

... this is equivalent of multiplying by the number 16777619 (FNV_prime_32) which in binary is 1000000000000000110010011 - broken down to this expression: 2^24 + 2^8 + 2^7 + 2^4 + 2^1 + 2^0 . ...这等于乘以16777619(FNV_prime_32)的数字(二进制​​为1000000000000000110010011)-分解为以下表达式: 2^24 + 2^8 + 2^7 + 2^4 + 2^1 + 2^0

For 64-bit you should multiply by 1099511628211 - binary 10000000000000000000000000000000110110011 ... expression: 2^88 + 2^8 + 2^7 + 2^5 + 2^4 + 2^1 + 2^0 . 对于64位,您应该乘以1099511628211-二进制1000000000000000000000000000000011011011 ...表达式: 2^88 + 2^8 + 2^7 + 2^5 + 2^4 + 2^1 + 2^0

I don't know how the expression $hash << 88 will be handled by PHP but you should experiment yourself. 我不知道表达式$hash << 88将如何被PHP处理,但是您应该尝试一下。 On my PHP 5.2.x it did not work well for numbers greater than 31. 在我的PHP 5.2.x上,不适用于大于31的数字。

Finally, you may need to modify the $hash = $hash & 0x0ffffffff; 最后,您可能需要修改$hash = $hash & 0x0ffffffff; to remove some garbage from the result. 从结果中删除一些垃圾。 I figured that out through experiments. 我通过实验弄清楚了。 For the 64-bit ot should be like $hash = $hash & 0x0ffffffffffffffff; 对于64位ot,应类似于$hash = $hash & 0x0ffffffffffffffff; . Verify if it works correctly with PHP. 验证它是否可以在PHP中正常工作。

You can also use other PHP libraries for higher arithmetic precision. 您还可以使用其他PHP库来提高算术精度。 In my opinion using bitwise shifts is faster. 我认为使用按位移位更快。

In fact you can product FNV Hash for any number of bits. 实际上,您可以乘以任意数量的位来生成FNV哈希。

It turns out that the implementation I cited is for 32-bit FNV1 only. 事实证明,我引用的实现仅适用于32位FNV1。 I managed to compile the C-source of FNV and used the binary and Tom's suggested tool to verify that 64-bit FNV indeed returns 16-character hex hashes 我设法编译了FNV的C源代码 ,并使用了二进制文件和Tom建议的工具来验证64位FNV确实返回了16个字符的十六进制哈希

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM