71

I got the problem when convert between this 2 type in PHP. This is the code I searched in google

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

I check it and found out this when I use XOR to encrypt.

I have the string "this is the test", after XOR with a key, I have the result in string ↕↑↔§P↔§P ♫§T↕§↕. After that, I tried to convert it to hex by function strToHex() and I got these 12181d15501d15500e15541215712. Then, I tested with the function hexToStr() and I have ↕↑↔§P↔§P♫§T↕§q. So, what should I do to solve this problem? Why does it wrong when I convert this 2 style value?

Arturs
  • 1,258
  • 5
  • 21
  • 28
JoeNguyen
  • 1,049
  • 2
  • 11
  • 15
  • 10
    You know there are `hex2bin()` and `bin2hex()` in PHP? – जलजनक Feb 03 '13 at 17:00
  • *strToHex* returns a *string* of hex - so if you XOR that directly with the `^` operator, that won't give any good result. Maybe you could give *strToHex* another param being the number you want to XOR with, and XOR directly inside that function: `$hex .= dechex(ord($string[$i]) ^ $MYKEYBYTE);` – Déjà vu Feb 03 '13 at 17:02
  • I thought that the problem is at hexToStr() function. Because when it convert to string, it pass the space or some special character, and make the problem – JoeNguyen Feb 03 '13 at 17:16
  • I tried hex2bin() and bin2hex(). It's really good and solve this. but in real situation, It doesn't. It just be right if I call bin2hex() function after encrypt by XOR the plaintext with key. But in a real situation, we usually use strToHex() after XOR , so when we decrypt by XOR the Crypt with KEY to get the plaintext, we call the hexToStr() It will get wrong result. – JoeNguyen Feb 03 '13 at 17:22

8 Answers8

137

For people that end up here and are just looking for the hex representation of a (binary) string.

bin2hex("that's all you need");
# 74686174277320616c6c20796f75206e656564

hex2bin('74686174277320616c6c20796f75206e656564');
# that's all you need

Doc: bin2hex, hex2bin.

Philippe Gerber
  • 17,457
  • 6
  • 45
  • 40
  • what about [2's compliment](https://stackoverflow.com/questions/61952913/php-string-to-hex-with2s-complement)? – Moeez May 22 '20 at 15:33
  • I made a gist that incorporated this. A simple hex dumper function for PHP: https://gist.github.com/hopeseekr/9964a9f12428dd220c3dd29a9943ce65 – Theodore R. Smith Jan 21 '23 at 20:00
56

For any char with ord($char) < 16 you get a HEX back which is only 1 long. You forgot to add 0 padding.

This should solve it:

<?php
function strToHex($string){
    $hex = '';
    for ($i=0; $i<strlen($string); $i++){
        $ord = ord($string[$i]);
        $hexCode = dechex($ord);
        $hex .= substr('0'.$hexCode, -2);
    }
    return strToUpper($hex);
}
function hexToStr($hex){
    $string='';
    for ($i=0; $i < strlen($hex)-1; $i+=2){
        $string .= chr(hexdec($hex[$i].$hex[$i+1]));
    }
    return $string;
}


// Tests
header('Content-Type: text/plain');
function test($expected, $actual, $success) {
    if($expected !== $actual) {
        echo "Expected: '$expected'\n";
        echo "Actual:   '$actual'\n";
        echo "\n";
        $success = false;
    }
    return $success;
}

$success = true;
$success = test('00', strToHex(hexToStr('00')), $success);
$success = test('FF', strToHex(hexToStr('FF')), $success);
$success = test('000102FF', strToHex(hexToStr('000102FF')), $success);
$success = test('↕↑↔§P↔§P ♫§T↕§↕', hexToStr(strToHex('↕↑↔§P↔§P ♫§T↕§↕')), $success);

echo $success ? "Success" : "\nFailed";
boomla
  • 661
  • 5
  • 5
37

PHP :

string to hex:

implode(unpack("H*", $string));

hex to string:

pack("H*", $hex);
Sos.
  • 914
  • 10
  • 14
13

Here's what I use:

function strhex($string) {
  $hexstr = unpack('H*', $string);
  return array_shift($hexstr);
}
Bill Shirley
  • 131
  • 1
  • 2
  • with [2's compliment](https://stackoverflow.com/questions/61952913/php-string-to-hex-with2s-complement)? – Moeez May 22 '20 at 13:33
1
function hexToStr($hex){
    // Remove spaces if the hex string has spaces
    $hex = str_replace(' ', '', $hex);
    return hex2bin($hex);
}
// Test it 
$hex    = "53 44 43 30 30 32 30 30 30 31 37 33";
echo hexToStr($hex); // SDC002000173

/**
 * Test Hex To string with PHP UNIT
 * @param  string $value
 * @return 
 */
public function testHexToString()
{
    $string = 'SDC002000173';
    $hex    = "53 44 43 30 30 32 30 30 30 31 37 33";
    $result = hexToStr($hex);

    $this->assertEquals($result,$string);
}
Kamaro
  • 955
  • 1
  • 10
  • 11
1

Using @bill-shirley answer with a little addition

function str_to_hex($string) {
$hexstr = unpack('H*', $string);
return array_shift($hexstr);
}
function hex_to_str($string) {
return hex2bin("$string");
}

Usage:

  $str = "Go placidly amidst the noise";
  $hexstr = str_to_hex($str);// 476f20706c616369646c7920616d6964737420746865206e6f697365
  $strstr = hex_to_str($str);// Go placidly amidst the noise
PeterT
  • 49
  • 7
  • Why not convert the accented characters first – PeterT May 20 '20 at 10:48
  • Any particular approach recommended? `mb_convert_encoding`? This is outside the original scope, but the hex information will be converted back into string in MSSQL, which doesn't have a decoding function. – ner0 May 20 '20 at 14:05
0

I only have half the answer, but I hope that it is useful as it adds unicode (utf-8) support

    /**
     * hexadecimal to unicode character
     * @param  string  $hex
     * @return string
     */
    function hex2uni($hex) { 
      $dec = hexdec($hex);
        if($dec < 128) {
            return chr($dec);
        }
        if($dec < 2048) {
            $utf = chr(192 + (($dec - ($dec % 64)) / 64));
        } else {
            $utf = chr(224 + (($dec - ($dec % 4096)) / 4096));
            $utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64));
        }
        return $utf . chr(128 + ($dec % 64));
    }

To string

    var_dump(hex2uni('e641'));

Based on: http://www.php.net/manual/en/function.chr.php#Hcom55978

Timo Huovinen
  • 53,325
  • 33
  • 152
  • 143
0

You can try the following code to convert the image to hex string

<?php
$image = 'sample.bmp';
$file = fopen($image, 'r') or die("Could not open $image");
while ($file && !feof($file)){
$chunk = fread($file, 1000000); # You can affect performance altering
this number. YMMV.
# This loop will be dog-slow, almost for sure...
# You could snag two or three bytes and shift/add them,
# but at 4 bytes, you violate the 7fffffff limit of dechex...
# You could maybe write a better dechex that would accept multiple bytes
# and use substr... Maybe.
for ($byte = 0; $byte < strlen($chunk); $byte++)){
echo dechex(ord($chunk[$byte]));
}
}
?>