php - 将嵌入式 C 函数转换为 PHP 函数

标签 php c function unsigned-integer

我正在尝试在 PHP 中“翻译”以下用 C 语言编写的函数。问题是,用 PHP 编写的函数返回的结果与用 C 编写的函数返回的结果不同。

我认为问题来自 PHP 中的整数溢出,它无法将变量视为无符号 32 位整数。

我尝试用 0xFFFFFFFF 对所有操作进行 AND 屏蔽,但没有成功。您有其他可行的解决方案吗?

C 函数:

void
decipher(const uint32_t num_rounds, uint32_t v[2], const uint32_t key[4])
{
    uint32_t idx;
    uint32_t v0 = v[0];
    uint32_t v1 = v[1];
    uint32_t delta = 0x9E3779B9;
    uint32_t sum = delta * num_rounds;

    for (idx = 0; idx < num_rounds; ++idx)
    {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }

    v[0] = v0;
    v[1] = v1;
}

PHP 函数:

function decipher($num_rounds, &$v, $key)
{
    $v0 = $v[0];
    $v1 = $v[1];
    $delta = 0x9E3779B9;
    $sum = ($delta * $num_rounds) & 0xFFFFFFFF;

    for ($idx = 0; $idx < $num_rounds; ++$idx)
    {
        $v1 -= (((($v0 << 4) ^ ($v0 >> 5)) + $v0) ^ ($sum + $key[($sum >> 11) & 3])) & 0xFFFFFFFF;
        $v1 &= 0xFFFFFFFF;
        $sum -= $delta;
        $sum &= 0xFFFFFFFF;
        $v0 -= ((($v1 << 4) ^ ($v1 >> 5) + $v1) ^ ($sum + $key[$sum & 3])) & 0xFFFFFFFF;
        $v0 &= 0xFFFFFFFF;
    }

    $v[0] = $v0;
    $v[1] = $v1;
}

谢谢。

解决方案:

我找到了一个解决方案:以下代码使用允许对无符号 32 位整数进行移位操作和加法的函数。

function decipher($num_rounds, &$v, $key)
{
    $v0 = $v[0];
    $v1 = $v[1];
    $delta = 0x9E3779B9;
    $sum = ($delta * $num_rounds) & 0xFFFFFFFF;

    for ($idx = 0; $idx < $num_rounds; ++$idx)
    {   
        $v1 = _add($v1, -(_add($v0 << 4 ^ _rshift($v0, 5), $v0) ^ _add($sum, $key[_rshift($sum, 11) & 3])));
        $sum = _add($sum, -$delta);
        $v0 = _add($v0, -(_add($v1 << 4 ^ _rshift($v1, 5), $v1) ^ _add($sum, $key[$sum & 3])));
    }

    $v[0] = $v0;
    $v[1] = $v1;
}

function _rshift($integer, $n)
{
    // convert to 32 bits
    if (0xffffffff < $integer || -0xffffffff > $integer)
    {
        $integer = fmod($integer, 0xffffffff + 1);
    }

    // convert to unsigned integer
    if (0x7fffffff < $integer) {
        $integer -= 0xffffffff + 1.0;
    }
    else if (-0x80000000 > $integer)
    {
        $integer += 0xffffffff + 1.0;
    }

    // do right shift
    if (0 > $integer)
    {
        // remove sign bit before shift
        $integer &= 0x7fffffff;
        // right shift
        $integer >>= $n;
        // set shifted sign bit
        $integer |= 1 << (31 - $n);
    }
    else
    {
        // use normal right shift
        $integer >>= $n;
    }

    return $integer;
}


function _add($i1, $i2)
{
    $result = 0.0;

    foreach (func_get_args() as $value)
    {
        // remove sign if necessary
        if (0.0 > $value)
        {
            $value -= 1.0 + 0xffffffff;
        }

        $result += $value;
    }

    // convert to 32 bits
    if (0xffffffff < $result || -0xffffffff > $result)
    {
        $result = fmod($result, 0xffffffff + 1);
    }

    // convert to signed integer
    if (0x7fffffff < $result)
    {
        $result -= 0xffffffff + 1.0;
    }
    else if (-0x80000000 > $result)
    {
        $result += 0xffffffff + 1.0;
    }

    return $result;
}

感谢您的回答。

最佳答案

如果您需要在 PHP 中对非常大的整数进行数学运算,您的选择基本上是使用字符串和您选择的任意精度库:

在这种情况下,GMP 是您唯一的选择,因为其他库不支持按位运算。

关于php - 将嵌入式 C 函数转换为 PHP 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8324719/

相关文章:

php - PHP 中的并行下载

php - 在保留变量名称的同时将 mySQL 函数转换为 PDO 时遇到问题 - 几乎已经解决了

c - 不同的 gdb 寄存器名称

swift - 我可以在 Swift 中使用运算符作为默认函数参数吗?

javascript - 使用函数声明时的自定义函数(也称为惰性函数定义)

php - 在laravel Blade 模板中访问对象内的对象

php - 如何在 shopify 的产品详细信息页面上显示元字段?

c - `free()` 包装器

c - 调试套接字程序

function - 函数如何在内存中编码/存储?