Encoding/decoding string in hexadecimal and back - php

Given a string that may contain any character (including a unicode characters), how can I convert this string into hexadecimal representation, and then reverse and obtain from hexadecimal this string?

Use pack() and unpack():
function hex2str( $hex ) {
return pack('H*', $hex);
}
function str2hex( $str ) {
return array_shift( unpack('H*', $str) );
}
$txt = 'This is test';
$hex = str2hex( $txt );
$str = hex2str( $hex );
echo "{$txt} => {$hex} => {$str}\n";
would produce
This is test => 546869732069732074657374 => This is test

Use a function like this:
<?php
function bin2hex($str) {
$hex = "";
$i = 0;
do {
$hex .= dechex(ord($str{$i}));
$i++;
} while ($i < strlen($str));
return $hex;
}
// Look what happens when ord($str{$i}) is 0...15
// you get a single digit hexadecimal value 0...F
// bin2hex($str) could return something like 4a3,
// decimals(74, 3), whatever the binary value is of those.
function hex2bin($str) {
$bin = "";
$i = 0;
do {
$bin .= chr(hexdec($str{$i}.$str{($i + 1)}));
$i += 2;
} while ($i < strlen($str));
return $bin;
}
// hex2bin("4a3") just broke. Now what?
// Using sprintf() to get it right.
function bin2hex($str) {
$hex = "";
$i = 0;
do {
$hex .= sprintf("%02x", ord($str{$i}));
$i++;
} while ($i < strlen($str));
return $hex;
}
// now using whatever the binary value of decimals(74, 3)
// and this bin2hex() you get a hexadecimal value you can
// then run the hex2bin function on. 4a03 instead of 4a3.
?>
Source: http://php.net/manual/en/function.bin2hex.php

Related

php string to hex with2's complement:

Hi I have a string 193390663 which I want to convert into the hex with 2's compliment. The output is 0B86E847
Right now I am using below function but it's giving me 313933333930363633
public static function String2Hex($string)
{
$hex = '';
for($i=0; $i<strlen($string); $i++)
{
$hex.=dechex(ord($string[$i]));
}
}
Update 1
Tried this
$sub2 = substr($m->msn,4,9);
$m->m_hex = dechex ($sub2);
Output
b86e847
But I want output like 0B86E847
Any help would be highly appreciated.
Solution you are looking for is as below,
It is referenced from one of the answer given at Create hex-representation of signed int in PHP.
<?php
function signed2hex($value, $reverseEndianness = true)
{
$packed = pack('i', $value);
$hex='';
for ($i=0; $i < 4; $i++){
$hex .= strtoupper( str_pad( dechex(ord($packed[$i])) , 2, '0', STR_PAD_LEFT) );
}
$tmp = str_split($hex, 2);
$out = implode('', ($reverseEndianness ? array_reverse($tmp) : $tmp));
return $out;
}
echo signed2hex(193390663);

PHP problem with Bulgarian-MIK character set, cant get one letter

I know that Bulgarian-MIK character set can be converted with the ord function and adding 64, and the bulgarian-MIK characters are from 127 to 191 but i cant get the letter "а"(ord - 127).I tried a lot of ways but it seems that php is processing "а" with a blank symbol and i cant get it.
define("PHP_NL", "<br>");
$string = '-------------- 1 --------------'.PHP_NL;
$string .= '413 …±Ї°Ґ±® €¶® X1.000'.PHP_NL;
$string .= '358 ЊЁ­ ‚®¤  0.5 X1.000'.PHP_NL;
$string .= '--------------------------------'.PHP_NL;
$string .= '1 -Ђ¤°Ё ­  - ЊЂ‘Ђ: 1 - 6'.PHP_NL;
$string .= '17-08-2018 09:05:32'.PHP_NL;
$string .= '--------------------------------';
That is my string with Bulgarian-MIK encoding.I tried to convert it and i every letter is converted fine, but only "а" i cant get.
My function
function ConvertDosToWin($string) {
$chr = null;
for ($i = 1;$i<strlen($string);$i++) {
$chr = mb_convert_encoding($string[$i],'utf-8','windows-1251');
if((ord($chr) >= 127) && (ord($chr)<=(127+64)) ) {
echo 'inside if';
$string[$i] = chr(ord($chr)+64);
}
}
return $string;
}
I fixed the problem using iconv.
function ConvertWinToDos($string) {
$chr = null;
for ($i = 1;$i<strlen($string);$i++) {
$string = iconv(mb_detect_encoding($string,mb_detect_order(),true),'windows-1251',$string);
$chr = $string[$i];
if ((ord($chr) >= 192) && (ord($chr) <= 255)) {
$string[$i] = chr(ord($chr) - 64);
}
}
return $string;
}
I think that this approach may help. I used this in an old project and next is working example. PHP file is Windows-1251 encoded. If your text is in different encoding, you need to convert text using mb_convert_encoding() or iconv(), because ord() returns the binary value of the first byte of text as an unsigned integer between 0 and 255.
Test.php:
<?php
// Functions
function ConvertDosToWin($string) {
$chr = null;
for ($i = 0; $i<strlen($string); $i++) {
if ((ord($chr) >= 128) && (ord($chr) <= 191)) {
$string[$i] = chr(ord($chr) + 64);
}
}
return $string;
}
function ConvertWinToDos($string) {
$chr = null;
for ($i = 0; $i<strlen($string); $i++) {
$chr = $string[$i];
if ((ord($chr) >= 192) && (ord($chr) <= 255)) {
$string[$i] = chr(ord($chr) - 64);
}
}
return $string;
}
// Output
$text = 'АБВГДЕЖЗИЙ';
$text = ConvertWinToDos($text);
file_put_contents('dos.txt', $text);
?>

