Converting Hex String To Float - php

Hi I need to convert this HEX String 6BE15C3E into a float. I have been using an Arduino to do this in the past and below is the code I would use to convert the HEX into a float on an Arduino.
uint8_t l[] = {0x6b, 0xe1, 0x5c, 0x3e};
float var1;
memcpy(&var1, l, 4);
Serial.println(var1);
The result of the above code is 0.22 which is correct. I've tried using the following code in PHP but I don't get the correct answer:
print_r(hex2float("6BE15C3E"));
function hex2float($strHex) {
$hex = sscanf($strHex, "%02x%02x%02x%02x%02x%02x%02x%02x");
$hex = array_reverse($hex);
$bin = implode('', array_map('chr', $hex));
$array = unpack("dnum", $bin);
return $array['num'];
}
This code is returning 4.56588239954E+211 which seems way off and I'm not sure why. I know the Arduino example has been converted into bytes before hand but I don't know if this needs to be done in PHP.

These are probably not optimal, but I think they work:
function hex2float($strHex) {
$hex = sscanf($strHex, "%02x%02x%02x%02x");
$hex = array_reverse($hex);
$bin = implode('', array_map('chr', $hex));
$array = unpack("f", $bin);
return $array[1];
}
function float2hex($f)
{
$a = unpack("I", pack( "f", $f ));
$w = pack("N", $a[1] );
return bin2hex($w);
}
Tests:
function Test($hex)
{
$f = hex2float($hex);
$hex2 = float2hex($f);
echo "$hex --> $f --> $hex2<br>\n";
}
3f800000 --> 1 --> 3f800000
40000000 --> 2 --> 40000000
bf800000 --> -1 --> bf800000
c0000000 --> -2 --> c0000000
6BE15C3E --> 5.448878216557E+26 --> 6be15c3e
3E5CE16B --> 0.21570365130901 --> 3e5ce16b
Assuming your Arduino and your PHP script are running on different "endian" machines, then the array_reverse() should be removed from hex2float to 'fix' that function. (And float2hex will need some kind of reverse to make it match.)
I have not thought through what it would take to implement conversion between DOUBLE and hex.

Thank you Nigel Ren for fixing this issue. Here is the code used to fix the issue:
function hex2float($strHex) {
$hex = sscanf($strHex, "%02x%02x%02x%02x%02x%02x%02x%02x");
$bin = implode('', array_map('chr', $hex));
$array = unpack("f", $bin);
return $array[1];
}
When inputting 6BE15C3E it returns 0.215... which is the correct answer when rounded up.

Related

convert string to base convert 62 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I was trying to make a URL shortener. Where the give url needs to convert to base 62
I have converted the URL in following but it convert it to random number like 0 or 1sromm8 or 2gs0ygibs
base_convert($shortener->full_url, 10, 36);
How do i convert it to base62 so that every time 5 characters unique name generated.
I use this customized function to convert String to base62 String
function b62e($str) {
if(mb_check_encoding($str, 'ASCII')) {
$out = '';
$len = strlen($str);
for($i=0; $i<$len; $i+=8) {
$chunk = substr($str, $i, 8);
$outlen = ceil( strlen($chunk)*8/6 );// 8bit/char in, 6bits/char out, round up
$hex = bin2hex($chunk);// gmp won't convert from binary, so go via hex
$raw = gmp_strval(gmp_init(ltrim($hex, '0'), 16), 62);// gmp doesn't like leading 0s
$out .= str_pad($raw, $outlen, '0', STR_PAD_LEFT);
}
return $out;
}
return false;// unicode chars not supported
}
function b62d($str) {
if(mb_check_encoding($str, 'ASCII')) {
$out = '';
$len = strlen($str);
for ($i=0; $i<$len; $i+=11) {
$chunk = substr($str, $i, 11);
$outlen = floor( strlen($chunk)*6/8 );// 6bit/char in, 8bits/char out, round down
$raw = gmp_strval(gmp_init(ltrim($chunk, '0'), 62), 16);// gmp doesn't like leading 0s
$pad = str_pad($raw, $outlen * 2, '0', STR_PAD_LEFT);// double output length as as we're going via hex (4bits/char)
$out .= pack('H*', $pad);// same as hex2bin
}
return $out;
}
return false;// unicode chars not supported
}
Demo
All credits go to Marcus Bointon, Thanks to Flash Thunder answer
May you also use obfuscator to prevent users decode variables
function obf62rep($which){// make array before translate string
$rep = [];
$str1 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$str2 = 'GHIJKLMNqrstuvwx01OPQRSTUVWXYZhijklmnop23456789abcdefgyzABCDEF';
if($which){// while obfuscate from-->to
$fr = str_split($str1);
$to = $str2;
}else{// while de-obfuscate to-->from
$fr = str_split($str2);
$to = $str1;
}
foreach($fr as $k=>$v){// make array tr-->to
$rep[$v] = $to[$k];
}
return $rep;
}
function obf62e($str){return strtr($str,obf62rep(1));}// translate string = obf
function obf62d($str){return strtr($str,obf62rep(0));}// translate back = deobf
Demo
And then make it more simple to use, like
function ob62e($str){return obf62e(b62e($str));}// encode base62 + obfuscate
function ob62d($str){return b62d(obf62d($str));}// decode base62 + deobfuscate
Sample usage
echo ob62e('test');
$name = ob62e('jhon');

