如何在Python中获得相同的PHP adler32哈希?

时间:2015-05-27 10:03:37

标签: php python hash

我需要生成相同的adler32哈希,它由PHP生成,但使用Python。不幸的是,标准实现不同。有什么想法吗?

$ php -r 'print hash("adler32", "bla") . "\n";'
02620130

$ python -c 'import zlib; print zlib.adler32("bla");'
39977264

(使用PHP 5.5.9和Python 2.7.6)

目前我已经诉诸

def php_adler32(string):
    phpcode = """print hash("adler32", "%s");""" % string
    try:
        rv = subprocess.check_output(['php','-r',phpcode], shell=False)
    except subprocess.CalledProcessError as e:
        raise RuntimeError("Could not compute adler32 through php: %s" % e)
    return rv

但我害怕最终使用此代码登录dailywtf.com。

2 个答案:

答案 0 :(得分:1)

从四处查看,我相信PHP实现返回的值不正确。 (https://github.com/Sembiance/mhash/issues/6

使用PHP使用的旧版mhash库(现在通过哈希弃用)进行测试时,我们可以看到与当前哈希库相同的结果。

define('MOD_ADLER', 65521);
// Wikipedia Implimentation for testing.
function adler32($data) {
    $a = 1; 
    $b = 0; 
    $len = strlen($data);
    for ($index = 0; $index < $len; ++$index) {
        $a = ($a + $data[$index]) % MOD_ADLER;
        $b = ($b + $a) % MOD_ADLER;
    }
    return ($b << 16) | $a;
}
echo "programed version: " . adler32("bla") . "<br>";
echo "php version: " . hash("adler32", "bla") . "<br>";
echo "mhash version: " .bin2hex(mhash(MHASH_ADLER32, "bla"));

最终结果变为:

programed version: 196609 (I'm not quite sure why this occured to be honest)
php version: 02620130
mhash version: 02620130

我们可以看到PHP(哈希)和mash版本产生相同的结果,尽管mhash函数返回一个十六进制数。

zlib python结果在输出方面证明是最可靠的。

答案 1 :(得分:1)

简短回答,pyton以十进制给出结果,PHP以十六进制给出结果。所以如此转换:

php -r 'print hexdec(hash("adler32", "bla")) . "\n";'

应该给你一个与python同意的结果。

更长的答案

adler 32滚动散列由A和B值组成。 A值从1开始,并加上模数为65521的字符值.B值从零开始,加上当前A值模65521,所以对于bla我们有:

Character Decimal Adler_A Adler_B
                        1       0
      'b'      98      99      99
      'l'     108      207    306
      'a'      97      304    610

因此,整个字符串的最终adler32 A和B值为Adler_A = 304Adler_B = 610,当转换为big-endian十六进制时,Adler_A = 0130Adler_B = 0262。所以你可以看到PHP的哈希给你一个Adler_B的big-endian表示,然后是Adler_A,01300262。将此十六进制值转换为十进制会得到39977264,这是您从python中获得的。