PHP convert large Decimal number to Hexadecimal - php

I am extracting information from a certificate using php and whilst the data is returned okay, there is one particular value "SerialNumber" which is being returned in what seems to be a different number format not sure what it is..
As an example, the actual format I am expecting to receive is:
‎58 ce a5 e3 63 51 b9 1f 49 e4 7a 20 ce ff 25 0f
However, what I am actually getting back is this:
118045041395046077749311747456482878735
Here is my php to perform the lookup:
$serial = $cert['tbsCertificate']['serialNumber'];
I have tried doing a few different conversions but none of them came back with the expected format.
Sample of a typical certificate serialnumber field..
VAR DUMP
["version"]=>
string(2) "v3"
["serialNumber"]=>
object(Math_BigInteger)#5 (6) {
["value"]=>
string(39) "118045041395046077749311747456482878735"
["is_negative"]=>
bool(false)
["generator"]=>
string(7) "mt_rand"
["precision"]=>
int(-1)
["bitmask"]=>
bool(false)
["hex"]=>
NULL

Your SerialNumber is a Math_BigInteger object as the var_dump shows.
Use the toHex method to retrieve the contained number in a hexadecimal format.
See reference on PEAR website.
$serial = $cert['tbsCertificate']['serialNumber'];
$valueInHex = $serial->toHex();
Note: 118045041395046077749311747456482878735 in decimal format equals to 58CEA5E36351B91F49E47A20CEFF250F in hexadecimal format. You may easily check that with an online converter like this.

Here is alternative solution to convert decimal number to hexadecimal format without using external libraries.
$dec = '118045041395046077749311747456482878735';
// init hex array
$hex = array();
while ($dec) {
// get modulus // based on docs both params are string
$modulus = bcmod($dec, '16');
// convert to hex and prepend to array
array_unshift($hex, dechex($modulus));
// update decimal number
$dec = bcdiv(bcsub($dec, $modulus), 16);
}
// array elements to string
echo implode('', $hex);
And the output of the code ... Online Demo
58cea5e36351b91f49e47a20ceff250f
You can also use string concatenation instead of array prepend. Hope this helps. Thanks!

Related

php binary to decimal

I am connecting to an api that returns binary string data that I need to convert to decimal format with php. The data comes across in four-part chunks like "66 50 235 133" and should translate to some value around 50.00 (not sure exactly what the decimal value should be, but should be close to 50).
So, I need to convert the binary string "66 50 235 133" to a decimal value around 50.
I have read the pack and unpack function pages on php.net, but am unsure if this is the correct function to use and which formats to use (signed/unsigned,endian,etc). Thanks for any help you can offer or any help point me in the right direction!
Might be:
$input = '66 50 235 133';
$value = unpack('g', implode('', array_map('chr', explode(' ', $input))));
// outputs -2.2117755600046E-35
Or:
$input = '66 50 235 133';
$value = unpack('G', implode('', array_map('chr', explode(' ', $input))));
// outputs 44.729999542236
Depending on the Endianness.
I suspect it's the later, if you think this number is close to 50.00.

How to convert uuid v4 of php into two 64 bit integers

Example:
Uuid generated from v4 of php :
8bc278cb-2fb6-413b-add6-8ba39bf830e8
I want to convert this into two 64 bit integers.
I've tried using hexdec of php but it's return value is of numbers. I want datatype integer.
Interestingly :
I have tried using hexdec with the above uuid and used this output to dechex. Some how, not getting the same value?
Any insights into this will be appreciated.
UUID is a 128bit data type. Excluding the 6 reserved bits, there are 122 data bits in it. Makes it impossible to fully convert any UUID to a 64bit integer. You'll at least need to store it as 2 64bit numbers or 4 32bit numbers.
You can unpack the UUID into binary, then unpack it as 4 32bit unsigned character:
function uuidToHex($uuid) {
return str_replace('-', '', $uuid);
}
function hexToUuid($hex) {
$regex = '/^([\da-f]{8})([\da-f]{4})([\da-f]{4})([\da-f]{4})([\da-f]{12})$/';
return preg_match($regex, $hex, $matches) ?
"{$matches[1]}-{$matches[2]}-{$matches[3]}-{$matches[4]}-{$matches[5]}" :
FALSE;
}
function hexToIntegers($hex) {
$bin = pack('h*', $hex);
return unpack('L*', $bin);
}
function integersToHex($integers) {
$args = $integers; $args[0] = 'L*'; ksort($args);
$bin = call_user_func_array('pack', $args);
$results = unpack('h*', $bin);
return $results[1];
}
$uuid = '1968ec4a-2a73-11df-9aca-00012e27a270';
var_dump($uuid);
$integers = hexToIntegers(uuidToHex('1968ec4a-2a73-11df-9aca-00012e27a270'));
var_dump($integers);
$uuid = hexToUuid(integersToHex($integers));
var_dump($uuid);
It will returns
string(36) "1968ec4a-2a73-11df-9aca-00012e27a270"
array(4) {
[1]=>
int(2764998289)
[2]=>
int(4245764002)
[3]=>
int(268479657)
[4]=>
int(120222434)
}
string(36) "1968ec4a-2a73-11df-9aca-00012e27a270"
$integers is an array 4 32bit numbers that represents the hex.
Reference
Stack Overflow: 16 bytes binary form of canonical uuid representation in php
Stack Overflow: How to convert byte array to integer in php?
PHP Manual: pack()
While it's common in other languages (like Java) to get the least significant and most significant bits of a UUID as two unsigned 64-bit integers, PHP has trouble with this because all integers in PHP are signed. Even if using a 64-bit build of PHP, you will run into integer overflows when trying to get a real integer value of the least or most significant bits of a UUID.
The maximum integer value on 64-bit PHP is 9,223,372,036,854,775,807, while an unsigned 64-bit integer has a max value of 18,446,744,073,709,551,615. A UUID as two 64-bit integers needs to support values up to 18,446,744,073,709,551,615.
As an earlier answer mentioned, it might be better to split up the UUID into four unsigned 32-bit integers, if you need to split it up like that. (The max value of an unsigned 32-bit integer is 4,294,967,295, which 64-bit PHP can support.)
If you're simply interested in storing a UUID in a more optimized way, you can convert it to a 16-byte binary string:
$uuid = '1968ec4a-2a73-11df-9aca-00012e27a270';
$binaryUuid = hex2bin(str_replace('-', '', $uuid));