How to convert binary to string with PHP

I want to convert a binary string to hexademical with PHP. The binary string encodes text.
I tried this code:
echo pack('H*', base_convert('0100100001100101011011000110110001101111001000000101011101101111011100100110110001100100', 2, 16));
But it is not working on long binary strings.
Example: I want 'Hello World', but it is writing 'Hello X'.
How to convert binary to hexadecimal with PHP?
As said in the php documentation, this is caused because:
base_convert() may lose precision on large numbers due to properties related to the internal "double" or "float" type used. Please see the Floating point numbers section in the manual for more specific information and limitations.
In the same documentation, there are a few code examples on how to solve this issue, like this one:
<?php
convBase('123', '0123456789', '01234567');
//Convert '123' from decimal (base10) to octal (base8).
//result: 173
convBase('70B1D707EAC2EDF4C6389F440C7294B51FFF57BB', '0123456789ABCDEF', '01');
//Convert '70B1D707EAC2EDF4C6389F440C7294B51FFF57BB' from hexadecimal (base16) to binary (base2).
//result:
//111000010110001110101110000011111101010110000101110
//110111110100110001100011100010011111010001000000110
//001110010100101001011010100011111111111110101011110
//111011
convBase('1324523453243154324542341524315432113200203012', '012345', '0123456789ABCDEF');
//Convert '1324523453243154324542341524315432113200203012' from senary (base6) to hexadecimal (base16).
//result: 1F9881BAD10454A8C23A838EF00F50
convBase('355927353784509896715106760','0123456789','Christopher');
//Convert '355927353784509896715106760' from decimal (base10) to undecimal (base11) using "Christopher" as the numbers.
//result: iihtspiphoeCrCeshhorsrrtrh
convBase('1C238Ab97132aAC84B72','0123456789aAbBcCdD', '~!##$%^&*()');
//Convert'1C238Ab97132aAC84B72' from octodecimal (base18) using '0123456789aAbBcCdD' as the numbers to undecimal (base11) using '~!##$%^&*()' as the numbers.
//result: !%~!!*&!~^!!&(&!~^#####&
function convBase($numberInput, $fromBaseInput, $toBaseInput)
{
if ($fromBaseInput==$toBaseInput) return $numberInput;
$fromBase = str_split($fromBaseInput,1);
$toBase = str_split($toBaseInput,1);
$number = str_split($numberInput,1);
$fromLen=strlen($fromBaseInput);
$toLen=strlen($toBaseInput);
$numberLen=strlen($numberInput);
$retval='';
if ($toBaseInput == '0123456789')
{
$retval=0;
for ($i = 1;$i <= $numberLen; $i++)
$retval = bcadd($retval, bcmul(array_search($number[$i-1], $fromBase),bcpow($fromLen,$numberLen-$i)));
return $retval;
}
if ($fromBaseInput != '0123456789')
$base10=convBase($numberInput, $fromBaseInput, '0123456789');
else
$base10 = $numberInput;
if ($base10<strlen($toBaseInput))
return $toBase[$base10];
while($base10 != '0')
{
$retval = $toBase[bcmod($base10,$toLen)].$retval;
$base10 = bcdiv($base10,$toLen,0);
}
return $retval;
}
?>
then you can just echo the return value of this function with the pack() function.

