Page 1 of 1

XTEA Encryption/Decryption

Posted: Thu May 03, 2012 5:59 pm
by cesarcesar
I am trying to decrypt a code encrypted with XTEA. I have been using a script found here, http://goo.gl/xCpgs and it works within its own encrypt/decrypt example. The problem is that it will not decrypt a code given to me by my client. In the code examples description it says the "key" is 16 characters, but the key I have from my client is 32 characters so I think this may be part of the problem, but I cannot find out in the code how to make it work with a 32 char key (if that is even the issue).

Below is the class from the link above and below that are sample encrypt and decrypt strings. If anyone can provide help or a better solution, it is greatly appreciated. My guess is that it is only allowing 16 of my 32 char key. I tried to use a 32 char key, but the code still seemed to only want 16. Help!

I also read something about XTEA only working within the same code language each side of the crypt was made. Can anyone validate this?

Code: Select all

<?php
/* PHP Implementation of XTEA (www.php-einfach.de)
*
* XTEA was designed in 1997 by David Wheeler and Roger Needham
* of the Cambridge Computer Laboratory.
* It is not subject to any patents.
*
* It is a 64-bit Feistel cipher, consisting of 64 rounds.
* XTA has a key length of 128 bits.
*
*
* ***********************
* Diese Implementierung darf frei verwendet werden, der Autor uebernimmt keine
* Haftung fuer die Richtigkeit, Fehlerfreiheit oder die Funktionsfaehigkeit dieses Scripts.
* Benutzung auf eigene Gefahr.
*
* Ueber einen Link auf www.php-einfach.de wuerden wir uns freuen.
*
* ************************
* Usage:
*
* include("xtea.class.php");
*
* $xtea = new XTEA("secret Key");
* $cipher = $xtea->Encrypt("Hello World"); //Encrypts 'Hello World'
* $plain = $xtea->Decrypt($cipher); //Decrypts the cipher text
*
* echo $plain;
*
*/

class XTEA {

   //Private
	var $key;

	// CBC or ECB Mode
	// normaly, CBC Mode would be the right choice
	var $cbc = 1;

   function XTEA($key) {
      $this->key_setup($key);
   }

   //encrypt
   function encrypt($text) {
      $n = strlen($text);
      if($n%8 != 0) $lng = ($n+(8-($n%8)));
      else $lng = 0;

      $text = str_pad($text, $lng, ' ');
      $text = $this->_str2long($text);

      //Initialization vector: IV
      if($this->cbc == 1) {
         $cipher[0][0] = time();
         $cipher[0][1] = (double)microtime()*1000000;
      }

      $a = 1;
      for($i = 0; $i<count($text); $i+=2) {
         if($this->cbc == 1) {
            //$text with last ciphertext XOR
            //$text is XORed with the previous ciphertext
            $text[$i] ^= $cipher[$a-1][0];
            $text[$i+1] ^= $cipher[$a-1][1];
         }

         $cipher[] = $this->block_encrypt($text[$i],$text[$i+1]);
         $a++;
      }

      $output = "";
      for($i = 0; $i<count($cipher); $i++) {
         $output .= $this->_long2str($cipher[$i][0]);
         $output .= $this->_long2str($cipher[$i][1]);
      }

      return base64_encode($output);
   }




   //decipher
   function decrypt($text) {
      $plain = array();
      $cipher = $this->_str2long(base64_decode($text));

      if($this->cbc == 1)
         $i = 2; //Message start at second block
      else
         $i = 0; //Message start at first block

      for($i; $i<count($cipher); $i+=2) {
         $return = $this->block_decrypt($cipher[$i],$cipher[$i+1]);

         //Xor Linkage of $return and ciphertext from the last two blocks or sections
         //XORed $return with the previous ciphertext
         if($this->cbc == 1)
            $plain[] = array($return[0]^$cipher[$i-2],$return[1]^$cipher[$i-1]);
         else          //EBC Mode
            $plain[] = $return;
      }

      for($i = 0; $i<count($plain); $i++) {
         $output .= $this->_long2str($plain[$i][0]);
         $output .= $this->_long2str($plain[$i][1]);
      }

      return $output;
   }

   //Prepare the key to decrypt ver / front
   function key_setup($key) {
		if(is_array($key))
      		$this->key = $key;
		else if(isset($key) && !empty($key))
			$this->key = $this->_str2long(str_pad($key, 16, $key));
		else
			$this->key = array(0,0,0,0);
   }


	//Performs a benchmark
	function benchmark($length=1000) {
		//1000 Byte String
		$string = str_pad("", $length, "text");


		//Key-Setup
		$start1 = time() + (double)microtime();
		$xtea = new XTEA("key");
		$end1 = time() + (double)microtime();

		//Encryption
		$start2 = time() + (double)microtime();
		$xtea->Encrypt($string);
		$end2 = time() + (double)microtime();



		echo "Encrypting ".$length." bytes: ".round($end2-$start2,2)." seconds (".round($length/($end2-$start2),2)." bytes/second)<br>";


	}

	//verify the correct implementation of the blowfish algorithm
	function check_implementation() {

		$xtea = new XTEA("");
		$vectors = array(
			array(array(0x00000000,0x00000000,0x00000000,0x00000000), array(0x41414141,0x41414141), array(0xed23375a,0x821a8c2d)),
			array(array(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f), array(0x41424344,0x45464748), array(0x497df3d0,0x72612cb5)),

		);

		//Correct implementation?
		$correct = true;
		//Test vectors, see http://www.schneier.com/code/vectors.txt
		foreach($vectors AS $vector) {
      	$key = $vector[0];
			$plain = $vector[1];
			$cipher = $vector[2];

			$xtea->key_setup($key);
			$return = $xtea->block_encrypt($vector[1][0],$vector[1][1]);

			if((int)$return[0] != (int)$cipher[0] || (int)$return[1] != (int)$cipher[1])
				$correct = false;

		}

		return $correct;

	}



	/***********************************
			Some internal functions
	 ***********************************/
   function block_encrypt($y, $z) {
	   $sum=0;
	   $delta=0x9e3779b9;


	   /* start cycle */
	   for ($i=0; $i<32; $i++)
	      {
	      $y      = $this->_add($y,
	                        $this->_add($z << 4 ^ $this->_rshift($z, 5), $z) ^
	                            $this-> _add($sum, $this->key[$sum & 3]));

	      $sum    = $this->_add($sum, $delta);

	      $z      = $this->_add($z,
	                        $this->_add($y << 4 ^ $this->_rshift($y, 5), $y) ^
	                              $this->_add($sum, $this->key[$this->_rshift($sum, 11) & 3]));

	      }

	   /* end cycle */
	   $v[0]=$y;
	   $v[1]=$z;

	   return array($y,$z);

   }

   function block_decrypt($y, $z) {
	   $delta=0x9e3779b9;
	   $sum=0xC6EF3720;
	   $n=32;

	   /* start cycle */
	   for ($i=0; $i<32; $i++)
	      {
	      $z      = $this->_add($z,
	                	-($this->_add($y << 4 ^ $this->_rshift($y, 5), $y) ^
	                  	$this->_add($sum, $this->key[$this->_rshift($sum, 11) & 3])));
	      $sum    = $this->_add($sum, -$delta);
	      $y      = $this->_add($y,
	                          -($this->_add($z << 4 ^ $this->_rshift($z, 5), $z) ^
	                                    $this->_add($sum, $this->key[$sum & 3])));

	      }
	   /* end cycle */

	   return array($y,$z);
    }




  	function _rshift($integer, $n) {
        // convert to 32 bits
        if (0xffffffff < $integer || -0xffffffff > $integer) {
            $integer = fmod($integer, 0xffffffff + 1);
        }

        // convert to unsigned integer
        if (0x7fffffff < $integer) {
            $integer -= 0xffffffff + 1.0;
        } elseif (-0x80000000 > $integer) {
            $integer += 0xffffffff + 1.0;
        }

        // do right shift
        if (0 > $integer) {
            $integer &= 0x7fffffff;                     // remove sign bit before shift
            $integer >>= $n;                            // right shift
            $integer |= 1 << (31 - $n);                 // set shifted sign bit
        } else {
            $integer >>= $n;                            // use normal right shift
        }

        return $integer;
    }


    function _add($i1, $i2) {
        $result = 0.0;

        foreach (func_get_args() as $value) {
            // remove sign if necessary
            if (0.0 > $value) {
                $value -= 1.0 + 0xffffffff;
            }

            $result += $value;
        }

        // convert to 32 bits
        if (0xffffffff < $result || -0xffffffff > $result) {
            $result = fmod($result, 0xffffffff + 1);
        }

        // convert to signed integer
        if (0x7fffffff < $result) {
            $result -= 0xffffffff + 1.0;
        } elseif (-0x80000000 > $result) {
            $result += 0xffffffff + 1.0;
        }

        return $result;
    }


   //Einen Text in Longzahlen umwandeln
   //Covert a string into longinteger
   function _str2long($data) {
       $n = strlen($data);
       $tmp = unpack('N*', $data);
       $data_long = array();
       $j = 0;

       foreach ($tmp as $value) $data_long[$j++] = $value;
       return $data_long;
   }

   //Longzahlen in Text umwandeln
   //Convert a longinteger into a string
   function _long2str($l){
       return pack('N', $l);
   }

}
?>

Re: XTEA Encryption/Decryption

Posted: Fri May 04, 2012 1:43 am
by cesarcesar
Thanks to @xyph for the help. I think I'm almost there. I can get the encrypted string to change to base64 and it "looks" correct, but it still will not decrypt. Could I still be having an issue with the key string of "28d75A09ec63cxvxve870fad25e79b8c"? How do I change this into 16 characters? Below is my current code.

Code: Select all

$ascii_string = '';
foreach( str_split($text,2) as $chunk ){ $ascii_string .= chr(hexdec($chunk)); }
$base64_string = base64_encode($ascii_string);

$xtea = new XTEA('28d75A09ec63cxxxxe870fad25e79b8c');
$output =$xtea->Decrypt($base64_string);


Re: XTEA Encryption/Decryption

Posted: Fri May 04, 2012 8:30 am
by x_mutatis_mutandis_x
cesarcesar wrote:Thanks to @xyph for the help. I think I'm almost there. I can get the encrypted string to change to base64 and it "looks" correct, but it still will not decrypt. Could I still be having an issue with the key string of "28d75A09ec63cxvxve870fad25e79b8c"? How do I change this into 16 characters? Below is my current code.

Code: Select all

$ascii_string = '';
foreach( str_split($text,2) as $chunk ){ $ascii_string .= chr(hexdec($chunk)); }
$base64_string = base64_encode($ascii_string);

$xtea = new XTEA('28d75A09ec63c32b1e870fad25e79b8c');
$output =$xtea->Decrypt($base64_string);

A simple test works fine for me when I use XTEA::encrypt() for a srting with the 32 char key "28d75A09ec63c32b1e870fad25e79b8c", and XTEA::decrypt() to get back the original string (see below)

Code: Select all

$ascii_string = 'Hello';
echo "Original: $ascii_string\n";

$xtea = new XTEA('28d75A09ec63c32b1e870fad25e79b8c');
$output = $xtea->encrypt($ascii_string);
echo "Encrypted: $output\n";
echo "Decrypted: " . $xtea->decrypt($output);
And the output:
Original: Hello
Encrypted: T6PZyQAN5m8cTRl1mk8rbw==
Decrypted: Hello
Same code with a longer string:
Original: This is a very large text as I'm trying to test this encryption-decryption class with a very long string. So lets hope to GOD it works!!!@####
Encrypted: T6Pa7QAN263ebf5UI/0DSYbIcES8x8n1cIRJhEn2qVOOzcN4HtSiywViKdUQ1baqJUE8P5hqj16AboQ2+m2bHRuNdsZIUBGeE+4AAoiBwdhC4EaqOCzjzYElF5JTECIDlxT5/cSS6Gim0ZuuGaeGNWpXLe/smiNKhSaX7Ojf4zxqIUR4F13dOS5xLPiPMd55sLgE1VWNtEc=
Decrypted: This is a very large text as I'm trying to test this encryption-decryption class with a very long string. So lets hope to GOD it works!!!@####

Re: XTEA Encryption/Decryption

Posted: Sun May 06, 2012 5:10 pm
by cesarcesar
crap. still lost and its not decrypting. This is where I'm at.

Code: Select all

// convert HEX key to ASCII (working)
$ascii_key = hexToAscii('28d75A09ec63c32b1e870fad25e79b8c');
// (×Z	ìcÃ+‡*%盌


// convert XTEA encrypted HEX value to ASCII (working)
$ascii = hexToAscii($text);
// °ŸO´jÔAŽQäàœlª:6b½ÂدjÓðgÊ9#¨QÖ9@'XÕ}IÌ}ïŒ{![KP¢Èÿ—¢žî¥õu÷¨b‹Û9wgGâDþ[iØÍc¤Ü€S`ðËK‰L¨kV萙µGþ£©ÿmnLd¶Ê{+3@Fçèdj0/co£IÃîøÄ\:tCU)+1ª"Í:Eçr-po1ë×ΰ¶í[Á`ëÖ/®6èEç…| 40WŠ<=묀íbÈß )*[_©‘Å


// base64 encode ASCII value (working)
$base64_string = base64_encode($ascii);
// sJ9PtGrUQY5R5OCcbBGqOjZij70cwtivatPwFGfKORAjHKhR1jlAJ1jVfUnMfRLvjHshW0tQosj/l6Ke7qX1dfeoYovbOXdnR+JE/ltp2M1jpNyAU2Dwy0uJTKhrVuiQmbVH/qONFqkCA/9tbkxktsp7KzMYQEbn6GRqMC9jb6NJw+74xFw6dEMDAlUpKzGqIs06RedyLXBvMevXzrC27VvBYOsc1i+uNuhF54V8nSA0MFeKPD3rrICPC+1iyN8gKSpbFF+pkcU=


