By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
438,521 Members | 1,476 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 438,521 IT Pros & Developers. It's quick & easy.

XTEA Encryption/Decryption

100+
P: 162
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?

Expand|Select|Wrap|Line Numbers
  1. <?php
  2. /* PHP Implementation of XTEA (www.php-einfach.de)
  3. *
  4. * XTEA was designed in 1997 by David Wheeler and Roger Needham
  5. * of the Cambridge Computer Laboratory.
  6. * It is not subject to any patents.
  7. *
  8. * It is a 64-bit Feistel cipher, consisting of 64 rounds.
  9. * XTA has a key length of 128 bits.
  10. *
  11. *
  12. * ***********************
  13. * Diese Implementierung darf frei verwendet werden, der Autor uebernimmt keine
  14. * Haftung fuer die Richtigkeit, Fehlerfreiheit oder die Funktionsfaehigkeit dieses Scripts.
  15. * Benutzung auf eigene Gefahr.
  16. *
  17. * Ueber einen Link auf www.php-einfach.de wuerden wir uns freuen.
  18. *
  19. * ************************
  20. * Usage:
  21. *
  22. * include("xtea.class.php");
  23. *
  24. * $xtea = new XTEA("secret Key");
  25. * $cipher = $xtea->Encrypt("Hello World"); //Encrypts 'Hello World'
  26. * $plain = $xtea->Decrypt($cipher); //Decrypts the cipher text
  27. *
  28. * echo $plain;
  29. *
  30. */
  31.  
  32. class XTEA {
  33.  
  34.    //Private
  35.     var $key;
  36.  
  37.     // CBC or ECB Mode
  38.     // normaly, CBC Mode would be the right choice
  39.     var $cbc = 1;
  40.  
  41.    function XTEA($key) {
  42.       $this->key_setup($key);
  43.    }
  44.  
  45.    //encrypt
  46.    function encrypt($text) {
  47.       $n = strlen($text);
  48.       if($n%8 != 0) $lng = ($n+(8-($n%8)));
  49.       else $lng = 0;
  50.  
  51.       $text = str_pad($text, $lng, ' ');
  52.       $text = $this->_str2long($text);
  53.  
  54.       //Initialization vector: IV
  55.       if($this->cbc == 1) {
  56.          $cipher[0][0] = time();
  57.          $cipher[0][1] = (double)microtime()*1000000;
  58.       }
  59.  
  60.       $a = 1;
  61.       for($i = 0; $i<count($text); $i+=2) {
  62.          if($this->cbc == 1) {
  63.             //$text with last ciphertext XOR
  64.             //$text is XORed with the previous ciphertext
  65.             $text[$i] ^= $cipher[$a-1][0];
  66.             $text[$i+1] ^= $cipher[$a-1][1];
  67.          }
  68.  
  69.          $cipher[] = $this->block_encrypt($text[$i],$text[$i+1]);
  70.          $a++;
  71.       }
  72.  
  73.       $output = "";
  74.       for($i = 0; $i<count($cipher); $i++) {
  75.          $output .= $this->_long2str($cipher[$i][0]);
  76.          $output .= $this->_long2str($cipher[$i][1]);
  77.       }
  78.  
  79.       return base64_encode($output);
  80.    }
  81.  
  82.  
  83.  
  84.  
  85.    //decipher
  86.    function decrypt($text) {
  87.       $plain = array();
  88.       $cipher = $this->_str2long(base64_decode($text));
  89.  
  90.       if($this->cbc == 1)
  91.          $i = 2; //Message start at second block
  92.       else
  93.          $i = 0; //Message start at first block
  94.  
  95.       for($i; $i<count($cipher); $i+=2) {
  96.          $return = $this->block_decrypt($cipher[$i],$cipher[$i+1]);
  97.  
  98.          //Xor Linkage of $return and ciphertext from the last two blocks or sections
  99.          //XORed $return with the previous ciphertext
  100.          if($this->cbc == 1)
  101.             $plain[] = array($return[0]^$cipher[$i-2],$return[1]^$cipher[$i-1]);
  102.          else          //EBC Mode
  103.             $plain[] = $return;
  104.       }
  105.  
  106.       for($i = 0; $i<count($plain); $i++) {
  107.          $output .= $this->_long2str($plain[$i][0]);
  108.          $output .= $this->_long2str($plain[$i][1]);
  109.       }
  110.  
  111.       return $output;
  112.    }
  113.  
  114.    //Prepare the key to decrypt ver / front
  115.    function key_setup($key) {
  116.         if(is_array($key))
  117.               $this->key = $key;
  118.         else if(isset($key) && !empty($key))
  119.             $this->key = $this->_str2long(str_pad($key, 16, $key));
  120.         else
  121.             $this->key = array(0,0,0,0);
  122.    }
  123.  
  124.  
  125.     //Performs a benchmark
  126.     function benchmark($length=1000) {
  127.         //1000 Byte String
  128.         $string = str_pad("", $length, "text");
  129.  
  130.  
  131.         //Key-Setup
  132.         $start1 = time() + (double)microtime();
  133.         $xtea = new XTEA("key");
  134.         $end1 = time() + (double)microtime();
  135.  
  136.         //Encryption
  137.         $start2 = time() + (double)microtime();
  138.         $xtea->Encrypt($string);
  139.         $end2 = time() + (double)microtime();
  140.  
  141.  
  142.  
  143.         echo "Encrypting ".$length." bytes: ".round($end2-$start2,2)." seconds (".round($length/($end2-$start2),2)." bytes/second)<br>";
  144.  
  145.  
  146.     }
  147.  
  148.     //verify the correct implementation of the blowfish algorithm
  149.     function check_implementation() {
  150.  
  151.         $xtea = new XTEA("");
  152.         $vectors = array(
  153.             array(array(0x00000000,0x00000000,0x00000000,0x00000000), array(0x41414141,0x41414141), array(0xed23375a,0x821a8c2d)),
  154.             array(array(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f), array(0x41424344,0x45464748), array(0x497df3d0,0x72612cb5)),
  155.  
  156.         );
  157.  
  158.         //Correct implementation?
  159.         $correct = true;
  160.         //Test vectors, see http://www.schneier.com/code/vectors.txt
  161.         foreach($vectors AS $vector) {
  162.           $key = $vector[0];
  163.             $plain = $vector[1];
  164.             $cipher = $vector[2];
  165.  
  166.             $xtea->key_setup($key);
  167.             $return = $xtea->block_encrypt($vector[1][0],$vector[1][1]);
  168.  
  169.             if((int)$return[0] != (int)$cipher[0] || (int)$return[1] != (int)$cipher[1])
  170.                 $correct = false;
  171.  
  172.         }
  173.  
  174.         return $correct;
  175.  
  176.     }
  177.  
  178.  
  179.  
  180.     /***********************************
  181.             Some internal functions
  182.      ***********************************/
  183.    function block_encrypt($y, $z) {
  184.        $sum=0;
  185.        $delta=0x9e3779b9;
  186.  
  187.  
  188.        /* start cycle */
  189.        for ($i=0; $i<32; $i++)
  190.           {
  191.           $y      = $this->_add($y,
  192.                             $this->_add($z << 4 ^ $this->_rshift($z, 5), $z) ^
  193.                                 $this-> _add($sum, $this->key[$sum & 3]));
  194.  
  195.           $sum    = $this->_add($sum, $delta);
  196.  
  197.           $z      = $this->_add($z,
  198.                             $this->_add($y << 4 ^ $this->_rshift($y, 5), $y) ^
  199.                                   $this->_add($sum, $this->key[$this->_rshift($sum, 11) & 3]));
  200.  
  201.           }
  202.  
  203.        /* end cycle */
  204.        $v[0]=$y;
  205.        $v[1]=$z;
  206.  
  207.        return array($y,$z);
  208.  
  209.    }
  210.  
  211.    function block_decrypt($y, $z) {
  212.        $delta=0x9e3779b9;
  213.        $sum=0xC6EF3720;
  214.        $n=32;
  215.  
  216.        /* start cycle */
  217.        for ($i=0; $i<32; $i++)
  218.           {
  219.           $z      = $this->_add($z,
  220.                         -($this->_add($y << 4 ^ $this->_rshift($y, 5), $y) ^
  221.                           $this->_add($sum, $this->key[$this->_rshift($sum, 11) & 3])));
  222.           $sum    = $this->_add($sum, -$delta);
  223.           $y      = $this->_add($y,
  224.                               -($this->_add($z << 4 ^ $this->_rshift($z, 5), $z) ^
  225.                                         $this->_add($sum, $this->key[$sum & 3])));
  226.  
  227.           }
  228.        /* end cycle */
  229.  
  230.        return array($y,$z);
  231.     }
  232.  
  233.  
  234.  
  235.  
  236.       function _rshift($integer, $n) {
  237.         // convert to 32 bits
  238.         if (0xffffffff < $integer || -0xffffffff > $integer) {
  239.             $integer = fmod($integer, 0xffffffff + 1);
  240.         }
  241.  
  242.         // convert to unsigned integer
  243.         if (0x7fffffff < $integer) {
  244.             $integer -= 0xffffffff + 1.0;
  245.         } elseif (-0x80000000 > $integer) {
  246.             $integer += 0xffffffff + 1.0;
  247.         }
  248.  
  249.         // do right shift
  250.         if (0 > $integer) {
  251.             $integer &= 0x7fffffff;                     // remove sign bit before shift
  252.             $integer >>= $n;                            // right shift
  253.             $integer |= 1 << (31 - $n);                 // set shifted sign bit
  254.         } else {
  255.             $integer >>= $n;                            // use normal right shift
  256.         }
  257.  
  258.         return $integer;
  259.     }
  260.  
  261.  
  262.     function _add($i1, $i2) {
  263.         $result = 0.0;
  264.  
  265.         foreach (func_get_args() as $value) {
  266.             // remove sign if necessary
  267.             if (0.0 > $value) {
  268.                 $value -= 1.0 + 0xffffffff;
  269.             }
  270.  
  271.             $result += $value;
  272.         }
  273.  
  274.         // convert to 32 bits
  275.         if (0xffffffff < $result || -0xffffffff > $result) {
  276.             $result = fmod($result, 0xffffffff + 1);
  277.         }
  278.  
  279.         // convert to signed integer
  280.         if (0x7fffffff < $result) {
  281.             $result -= 0xffffffff + 1.0;
  282.         } elseif (-0x80000000 > $result) {
  283.             $result += 0xffffffff + 1.0;
  284.         }
  285.  
  286.         return $result;
  287.     }
  288.  
  289.  
  290.    //Einen Text in Longzahlen umwandeln
  291.    //Covert a string into longinteger
  292.    function _str2long($data) {
  293.        $n = strlen($data);
  294.        $tmp = unpack('N*', $data);
  295.        $data_long = array();
  296.        $j = 0;
  297.  
  298.        foreach ($tmp as $value) $data_long[$j++] = $value;
  299.        return $data_long;
  300.    }
  301.  
  302.    //Longzahlen in Text umwandeln
  303.    //Convert a longinteger into a string
  304.    function _long2str($l){
  305.        return pack('N', $l);
  306.    }
  307.  
  308. }
  309. ?>
  310.  