Php change a number into another number that can be changed back to the original

Using PHP, I'm trying to encode a number into another number that I can decode back to the original number. The encoded string needs to be only numbers and should not contain anything else.
Eg: 10 becomes 573563547892 or something like that.
How can I do something like this in PHP? I tried quite a few encrypt decrypt functions, but none output only numbers.
I looking for something to use in a URL that isn't easy to guess.
So: http://www.me.com/index.PHP?page=20 becomes http://www.me.com/index.PHP?page=5705254782562466
Why not using a mathematicat operation on the original number? like x becomes x * y + z. you would only have to make the reverse operation to get the original number. consider using large enough prime numbers for y and/or z
Quite heavy, but very good encryption, by using ord & chr a bit. While this works, consider other options: just being able to use strings rather then numbers already makes it a lot simpler (base64_encode etc.):
<?php
class Crypter {
private $key = '';
private $iv = '';
function __construct($key,$iv){
$this->key = $key;
$this->iv = $iv;
}
protected function getCipher(){
$cipher = mcrypt_module_open(MCRYPT_BLOWFISH,'','cbc','');
mcrypt_generic_init($cipher, $this->key, $this->iv);
return $cipher;
}
function encrypt($string){
$binary = mcrypt_generic($this->getCipher(),$string);
$string = '';
for($i = 0; $i < strlen($binary); $i++){
$string .= str_pad(ord($binary[$i]),3,'0',STR_PAD_LEFT);
}
return $string;
}
function decrypt($encrypted){
//check for missing leading 0's
$encrypted = str_pad($encrypted, ceil(strlen($encrypted) / 3) * 3,'0', STR_PAD_LEFT);
$binary = '';
$values = str_split($encrypted,3);
foreach($values as $chr){
$chr = ltrim($chr,'0');
$binary .= chr($chr);
}
return mdecrypt_generic($this->getCipher(),$binary);
}
}
$crypt = new Crypter('secret key','12348765');
$encrypted = $crypt->encrypt(1234);
echo $encrypted.PHP_EOL;
//fake missing leading 0
$encrypted = ltrim($encrypted,'0');
echo $encrypted.PHP_EOL;
$decrypted = $crypt->decrypt($encrypted);
echo $decrypted.PHP_EOL;
Result:
057044206104214236155088
57044206104214236155088
1234

Native PHP function for hex string representation?

Is there a native PHP function for converting a string to its HEX representation that can be then eval()'d as a string, such as:
"ABC" => "\x41\x42\x43"
I know it can be done in several steps, I'm just wondering if I'm unnecessarily complicating something that could be done with a single, native function?
There is no native function, but you can use hex2bin to eval PHP code which is in hex, e.g.
eval(hex2bin("6563686f20706928293b")); # Output: 3.14159265359
eval(hex2bin(bin2hex("echo pi();"))); # Behind the scenes.
Or you can call the function which name is in hex string:
$ echo '<?$_=hex2bin(7069);die($_());' | php # 7069 = pi
3.14159265359
There is no built in PHP function to achieve the same results, but with some PHP-Fu you can do it in one line:
$str = 'ABC';
$str = '\x'.implode('\x', str_split(bin2hex($str), 2));
echo $str; // \x41\x42\x43
There is also a piece of code in the PHP docs which gives exactly the same results:
$str = 'ABC';
$field=bin2hex($str);
$field=chunk_split($field,2,"\\x");
$field= "\\x" . substr($field,0,-2);
echo $field; // \x41\x42\x43
$n = 1234;
echo printf("%x", $n); //should return the hexadecimal format of the number
Why don't you try something like this?
function strtohex($string) {
if (!empty($string)) {
$output = null;
$count = strlen($string, "UTF-8");
for ($i = 0; $i < $count; $i++) {
$output .= dechex(ord($string[$i]));
}
return $output;
}
}
For one-liners, the only alternative I can think about is the bin2hex() function, which is native in PHP and it offers the same.

