Converting byte-stream into numeric data-type

后端 未结 4 680
不思量自难忘°
不思量自难忘° 2021-01-16 01:11

Let\'s say I have a byte-stream in which I know the location of a 64-bit value (a 64-bit nonce). The byte-order is Little-Endian. As PHP\'s integer data-type is limited to 3

相关标签:
4条回答
  • 2021-01-16 01:41

    Just looked up the code for Zend_Crypt_Math_BigInteger_Bcmath and Zend_Crypt_Math_BigInteger_Gmp which deals with this problem:

    Using BCmath (Big-Endian)

    This is essentially the solution posted by 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;
    }
    

    Using GMP (Big-Endian)

    Same algorithem - just different function names.

    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);
    }
    

    Changing the algorithem to use Litte-Endian byte-order is quite simple: just read the binary data from end to start:

    Using 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;
    }
    

    Using 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);
    }
    
    0 讨论(0)
  • 2021-01-16 01:45

    Two years late to the party, but if anyone still cares: unpack is the built-in way to go here, you can unpack it as a couple of 32-bit ints, or as a double.

    0 讨论(0)
  • 2021-01-16 01:48

    This seems like a total hack, but it should do the job, assuming you have the BC Math functions that daemonmoi recommended:

    $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 讨论(0)
  • I know this is not quite the answer to the question, but check out the BC Math functions to handle big numbers.

    0 讨论(0)
提交回复
热议问题