May 3 '12 #1
Share this Question
Share on Google+
13 Replies


Rabbit
Expert Mod 10K+
P: 12,369
XTEA uses a 128-bit key, or 16 bytes. If you have a 32 byte key from the client, that probably means they gave it to you in hex format. You'll just need to convert it from hex to decimal or ascii, whichever your function accepts.
May 3 '12 #2

100+
P: 162
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.

Expand|Select|Wrap|Line Numbers
  1. $ascii_string = '';
  2. foreach( str_split($text,2) as $chunk ){ $ascii_string .= chr(hexdec($chunk)); }
  3. $base64_string = base64_encode($ascii_string);
  4.  
  5. $xtea = new XTEA('28d75A09ec63c32b1e870fad25e79b8c');
  6. $output =$xtea->Decrypt($base64_string);
  7.  
  8.  
May 4 '12 #3

Rabbit
Expert Mod 10K+
P: 12,369
Your key in the code and in your description is different. Why is that? Which one is correct? If the one in the code is what was given to you, then that is hexadecimal. Refer back to my previous post.
May 4 '12 #4

100+
P: 162
the one in the code is correct.
May 4 '12 #5

Rabbit
Expert Mod 10K+
P: 12,369
Then refer back to my previous post.
May 4 '12 #6

100+
P: 162
thanks. i'll run it later tonight
May 4 '12 #7

Rabbit
Expert Mod 10K+
P: 12,369
Just be aware that the hex key they gave you contains unprintable characters. So you will probably want to do the conversion in code and then pass that along to the decryption function.
May 4 '12 #8

100+
P: 162
crap. still lost and its not decrypting. This is where I'm at.

Expand|Select|Wrap|Line Numbers
  1. // convert HEX key to ASCII (working)
  2. $ascii_key = hexToAscii('28d75A09ec63c32b1e870fad25e79b8c');
  3. // (Z    c+‡*%›Œ
  4.  
  5.  
  6. // convert XTEA encrypted HEX value to ASCII (working)
  7. $ascii = hexToAscii($text);
  8. // ŸOjAŽQœl:6bدjg9#Q9@'X}I}Œ{![KP—žub‹9wgGD[ic€S`K‰LkV™GmnLd{+3@Fdj0/coI\:tCU)+1":Er-po1ΰ[`/6E…| 40WŠ<=€b )*[_‘
  9.  
  10.  
  11. // base64 encode ASCII value (working)
  12. $base64_string = base64_encode($ascii);
  13. // sJ9PtGrUQY5R5OCcbBGqOjZij70cwtivatPwFGfKORAjHKhR1jlAJ1jVfUnMfRLvjHshW0tQosj/l6Ke7qX1dfeoYovbOXdnR+JE/ltp2M1jpNyAU2Dwy0uJTKhrVuiQmbVH/qONFqkCA/9tbkxktsp7KzMYQEbn6GRqMC9jb6NJw+74xFw6dEMDAlUpKzGqIs06RedyLXBvMevXzrC27VvBYOsc1i+uNuhF54V8nSA0MFeKPD3rrICPC+1iyN8gKSpbFF+pkcU=
  14.  
  15.  
  16. // decrypt XTEA encrypted value (FAILING)
  17. $xtea = new XTEA($ascii_key);
  18. $output = $xtea->Decrypt($base64_string);
  19. echo  nl2br(htmlentities(stripslashes($output)));
  20. // |61}BhžB`”od4H]sZ’=8€Srh$0n'wḥTwp}4-8EŸšl0SSFŒ|}I„Y;L(b‹-iScž4!컁f”[y4m—O"˜E&T‡'
  21. œ7}CVqWC_&ƒšWn}›„›ŽP
  22.  
As you can see the last result is not a legible string. It should look like a bunch of parameters after a url. HELP!!
May 6 '12 #9

Rabbit
Expert Mod 10K+
P: 12,369
Why the base64?
May 7 '12 #10

100+
P: 162
It was suggested by someone else. With it the resulting value "looks" like it should. Meaning it the string looks like the encrypted value (before HEX) that XTEA produces when doing and encryption.
May 7 '12 #11

Rabbit
Expert Mod 10K+
P: 12,369
Don't use base64.
May 7 '12 #12

100+
P: 162
why not? without it the code looks nothing like it should. Example, if i do a regular encrypt the string looks a certain way, i can then run this a s a decrypt and it does fine. But when i get it from my client and do the decrypt without base64, the string doesnt look like the output I would have created. get it?
May 7 '12 #13

Rabbit
Expert Mod 10K+
P: 12,369
XTEA does not, in it's specification, require that the input and output be encoded in Base64. An individual implementation can, if they wish, implement an encoding so as to present the result in a user friendly format such as Base64 or Hex.

That is why I said not to use Base64. However, after looking at your particular implementation, I notice that it is using Base64. What's left that could explain it is either

1) The person encrypted it in a mode different than the one you're using. Like ECB, CBC, CFB, etc. You could ask the person which mode they used or you could try them all and see if one of them sticks. Your implementation only implements ECB and CBC so if it's one of the other ones, you'll have to code for those. Your default is CBC so I would try ECB next before attempting to code the other modes.

2) There is an error in your and/or their implementation of XTEA. The only way to to see if that is the case is to encode a series of known cipher texts and keys using the same mode and comparing the results.
May 8 '12 #14

Post your reply

Sign in to post your reply or Sign up for a free account.