SitePoint Sponsor

User Tag List

Results 1 to 11 of 11
  1. #1
    SitePoint Member
    Join Date
    Dec 2009
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Problems converting mcrypt cipher text to binary and back

    For a school project I'm developing a php based steganography class. As part of it I am encrypting the message to be hidden before encoding it into an image. So this means I must convert the resulting cipher text from mcrypt into binary. My problem is that when I try converting the binary back into the cipher text the result is different from the original cipher text. (The output binary looks strange to for that matter.) I'm assuming that the problem lies with the encoding used on the cipher text and the encoding used when converting back from binary are different but I have no idea where to start to fix that. You can see a live example at dev.hersha.me/str2bin.php and my code will be posted below.

    Code:
    <?php
    
    class phpSteg {
    
    	function bin2bstr($input) {
    		if (!is_string($input)) return null;
    		return pack('H*', base_convert($input, 2, 16));	
    	}
    
    	function bstr2bin($input) {
    		if (!is_string($input)) return null;
    		$value = unpack('H*', $input);
    		return base_convert($value[1], 16, 2);
    	}
    
    
    };
    
    $steg = new phpSteg();
    
    //echo $steg->bstr2bin('OMG') . "\n <br \>";
    //echo $steg->bin2bstr('010011110100110101000111') . "\n <br \>";
    $hash =  hash('md5',"OMGZWTF");
    echo $hash . "\n <br \>";
    $message = "OMG WTF BBQ";
    
    $text = $message;
    $key = $hash;
    
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB), MCRYPT_RAND);
    echo $iv . "\n <br \>";
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CFB, $iv);
    
    $binenc = $steg->bstr2bin($encrypted);
    
    $bstrenc = $steg->bin2bstr($binenc);
    
    
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $bstrenc, MCRYPT_MODE_CFB, $iv);
    echo "Cipher Text : " . $encrypted . "\n <br \>";
    
    echo "Cipher Text (binary) : " . $binenc . "\n <br \>";
    
    echo "Cipher Text (back from binary) : " . $bstrenc . "\n <br \>";
    
    echo "Decryption : " . $decrypted; // The quick brown fox jumps over the lazy dog
    
    ?>

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,705
    Mentioned
    102 Post(s)
    Tagged
    4 Thread(s)
    Start testing by encoding, and then immediately decoding the just-encoded string.

    If that doesn't work properly there's not much point in looking further, until that side of things works as expected.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Isn't there some trim tomfoolery required on decryption IIRC?
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,705
    Mentioned
    102 Post(s)
    Tagged
    4 Thread(s)
    Well, if you have a look at the http://php.net/manual/en/function.base-convert.php you will see a large warning saying that it may lose precision.

    If you look at the pack documentation page you will see that functions are provided to pack and unpack strings.

    Code php:
    <?php 
        public function unpack_str($str, $len) { 
            $tmp_arr = unpack("c".$len."chars", $str); 
            $out_str = ""; 
            foreach($tmp_arr as $v) { 
                if($v>0) { 
                    $out_str .= chr($v); 
                } 
            } 
     
            return $out_str; 
        } 
     
        public function pack_str($str, $len) {        
            $out_str = ""; 
            for($i=0; $i<$len; $i++) { 
                $out_str .= pack("c", ord(substr($str, $i, 1))); 
            } 
            return $out_str; 
        } 
    ?>

    Hopefully these resources will be useful for you to work further from.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  5. #5
    SitePoint Member
    Join Date
    Dec 2009
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the help pmw57 it was a precision issues with base_convert. I guess I should convert each character of the string to binary individually. That seems a slow and clunky way of doing it but whatever. But I don't think that's my only problem. If you look even though the binary of the cipher text is truncated the first few characters of the cipher text are changed from the original.

    Slowly getting there got my output binary right now need to get my converstion from binary right.

  6. #6
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,705
    Mentioned
    102 Post(s)
    Tagged
    4 Thread(s)
    My other computer (it's a Porsche) is running SpinRite right now, so when it's finished I'll see if I have some good info on cryptography scripts there.

    In the meantime, do you experience any conversion loss when using the pack_str and unpack_str functions?
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  7. #7
    SitePoint Member
    Join Date
    Dec 2009
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    *Sigh* Cant figure out how to break a long string of binary into an array of 8 bit chunks. Tried
    Code:
    preg_split('/[0-1]{8}/', $input, -1, PREG_SPLIT_NO_EMPTY);
    but no luck. Any ideas?

  8. #8
    SitePoint Member
    Join Date
    Dec 2009
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by pmw57 View Post
    My other computer (it's a Porsche) is running SpinRite right now, so when it's finished I'll see if I have some good info on cryptography scripts there.

    In the meantime, do you experience any conversion loss when using the pack_str and unpack_str functions?
    I figured out the cipher inconsistencies. It was that base_convert wasn't putting all of the leading zeros in for the special characters. using sprintf("%08d", $input) sorted it right out.

    Changed my binary conversion function to:
    Code:
     function bstr2bin($input) {
             if (!is_string($input)) return null;
             $bin = "";
             $array = preg_split('//', $input, -1, PREG_SPLIT_NO_EMPTY);
             foreach($array as $char) {
                     $hex = unpack('H*', $char);
                     echo $char . "->" . $hex[1] . "->".sprintf("%08d",base_convert($hex[1],16,2))."\n <br />";
                     $bin .= sprintf("%08d",base_convert($hex[1], 16, 2));
             }
             //$value = unpack('H*', $input);
             return $bin; //base_convert($value[1], 16, 2);
     }
    That got rid of the precision errors since its only converting one character at a time.

  9. #9
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    See str_split().
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  10. #10
    SitePoint Member
    Join Date
    Dec 2009
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by AnthonySterling View Post
    See str_split().
    Nice didn't notice that one in the documentation. Man base_convert has some serious issues with leading zeros when doing these conversions. Which is completely understandable since you don't need 0010 to get 2 all you need is 10 but its really annoying to debug.

  11. #11
    SitePoint Member
    Join Date
    Dec 2009
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Note to self use %02s instead of %02d with sprintf() when dealing with strings :P

    edit:
    Oh also all working now to make it all a nice pretty class.
    And get to work on the actually steganography part of the project.

    Here's the finished messy code if anyone is interested.
    Code:
    <?php
    
    class phpSteg {
    
            function bin2bstr($input) {
                    if (!is_string($input)) return null;
                    $hex = "";
                    $array = str_split($input, 8);
                    //print_r ($array);
                    foreach($array as $bin) {
                            echo $bin . "->".sprintf("%02s",base_convert($bin, 2, 16))."\n <br />";
                            $string .= pack('H*', sprintf("%02s", base_convert($bin, 2, 16)));
                    }
                    return $string; //pack('H*', base_convert($input, 2, 16));
            }
    
            function bstr2bin($input) {
                    if (!is_string($input)) return null;
                    $bin = "";
                    $array = preg_split('//', $input, -1, PREG_SPLIT_NO_EMPTY);
                    foreach($array as $char) {
                            $hex = unpack('H*', $char);
                            echo $char . "->" . $hex[1] . "->".sprintf("%08s",base_convert($hex[1],16,2))."\n <br />";
                            $bin .= sprintf("%08s",base_convert($hex[1], 16, 2));
                    }
                    //$value = unpack('H*', $input);
                    return $bin; //base_convert($value[1], 16, 2);
            }
    
    
    };
    
    
    $steg = new phpSteg();
    
    //echo $steg->bstr2bin('OMG') . "\n <br \>";
    //echo $steg->bin2bstr('010011110100110101000111') . "\n <br \>";
    $hash =  hash('md5',"OMGZWTF");
    $message = "OMG WTF BBQ";
    
    $text = $message;
    $key = $hash;
    
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB), MCRYPT_RAND);
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CFB, $iv);
    $binenc = $steg->bstr2bin($encrypted);
    $bstrenc = $steg->bin2bstr($binenc);
    $binmsg = $steg->bstr2bin($message);
    $bstrmsg = $steg->bin2bstr($binmsg);
    $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CFB, $iv));
    $decryptedbin = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $bstrenc, MCRYPT_MODE_CFB, $iv));
    
    
    echo "Message : " . $message . "\n <br />";
    echo "Simple String to Binary and Back\n <br />";
    echo "Binary Message : " . $binmsg . "\n <br />";
    echo "Back to String : " . $bstrmsg . "\n <br />";
    echo "Encryption no binary conversion\n <br />";
    echo "Key : " . $key . "\n <br />";
    echo "IV : " . $iv . "\n <br />";
    echo "Cipher Text : " . $encrypted . "\n <br />";
    echo "Decryption : " . $decrypted . "\n <br />";
    echo "Encryption with binary conversion\n <br />";
    echo "Cipher Text (binary) : " . $binenc . "\n <br />";
    echo "Cipher Text (back from binary) : " . $bstrenc . "\n <br />";
    echo "Decryption : " . $decryptedbin; // The quick brown fox jumps over the lazy dog
    
    
    ?>


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •