Преобразование байтового потока в числовой тип данных - PullRequest
1 голос
/ 07 апреля 2009

Допустим, у меня есть поток байтов, в котором я знаю местоположение 64-битного значения (одноразового номера 64-битного). Порядок байтов является Little-Endian. Поскольку целочисленный тип данных PHP ограничен 32-разрядным (по крайней мере, в 32-разрядных операционных системах), как бы я преобразовал последовательность байтов в числовое представление PHP (я думаю, было бы достаточно float)?

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

Ответы [ 4 ]

6 голосов
/ 08 апреля 2009

Только что посмотрел код для Zend_Crypt_Math_BigInteger_Bcmath и Zend_Crypt_Math_BigInteger_Gmp, который решает эту проблему:

Использование BCmath (Big-Endian)

Это, по сути, решение, опубликованное Чедом Бёрчем .

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 (Big-Endian)

Тот же алгоритм - только разные имена функций.

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);
}
2 голосов
/ 15 мая 2011

Два года опаздывает на вечеринку, но если кому-то все равно: распаковка - это встроенный способ перехода, вы можете распаковать его как пару 32-битных целых или как двойные.

1 голос
/ 07 апреля 2009

Это похоже на полный взлом, но он должен делать свою работу, предполагая, что у вас есть функции BC Math, рекомендованные daemonmoi:

$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);
}
0 голосов
/ 07 апреля 2009

Я знаю, что это не совсем ответ на вопрос, но посмотрите математические функции BC для обработки больших чисел.

...