convert emoji to their hex code

I'm trying to detect the emoji that I get through e.g. a POST (the source ist not necessary).
As an example I'm using this emoji: ✊🏾 (I hope it's visible)
The code for it is U+270A U+1F3FE (I'm using http://unicode.org/emoji/charts/full-emoji-list.html for the codes)
Now I converted the emoji with json_encode and I get: \u270a\ud83c\udffe
Here the only part that is equal is 270a. \ud83c\udffe is not equal to U+1F3FE, not even if I add them together (1B83A)
How do I get from ✊🏾 to U+270A U+1F3FE with e.g. php?
Use mb_convert_encoding and convert from UTF-8 to UTF-32. Then do some additional formatting:
// Strips leading zeros
// And returns str in UPPERCASE letters with a U+ prefix
function format($str) {
$copy = false;
$len = strlen($str);
$res = '';
for ($i = 0; $i < $len; ++$i) {
$ch = $str[$i];
if (!$copy) {
if ($ch != '0') {
$copy = true;
}
// Prevent format("0") from returning ""
else if (($i + 1) == $len) {
$res = '0';
}
}
if ($copy) {
$res .= $ch;
}
}
return 'U+'.strtoupper($res);
}
function convert_emoji($emoji) {
// ✊🏾 --> 0000270a0001f3fe
$emoji = mb_convert_encoding($emoji, 'UTF-32', 'UTF-8');
$hex = bin2hex($emoji);
// Split the UTF-32 hex representation into chunks
$hex_len = strlen($hex) / 8;
$chunks = array();
for ($i = 0; $i < $hex_len; ++$i) {
$tmp = substr($hex, $i * 8, 8);
// Format each chunk
$chunks[$i] = format($tmp);
}
// Convert chunks array back to a string
return implode($chunks, ' ');
}
echo convert_emoji('✊🏾'); // U+270A U+1F3FE
Simple function, inspired by #d3L answer above
function emoji_to_unicode($emoji) {
$emoji = mb_convert_encoding($emoji, 'UTF-32', 'UTF-8');
$unicode = strtoupper(preg_replace("/^[0]+/","U+",bin2hex($emoji)));
return $unicode;
}
Exmaple
emoji_to_unicode("💵");//returns U+1F4B5
You can do like this, consider the emoji a normal character.
$emoji = "✊🏾";
$str = str_replace('"', "", json_encode($emoji, JSON_HEX_APOS));
$myInput = $str;
$myHexString = str_replace('\\u', '', $myInput);
$myBinString = hex2bin($myHexString);
print iconv("UTF-16BE", "UTF-8", $myBinString);

An encoding scheme to shorten a string of numbers that is url safe

I have a string that looks like this (contains numbers, periods and dashes):
1372137673.276886940002-19690324617-19694854617-18953258947
Since I only have numbers, periods and dashes, I would like to use an url-safe (only numbers and letters) encoding scheme to shorten it. I also need to be able to reverse the encoded string to its original form.
I have had a look at base64, but it increases the size of the string by a fair bit, which is not what I want.
I plan to have this implemented in PHP and Javascript.
Are there any existing schemes that can do this? My main motivation is to make the above string shorter and the result should be URL safe.
Convert the numbers into their binary form, then Base64 encode that.
One reasonable attempt would be:
break down the string into tokens separated by dashes and dots
convert each token to a higher base (36 is a base which you can convert to and from easily from both JS and PHP)
join the tokens back together -- both dashes and dots are valid in a URL
However, the "have to do this in JS also" requirement seems a bit suspect -- why does your client-side code have to extract information from URLs which are ultimately under the server's authority? In general URLs should be opaque and when that's not true alarm bells should start ringing.
To do it in javascript also, you need the help of http://phpjs.org/ :)
i think all php functions i used in this script is available there, like bcomp
You can tweak this code to get an even smaller string, bit busy now, if i got time, sure i will update this answer :)
<?php
/**
* This function will encode a larger number to small string
**/
function encode( $int = null ) {
$chars = 'kwn7uh2qifbj8te9vp64zxcmayrg50ds31';
$uid = '';
while( bccomp( $int, 0, 0) != 0 ) {
$rem = bcmod( $int, 34 );
$int = bcdiv( bcsub( $int, $rem, 0 ), 34, 0 );
$uid = $chars[$rem].$uid;
}
return $uid;
}
/**
* This function will decode a string encoded with above function to its original state
**/
function decode( $uid = null ) {
$chars = 'kwn7uh2qifbj8te9vp64zxcmayrg50ds31';
$id = '';
$len = strlen( $uid );
for( $i = $len - 1; $i >= 0; $i-- ) {
$value = strpos( $chars, $uid[$i] );
$id = bcadd( $id, bcmul( $value, bcpow( 34, ( $len - $i - 1 ) ) ) );
}
return $id;
}
/**
* Below function is only for your needs
**/
function int_to_str( $str = null, $decode = false ) {
//$len = array(); // reserved for further updates :)
$numbers1 = explode( "-", $str );
foreach( $numbers1 as &$num1 ) {
$func = ( $decode ) ? "decode" : "encode";
$num1 = implode( ".", array_map( $func, explode( ".", $num1 ) ) );
}
$numbers1 = implode( "-", $numbers1 );
return $numbers1;
}
// Encode your numbers to short strings
$str = int_to_str( "1372137673.276886940002-19690324617-19694854617-18953258947" );
// Decode your encoded string to its original state
$int = int_to_str( $str, true );
echo $str."<br />";
echo $int;
?>
Just because it was fun to do... it encodes the string on a custom base 64 keeping the separators intact:
function encode_token($digit) {
if ($digit < 10)
return (string) $digit;
if ($digit < 36)
return chr(ord('A') + ($digit - 10));
if ($digit < 62)
return chr(ord('a') + ($digit - 36));
if ($digit == 62) return ',';
return '+';
}
function encode_value($value) {
if (in_array($value, array('.', '-'))) return $value;
$int = (int) $value;
$encoded = '';
while($int) {
$encoded .= encode_token($int & 0x3F);
$int >>= 6;
}
return $encoded;
}
function encode($string) {
$values = preg_split(',([\.-]),', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
$encoded = '';
foreach($values as $value)
$encoded .= encode_value($value);
return $encoded;
}
function decode_token($token) {
if ($token <= '9') return (int) $token;
if ($token <= 'Z') return 10 + ord($token) - ord('A');
if ($token <= 'z') return 36 + ord($token) - ord('a');
if ($token == ',') return 62;
return 63;
}
function decode_value($value) {
if (in_array($value, array('.', '-'))) return $value;
$decoded = 0;
for($i = strlen($value) - 1;$i >= 0;$i--) {
$decoded <<= 6;
$decoded |= decode_token($value[$i]);
}
return $decoded;
}
function decode($string) {
$values = preg_split(',([\.-]),', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
$decoded = '';
foreach($values as $value)
$decoded .= decode_value($value);
return $decoded;
}
$string = '1372137673.276886940002-19690324617-19694854617-18953258947';
echo $string . PHP_EOL;
$encoded = encode($string);
echo $encoded . PHP_EOL;
$decoded = decode($encoded);
echo $decoded . PHP_EOL;

Encrypt/decrypt with XOR in PHP

I am studying encryption. And I got a problem like this:
After I XOR plaintext with a key, I get a crypt, "010e010c15061b4117030f54060e54040e0642181b17", as hex type. If I want to get plaintext from this crypt, what should I do in PHP?
I tried convert it to string/int and after that take them to XOR with the key (three letters). But it doesn't work.
This is the code:
function xor_this($string) {
// Let's define our key here
$key = 'fpt';
// Our plaintext/ciphertext
$text = $string;
// Our output text
$outText = '';
// Iterate through each character
for($i=0; $i<strlen($text); )
{
for($j=0; $j<strlen($key); $j++,$i++)
{
$outText .= ($text[$i] ^ $key[$j]);
//echo 'i=' . $i . ', ' . 'j=' . $j . ', ' . $outText{$i} . '<br />'; // For debugging
}
}
return $outText;
}
function strToHex($string)
{
$hex = '';
for ($i=0; $i < strlen($string); $i++)
{
$hex .= dechex(ord($string[$i]));
}
return $hex;
}
function hexToStr($hex)
{
$string = '';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
$a = "This is the test";
$b = xor_this($a);
echo xor_this($b), '-------------';
//
$c = strToHex($b);
$e = xor_this($c);
echo $e, '++++++++';
//
$d = hexToStr($c);
$f = xor_this($d);
echo $f, '=================';
And this is the result:
This is the test-------------
PHP Notice: Uninitialized string offset: 29 in C:\
Users\Administrator\Desktop\test.php on line 210 PHP Stack trace: PHP
1. {main}() C:\Users\Administrator\Desktop\test.php:0 PHP 2. xor_this() C:\Users\Administrator\Desktop\test.php:239
Notice: Uninitialized string offset: 29 in
C:\Users\Administrator\Desktop\test.p hp on line 210
Call Stack:
0.0005 674280 1. {main}() C:\Users\Administrator\Desktop\test.php:0
0.0022 674848 2. xor_this() C:\Users\Administrator\Desktop\test.php:23 9
UBE^A►WEAVA►WEAV#◄WEARAFWECWB++++++++
This is zs$fs☺=================
Why? The "UBE^A►WEAVA►WEAV#◄WEARAFWECWB++++++++" is the result, which I got trouble in my real work.
Try this:
function xor_this($string) {
// Let's define our key here
$key = ('magic_key');
// Our plaintext/ciphertext
$text = $string;
// Our output text
$outText = '';
// Iterate through each character
for($i=0; $i<strlen($text); )
{
for($j=0; ($j<strlen($key) && $i<strlen($text)); $j++,$i++)
{
$outText .= $text{$i} ^ $key{$j};
//echo 'i=' . $i . ', ' . 'j=' . $j . ', ' . $outText{$i} . '<br />'; // For debugging
}
}
return $outText;
}
Basically to revert text back (even numbers are in) you can use the same function:
$textToObfuscate = "Some Text 12345";
$obfuscatedText = xor_this($textToObfuscate);
$restoredText = xor_this($obfuscatedText);
Even easier:
function xor_string($string, $key) {
for($i = 0; $i < strlen($string); $i++)
$string[$i] = ($string[$i] ^ $key[$i % strlen($key)]);
return $string;
}
Based on the code above i created 2 functions to xor encode a JSON string using javascript and then decode it on server side using PHP.
!!! Important: If you will have characters different from ASCII(like Chinese, Cyrillic, Symbols...) in your JSON string, you
must either write some code in PHP or JS to fix how these
characters are encoded/decoded (ord/chr in PHP produce different
results in comparison with JS charCodeAt/String.fromCharCode) or
just base64_encode the JSON string and after that xor encode it.
Personally i use xor_string(base64_encode(JSON.stringify(object)), 'xor_key') in JS and on PHP side:
$json = json_decode(base64_decode(
xor_string(file_get_contents("php://input"), 'xor_key')
),
true);
PHP:
function xor_string($string, $key) {
$str_len = strlen($string);
$key_len = strlen($key);
for($i = 0; $i < $str_len; $i++) {
$string[$i] = $string[$i] ^ $key[$i % $key_len];
}
return $string;
}
Javascript:
function xor_string(string, key) {
string = string.split('');
key = key.split('');
var str_len = string.length;
var key_len = key.length;
var String_fromCharCode = String.fromCharCode;
for(var i = 0; i < str_len; i++) {
string[i] = String_fromCharCode(string[i].charCodeAt(0) ^ key[i % key_len].charCodeAt(0));
}
return string.join('');
}

Categories