1

假设我有一个字节流,其中我知道 64 位值(64 位随机数)的位置。字节顺序是 Little-Endian。由于 PHP 的整数数据类型仅限于 32 位(至少在 32 位操作系统上),我如何将字节序列转换为 PHP 数字表示(我认为浮点数就足够了)?

$serverChallenge = substr($bytes, 24, 8);
// $serverChallenge now contains the byte-sequence 
// of which I know that it's a 64-bit value
4

4 回答 4

6

刚刚查找了处理此问题的Zend_Crypt_Math_BigInteger_Bcmath代码Zend_Crypt_Math_BigInteger_Gmp

使用 BCmath (Big-Endian)

这基本上是Chad Birch发布的解决方案。

public static function bc_binaryToInteger($operand)
{
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = bcadd(bcmul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return $result;
}

使用 GMP(大端)

相同的算法 - 只是不同的函数名称。

public static function gmp_binaryToInteger($operand)
{
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = gmp_add(gmp_mul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return gmp_strval($result);
}

将算法更改为使用 Litte-Endian 字节顺序非常简单:只需从头到尾读取二进制数据:

使用 BCmath (Litte-Endian)

public static function bc_binaryToInteger($operand)
{
    // Just reverse the binray data
    $operand = strrev($operand);
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = bcadd(bcmul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return $result;
}

使用 GMP (Litte-Endian)

public static function gmp_binaryToInteger($operand)
{
    // Just reverse the binray data
    $operand = strrev($operand);
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = gmp_add(gmp_mul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return gmp_strval($result);
}
于 2009-04-08T07:10:19.970 回答
1

这似乎完全是一个技巧,但它应该可以完成这项工作,假设你有 daemonmoi 推荐的 BC 数学函数:

$result = "0";
for ($i = strlen($serverChallenge) - 1; $i >= 0; $i--)
{
    $result = bcmul($result, 256); // shift result

    $nextByte = (string)(ord($serverChallenge[$i]));
    $result = bcadd($result, $nextByte);
}
于 2009-04-07T15:24:36.077 回答
1

聚会晚了两年,但如果有人仍然关心:解包是这里的内置方式,您可以将其解包为几个 32 位整数或双精度。

于 2011-05-15T00:27:13.773 回答
0

我知道这不是问题的完全答案,但请查看BC Math 函数来处理大数字。

于 2009-04-07T14:46:14.250 回答