将C哈希函数转换为PHP:ezmlm_hash

时间:2010-06-30 15:28:41

标签: php c casting hash

我正在尝试在我的服务器上从PHP 5.2.x升级到5.3.2。问题是,我依赖于PHP的ezmlm_hash()的破解实现(这里列出了错误:http://bugs.php.net/bug.php?id=47969)。

我的第一个想法是用PHP自己重写破解版本的本机PHP函数(用C语言编写)并在我的代码中使用它,而不是修改PHP源代码并且必须从源代码编译PHP。 / p>

以下是代码的C版本:

PHP_FUNCTION(ezmlm_hash)
{
    char *str = NULL;
    unsigned int h = 5381L;
    int j, str_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
                              &str, &str_len) == FAILURE) {
        return;
    }

    for (j = 0; j < str_len; j++) {
        h = (h + (h << 5)) ^ (unsigned long) (unsigned char) tolower(str[j]);
    }

    h = (h % 53);

    RETURN_LONG((int) h);
}

这是我用PHP编写的内容:

function ezmlm_hash_mine($email_address){
    $h = 5381;
    $email_length = strlen($email_address);
    for($x=0;$x<$email_length;$x++){
        $chr = strtolower($email_address[$x]);
        $h = ($h + ($h << 5)) ^ ( ord($chr) );
    }

    $h = $h % 53;
    return $h;
}

我正在使用64位计算机。这两个函数输出不同的结果:

$email_addresses = array(
    'test@example.com',
    'mike@example.com',
);

print('<PRE>');

foreach($email_addresses as $email_address){
    print(ezmlm_hash($email_address).PHP_EOL);
    print(ezmlm_hash_mine($email_address).PHP_EOL.PHP_EOL);
}

输出:

23
-52

15
-21

我知道我可能有一些精确或打字问题,我只是不确定如何解决它。任何帮助将不胜感激!

更新

当我在32位机器上运行代码时,它们都输出新的校正值:

12
12

45
45

我认为这与模运算符有关...有没有人知道C模运算符的PHP等价物? PHP中的%表现不同!

更新2

似乎这对于vanilla PHP是不可能的,因为它的浮点运算没有足够的精度和奇怪的。我将不得不安装BCMath或GMP。感谢大家的见解。

2 个答案:

答案 0 :(得分:1)

计算后尝试将此EDIT截断为32位:

function ezmlm_hash_mine($email_address){
    $h = gmp_init(5381);
    $d = gmp_setbit(0, 64);
    $d32 = gmp_setbit(0, 32);
    $email_length = strlen($email_address);

    $chr = strtolower($email_address);

    for($x=0;$x<$email_length;$x++){    
        $h = gmp_mod(gmp_xor(gmp_mod(gmp_add($h, gmp_mod(gmp_mul($h, "32"), $d)), $d), ord($chr[$x])), $d32);
    }

    $h = gmp_mod($h, 53);
    return gmp_intval($h);
}

答案 1 :(得分:0)

问题可能出在这一行 $ h =($ h +($ h&lt;&lt; 5))^(ord($ chr));

在应用xor之前的C中,单个字符被强制转换为4字节长。虽然我不确定什么类型的ord返回,但尝试在较小的表达式中打破表达式并测试它们在C和PHP中表现相同的天气

像h +(h <&lt; 5)在每个h的C和PHP中应该表现完全相同。