XTEA Encryption/Decryption

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • empiresolutions
    New Member
    • Apr 2006
    • 162

    XTEA Encryption/Decryption

    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:
    <?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);
       }
    
    }
    ?>
  • Rabbit
    Recognized Expert MVP
    • Jan 2007
    • 12517

    #2
    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.

    Comment

    • empiresolutions
      New Member
      • Apr 2006
      • 162

      #3
      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 "28d75A09ec63cx vxve870fad25e79 b8c"? How do I change this into 16 characters? Below is my current code.

      Code:
      $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);

      Comment

      • Rabbit
        Recognized Expert MVP
        • Jan 2007
        • 12517

        #4
        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.

        Comment

        • empiresolutions
          New Member
          • Apr 2006
          • 162

          #5
          the one in the code is correct.

          Comment

          • Rabbit
            Recognized Expert MVP
            • Jan 2007
            • 12517

            #6
            Then refer back to my previous post.

            Comment

            • empiresolutions
              New Member
              • Apr 2006
              • 162

              #7
              thanks. i'll run it later tonight

              Comment

              • Rabbit
                Recognized Expert MVP
                • Jan 2007
                • 12517

                #8
                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.

                Comment

                • empiresolutions
                  New Member
                  • Apr 2006
                  • 162

                  #9
                  crap. still lost and its not decrypting. This is where I'm at.

                  Code:
                  // 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!!

                  Comment

                  • Rabbit
                    Recognized Expert MVP
                    • Jan 2007
                    • 12517

                    #10
                    Why the base64?

                    Comment

                    • empiresolutions
                      New Member
                      • Apr 2006
                      • 162

                      #11
                      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.

                      Comment

                      • Rabbit
                        Recognized Expert MVP
                        • Jan 2007
                        • 12517

                        #12
                        Don't use base64.

                        Comment

                        • empiresolutions
                          New Member
                          • Apr 2006
                          • 162

                          #13
                          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?

                          Comment

                          • Rabbit
                            Recognized Expert MVP
                            • Jan 2007
                            • 12517

                            #14
                            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.

                            Comment

                            Working...