Предположим, у меня есть байтовый поток, в котором я знаю местоположение 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
который занимается этой проблемой:
Это, по сути, решение, отправленное Чадом Берчем .
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; }
Тот же алгоритм – просто разные имена функций.
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 довольно просто: просто прочитайте двоичные данные с начала и конца:
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; }
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 для обработки больших чисел.