Bitwise and in PHP

I am very new face to PHP. I read that dechex(255) will give the corresponding hex value ff in PHP.
I need the hex value of -105. I tried dechex(-105) and got the result as ffffff97. But I just only want 97 to do some kind of stuffs.
In Java I know that a bit wise operation with 0xff gave us the result 97 that is (byte)-105 & (byte)0xff = 0x97.
Please to find the solution in PHP just like I've done in Java.
You can do it in php like this:
var_dump(dechex(-105 & 255))
to make it out of the final byte (example output below)
string(2) "97"
dechex() gives you a hexadecimal value for a decimal value between 0 and 2*PHP_INT_MAX+1 (unsigned int).
Anything below 0 or above 2*PHP_INT_MAX+1, will loop.
-105 is NOT 0xffffff97 , and it is not 0x97
0xffffff97 is 4294967191.
and 0x97 is 151.
If you want the hexadecimal representation of the negative number turned into a positive number, use the function abs().
$abs = abs(-105); // $abs becomes +105
$hex = dechex($abs); // $hex becomes 69
Either you want a binary negative value (ffffff97) or a signed value
// for a signed value
$i = -105;
if($i < 0)
echo '-'.dechex(abs($i));
else echo dechex($i);
If you want to remove front "f"
echo preg_replace('#^f+#', '', dechex($i));

PHP convert integer to 32 bit (4 Byte) hex for socket programming

I need to convert integer to a 4 byte (32 bit) hex for sending it as ACK to a device i am currently trying to integrate.
For example
3 = 00000003
15 = 0000000F
Check http://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html
1. Select signed 32 bit from the dropdown
2. Enter the value in decomal text box
3. Check value in hex field.
I am using php pack function with this parameter but based on the response from the device, it does not seem to be the correct approach.
$reply = pack(L*,$num);
Is this the correct parameter or there is some other way.
Please suuggest.
i would do
$a = 15;
var_dump( sprintf("%08X", $a) );
$a = 3;
var_dump( sprintf("%08X", $a) );
this outputs
string(8) "0000000F"
string(8) "00000003
08X means make a 8 char string padded with 0 (if needed) with the argument being treated as hex. (Upper case letters)
so in your example
$reply = sprintf("%08X", $num)

Convert PHP SHA1 to Ruby

I have this algorithm in PHP:
$encoded_key = 'WHllcnRGYTY3eWpUNjQ';
$decoded_key = base64_decode($encoded_key);
// XyertFa67yjT64
$params_string = implode('', $params);
//U215250.00121715620http://partner.domain.ru/order/U215/successhttp://partner.domain.ru/order/U215/fail
$raw_signature = hash_hmac('sha1', $params_string, $decoded_key, true);
// Byte-encoded, hex: c6881d8665afbb46a93a16b34bd152878a19ab3a
$encoded_signature = base64_encode($raw_signature);
// xogdhmWvu0apOhazS9FSh4oZqzo=
I'm trying to port this code to Ruby and get the same result but Base64 and OpenSSL can't help me. Does any one know whats wrong?
One problem is that you are using HMAC.hexdigest instead of HMAC.digest. Your PHP code is generating a raw HMAC and then encoding it in base 64. Therefore, you need to do the same thing in Ruby.
The other problem is the base 64 decoding step of the key. The key you entered is not padded correctly and will therefore be truncated by Ruby's base 64 library. For example:
encoded_key = "WHllcnRGYTY3eWpUNjQ"
Base64.decode64(encoded_key)
#=> "XyertFa67yjT"
# incomplete!
Base64.decode64("#{encoded_key}=\n")
#=> "XyertFa67yjT64"
# this is what you actually want
The padding and the final newline are there to ensure that the base 64 encoded data is complete, since it marks the end. However, it is possible to manually add the padding and just assume that the data is complete:
require 'base64'
require 'openssl'
def base64_pad(unpadded_str)
padding = case unpadded_str.size % 3
when 1 then "=="
when 2 then "="
end
"#{unpadded_str}#{padding}\n"
end
encoded_key = "WHllcnRGYTY3eWpUNjQ"
key = Base64.decode64(base64_pad(encoded_key))
#=> "XyertFa67yjT64"
string = "U215250.00121715620http://partner.domain.ru/order/U215/successhttp://partner.domain.ru/order/U215/fail"
Base64.encode64(OpenSSL::HMAC.digest('SHA1', key, string))
#=> "xogdhmWvu0apOhazS9FSh4oZqzo=\n"

Categories