PHP fast random string function

I need fast way for generating random strings a-Z0-9 in PHP. I've been doing some thinking and testing, this is what I've got so far:
function randStr($length) {
$result = null;
$replace = array('/', '+', '=');
while(!isset($result[$length-1])) {
$result.= str_replace($replace, NULL, base64_encode(mcrypt_create_iv($length, MCRYPT_RAND)));
}
return substr($result, 0, $length);
}
Function seems to be working fast compared to functions which iterate and choose random ASCII value for each char, but I'm concerned with 'quality' of my implementation. I do not know much about cryptography, so I'd like to ask whether this kind of function creates 'good' random values or not.
mcrypt_create_iv seems to return some kind of random binary values, actually used for encrypting/decrypting data with mcrypt library. What is base64_encode effect on this kind of binary data, do I actually decrease entropy, when I base64_encode it?
How does second parameter for mcrypt_create_iv affect my results? php.net manual states that MCRYPT_RAND is 'system random number generator'. Is it OS specific and if so, how good values are created?
This supposed to be secure on most of the systems and fast:
bin2hex(openssl_random_pseudo_bytes($length / 2));
benchmarks (1000000 records, string length 100 chars)
rstr1: 198.93383002281
rstr2: 35.5827729702
rstr3: 6.8811790943146
rstr4: 5.4545040130615
this:: 3.9310231208801
For anyone looking for an updated version of the "best" algorithm:
function randomString($length) {
$result = null;
$replace = array('/', '+', '=');
while(!isset($result[$length-1])) {
$result.= str_replace($replace, NULL, base64_encode(random_bytes($length)));
}
return substr($result, 0, $length);
}
I use the term "best" because it is faster than the random string manipulations of rstr1 and rstr2 and in comparison to the other solutions offers a full spectrum of letters (lower- and uppercased).
From my tests, your function is already very fast, but i managed to get to a faster one, even if it decreases the entropy
fcn time
rstr1: 1.074s (slowest)
rstr2: 0.917s
rstr3: 0.028s (yours)
rstr4: 0.022s (mine)
In my scenario, i needed 1k strings, as fast as possible.
function rstr1($length)
{
// #see http://stackoverflow.com/a/853846/11301
$alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return substr(str_shuffle(str_repeat($alphabet, $length)), 0, $length);
}
function rstr2($length)
{
// #see http://stackoverflow.com/a/853870/11301
$alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
$count = strlen($alphabet);
while ($length--) {
$str .= $alphabet[mt_rand(0, $count-1)];
}
return $str;
}
function rstr3($length) {
// #see http://stackoverflow.com/q/4757392/11301
$result = null;
$replace = array('/', '+', '=');
while(!isset($result[$length-1])) {
$result.= str_replace($replace, NULL, base64_encode(mcrypt_create_iv($length, MCRYPT_RAND)));
}
return substr($result, 0, $length);
}
function rstr4($length)
{
// uses md5 & mt_rand. Not as "random" as it could be, but it works, and its fastest from my tests
return str_shuffle(substr(str_repeat(md5(mt_rand()), 2+$length/32), 0, $length));
}
// test the functions
for($i=0; $i<1000; $i++){
#$x = rstr1(1024); #
#$x = rstr2(1024); # 0.917s
#$x = rstr3(1024); # 0.028s
#$x = rstr4(1024); # 0.022s
#dlog($x); return;
}
base64_encoding won't decrease entropy, it is just a different representation of the same data.
It is OS specific, but I think the random values created are good enough with this function. Under PHP 5.3 you have to seed the generator beforehand, it can be a problem if you use this code on different servers.
I usually work with this one.
Also I can choose if I don't want certain characters
function rstr5($length = 1) {
return substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyz", $length)), 0, $length);
}
This is how I'm doing it, though it's not exactly cryptographic; The Mersenne Twister is fast and reliable, but not the most secure.
function str_rand($chars, $len)
{
$str = '';
for ($max = strlen($chars) - 1, $i = 0; $i < $len; ++$i)
{
$str .= $chars[mt_rand(0, $max)];
}
return $str;
}
$strRand = str_rand('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 40);

Categories