Преобразование байтового потока в числовой тип данных

Предположим, у меня есть байтовый поток, в котором я знаю местоположение 64-битного значения (64-разрядное nonce). Байт-порядок – Маленький-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 

Просто просмотрел код для 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); } 

Изменение algorithem для использования байтового порядка 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); } 

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

Это похоже на полный взлом, но он должен выполнять эту работу, предполагая, что у вас есть функции математики BC, которые рекомендовал 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); } 

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