// decrypt XTEA encrypted value (FAILING)
$xtea = new XTEA($ascii_key);
$output = $xtea->Decrypt($base64_string);
echo  nl2br(htmlentities(stripslashes($output)));
// |üÑ61}¢BhžB`û”¢od¼4HÁÉ]sZÐ’=8ÿ€SúóØrh©òÌ$0nÄ'Ãw¾çhüÌ£TÆñwp}±Ì4-8EŸšl³¯0SéS¥åFŒ|Ù}I„ÚY;L(b‹-iSÖcž4!컁fôò¤”»ÑÙ[y4má—O"˜Eí&T‡Á'¸
œ7}ÎCVqòWC¢Þ_Ï&ƒšWn¨ðÏ}à›°„¢õ鍊ŽPÁÈ
As you can see the last result is not a legible string. It should look like a bunch of parameters after a url. HELP!!

Re: XTEA Encryption/Decryption

Posted: Mon May 07, 2012 9:03 am
by x_mutatis_mutandis_x
'28d75A09ec63c32b1e870fad25e79b8c' is an ASCII value, not a hex value. Hex values are represented as 0xAE, 0x2A etc. When you say your client is giving you the encrypted value, what do you mean by "client"? Who is the "client"? If the client is a third party service, then read their documentation about what encryption they are using to send you the "text". What is the value of $text?

Re: XTEA Encryption/Decryption

Posted: Mon May 07, 2012 9:36 am
by cesarcesar
Well that's good do know. The problem is no one has been able to get me a solid answer on what is going on so I just taking any suggestions I can get and trying them out. I have removed the hex conversion on the key, but the decrypt still looks like my last post.

Re: XTEA Encryption/Decryption

Posted: Mon May 07, 2012 11:25 am
by x_mutatis_mutandis_x

Code: Select all

$ascii_key = '28d75A09ec63c32b1e870fad25e79b8c';
$xtea = new XTEA($ascii_key);
$output = $xtea->Decrypt($text);
//let me know what is the value of $output

Re: XTEA Encryption/Decryption

Posted: Mon May 07, 2012 1:53 pm
by cesarcesar
Trying to decode

Code: Select all

B09F4FB46AD4418E51E4E09C6C11AA3A36628FBD1CC2D8AF6AD3F01467CA3910231CA851D639402758D57D49CC7D12EF8C7B215B4B50A2C8FF97A29EEEA5F575F7A8628BDB39776747E244FE5B69D8CD63A4DC805360F0CB4B894CA86B56E89099B547FEA38D16A90203FF6D6E4C64B6CA7B2B33184046E7E8646A302F636FA349C3EEF8C45C3A7443030255292B31AA22CD3A45E7722D706F31EBD7CEB0B6ED5BC160EB1CD62FAE36E845E7857C9D203430578A3C3DEBAC808F0BED62C8DF20292A5B145FA991C5
Results in

Code: Select all

¿ië%+°­+cå› ½dÌ#&÷¶Ôé}(8Ð×%š÷lì»ë‡¿ûRê@a
‘$¾X'e¢'´3ZÚšL#fž³*¾®¾C¿EK¬#^ïAØ¿">ÈF+iöO)Dº4î3P§®ep aØ"(;ZžFÆ_LŽi~çæ*ä|ˆÛÎLf¤Õeî¸ÍPL²ÃQé/D’þh#䃵byÀ¢™„þ-ë¿Ð’>R¤OêM¨•¥4ŸŽÌ=‹‰Ÿ_»A>˜ÍërBξ2"æx5½Îƒ,
|?HÃë»Q.æ¦=óOº‰çÌÌ*¹Í†ª«TR´Ö9BÕPtÁÙKË&‘Kªsó”{‡p“›é(=

Re: XTEA Encryption/Decryption

Posted: Mon May 07, 2012 2:45 pm
by x_mutatis_mutandis_x
cesarcesar wrote:Trying to decode

Code: Select all

B09F4FB46AD4418E51E4E09C6C11AA3A36628FBD1CC2D8AF6AD3F01467CA3910231CA851D639402758D57D49CC7D12EF8C7B215B4B50A2C8FF97A29EEEA5F575F7A8628BDB39776747E244FE5B69D8CD63A4DC805360F0CB4B894CA86B56E89099B547FEA38D16A90203FF6D6E4C64B6CA7B2B33184046E7E8646A302F636FA349C3EEF8C45C3A7443030255292B31AA22CD3A45E7722D706F31EBD7CEB0B6ED5BC160EB1CD62FAE36E845E7857C9D203430578A3C3DEBAC808F0BED62C8DF20292A5B145FA991C5
Looks like that's a hex value being sent to you, the key on the other hand is 32 char string value. Are you sure this has been encrypted with the algorithm you are using to decrypt it?