Crypt
[ class tree: Crypt ] [ index: Crypt ] [ all elements ]

Source for file Xtea.php

Documentation is available at Xtea.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. //
  4. // +----------------------------------------------------------------------+
  5. // | PHP version 4.0                                                      |
  6. // +----------------------------------------------------------------------+
  7. // | Copyright (c) 2002 The PHP Group                                     |
  8. // +----------------------------------------------------------------------+
  9. // | This source file is subject to version 2.02 of the PHP license,      |
  10. // | that is bundled with this package in the file LICENSE, and is        |
  11. // | available at through the world-wide-web at                           |
  12. // | http://www.php.net/license/2_02.txt.                                 |
  13. // | If you did not receive a copy of the PHP license and are unable to   |
  14. // | obtain it through the world-wide-web, please send a note to          |
  15. // | license@php.net so we can mail you a copy immediately.               |
  16. // +----------------------------------------------------------------------+
  17. // | Authors: Jeroen Derks <jeroen@derks.it>                              |
  18. // +----------------------------------------------------------------------+
  19. // | Original code: http://vader.brad.ac.uk/tea/source.shtml#new_ansi     |
  20. // +----------------------------------------------------------------------+
  21. //
  22. // $Id: Xtea.php,v 1.8 2004/09/06 17:23:41 jeroend Exp $
  23. //
  24.  
  25. /**
  26.  *  Class that implements the xTEA encryption algorithm.
  27.  *  This enables you to encrypt data without requiring mcrypt.
  28.  *
  29.  *  From the C source:
  30.  *  -----------------------------------------
  31.  *  The Tiny Encryption Algorithm (TEA) by
  32.  *  David Wheeler and Roger Needham of the
  33.  *  Cambridge Computer Laboratory.
  34.  *
  35.  *  Placed in the Public Domain by
  36.  *  David Wheeler and Roger Needham.
  37.  *
  38.  *  **** ANSI C VERSION (New Variant) ****
  39.  *
  40.  *  Notes:
  41.  *
  42.  *  TEA is a Feistel cipher with XOR and
  43.  *  and addition as the non-linear mixing
  44.  *  functions.
  45.  *
  46.  *  Takes 64 bits of data in v[0] and v[1].
  47.  *  Returns 64 bits of data in w[0] and w[1].
  48.  *  Takes 128 bits of key in k[0] - k[3].
  49.  *
  50.  *  TEA can be operated in any of the modes
  51.  *  of DES. Cipher Block Chaining is, for example,
  52.  *  simple to implement.
  53.  *
  54.  *  n is the number of iterations. 32 is ample,
  55.  *  16 is sufficient, as few as eight may be OK.
  56.  *  The algorithm achieves good dispersion after
  57.  *  six iterations. The iteration count can be
  58.  *  made variable if required.
  59.  *
  60.  *  Note this is optimised for 32-bit CPUs with
  61.  *  fast shift capabilities. It can very easily
  62.  *  be ported to assembly language on most CPUs.
  63.  *
  64.  *  delta is chosen to be the real part of (the
  65.  *  golden ratio Sqrt(5/4) - 1/2 ~ 0.618034
  66.  *  multiplied by 2^32).
  67.  *
  68.  *  This version has been amended to foil two
  69.  *  weaknesses identified by David A. Wagner
  70.  *  (daw@cs.berkeley.edu): 1) effective key
  71.  *  length of old-variant TEA was 126 not 128
  72.  *  bits 2) a related key attack was possible
  73.  *  although impractical.
  74.  *
  75.  *  void encipher(unsigned long *const v,unsigned long *const w,
  76.  *  const unsigned long *const k)
  77.  *  {
  78.  *   register unsigned long       y=v[0],z=v[1],sum=0,delta=0x9E3779B9,n=32;
  79.  *
  80.  *   while(n-->0)
  81.  *      {
  82.  *        y+= (z<<4 ^ z>>5) + z ^ sum + k[sum&3];
  83.  *      sum += delta;
  84.  *      z+= (y<<4 ^ y>>5) + y ^ sum + k[sum>>11 & 3];
  85.  *      }
  86.  *
  87.  *   w[0]=y; w[1]=z;
  88.  *  }
  89.  *
  90.  *  void decipher(unsigned long *const v,unsigned long *const w,
  91.  *  const unsigned long *const k)
  92.  *  {
  93.  *   register unsigned long       y=v[0],z=v[1],sum=0xC6EF3720,
  94.  *                                delta=0x9E3779B9,n=32;
  95.  *
  96.  *   # sum = delta<<5, in general sum = delta * n
  97.  *
  98.  *       while(n-->0)
  99.  *          {
  100.  *            z-= (y<<4 ^ y>>5) + y ^ sum + k[sum>>11 & 3];
  101.  *          sum -= delta;
  102.  *            y-= (z<<4 ^ z>>5) + z ^ sum + k[sum&3];
  103.  *          }
  104.  *
  105.  *   w[0]=y; w[1]=z;
  106.  *  }
  107.  *
  108.  *  -----------------------------------------
  109.  *
  110.  *  @TODO       Add CFB.
  111.  *
  112.  *  @package    Crypt
  113.  *  @version    $Revision: 1.8 $
  114.  *  @access     public
  115.  *  @author     Jeroen Derks <jeroen@derks.it>
  116.  */
  117.  
  118.  
  119.     /**
  120.      *  Number of iterations.
  121.      *  @var    integer 
  122.      *  @access private
  123.      *  @see    setIter(), getIter()
  124.      */
  125.      private $n_iter;
  126.  
  127.  
  128.     // {{{ Crypt_Xtea()
  129.  
  130.     /**
  131.      *  Constructor, sets the number of iterations.
  132.      *
  133.      *  @access public
  134.      *  @author         Jeroen Derks <jeroen@derks.it>
  135.      *  @see            setIter()
  136.      */
  137.     public function __construct ({
  138.         $this->setIter32 );
  139.     }
  140.  
  141.     // }}}
  142.     // {{{ setIter()
  143.  
  144.     /**
  145.      *  Set the number of iterations to use.
  146.      *
  147.      *  @param  integer $n_iter Number of iterations to use.
  148.      *
  149.      *  @access public
  150.      *  @author         Jeroen Derks <jeroen@derks.it>
  151.      *  @see            $n_iter, getIter()
  152.      */
  153.     public function setIter$n_iter {
  154.         $this->n_iter $n_iter;
  155.     }
  156.  
  157.     // }}}
  158.     // {{{ getIter()
  159.  
  160.     /**
  161.      *  Get the number of iterations to use.
  162.      *
  163.      *  @return integer Number of iterations to use.
  164.      *
  165.      *  @access public
  166.      *  @author         Jeroen Derks <jeroen@derks.it>
  167.      *  @see            $n_iter, setIter()
  168.      */
  169.     public function getIter({
  170.         return $this->n_iter;
  171.     }
  172.  
  173.     // }}}
  174.     // {{{ encrypt()
  175.  
  176.     /**
  177.      *  Encrypt a string using a specific key.
  178.      *
  179.      *  @param  string  $data   Data to encrypt.
  180.      *  @param  string  $key    Key to encrypt data with (binary string).
  181.      *
  182.      *  @return string          Binary encrypted character string.
  183.      *
  184.      *  @access public
  185.      *  @author         Jeroen Derks <jeroen@derks.it>
  186.      *  @see            decrypt(), _encipherLong(), _resize(), _str2long()
  187.      */
  188.     public function encrypt($data$key{
  189.         // resize data to 32 bits (4 bytes)
  190.         $n $this->_resize($data4);
  191.  
  192.         // convert data to long
  193.         $data_long[0]   $n;
  194.         $n_data_long    $this->_str2long(1$data$data_long);
  195.  
  196.         // resize data_long to 64 bits (2 longs of 32 bits)
  197.         $n count($data_long);
  198.         if (($n 1== 1{
  199.             $data_long[$nchr(0);
  200.             $n_data_long++;
  201.         }
  202.  
  203.         // resize key to a multiple of 128 bits (16 bytes)
  204.         $this->_resize($key16true);
  205.  
  206.         // convert key to long
  207.         $n_key_long $this->_str2long(0$key$key_long);
  208.  
  209.         // encrypt the long data with the key
  210.         $enc_data   '';
  211.         $w          = array0);
  212.         $j          = 0;
  213.         $k          = array000);
  214.         for ($i = 0; $i $n_data_long; ++$i{
  215.             // get next key part of 128 bits
  216.             if ($j + 4 <= $n_key_long{
  217.                 $k[0$key_long[$j];
  218.                 $k[1$key_long[$j + 1];
  219.                 $k[2$key_long[$j + 2];
  220.                 $k[3$key_long[$j + 3];
  221.             else {
  222.                 $k[0$key_long[$j $n_key_long];
  223.                 $k[1$key_long[($j + 1$n_key_long];
  224.                 $k[2$key_long[($j + 2$n_key_long];
  225.                 $k[3$key_long[($j + 3$n_key_long];
  226.             }
  227.             $j ($j + 4$n_key_long;
  228.  
  229.             $this->_encipherLong($data_long[$i]$data_long[++$i]$w$k);
  230.  
  231.             // append the enciphered longs to the result
  232.             $enc_data .= $this->_long2str($w[0]);
  233.             $enc_data .= $this->_long2str($w[1]);
  234.         }
  235.  
  236.         return $enc_data;
  237.     }
  238.  
  239.     // }}}
  240.     // {{{ decrypt()
  241.  
  242.     /**
  243.      *  Decrypt an encrypted string using a specific key.
  244.      *
  245.      *  @param  string  $data   Encrypted data to decrypt.
  246.      *  @param  string  $key    Key to decrypt encrypted data with (binary string).
  247.      *
  248.      *  @return string          Binary decrypted character string.
  249.      *
  250.      *  @access public
  251.      *  @author         Jeroen Derks <jeroen@derks.it>
  252.      *  @see            _encipherLong(), encrypt(), _resize(), _str2long()
  253.      */
  254.     public function decrypt($enc_data$key{
  255.         // convert data to long
  256.         $n_enc_data_long $this->_str2long(0$enc_data$enc_data_long);
  257.  
  258.         // resize key to a multiple of 128 bits (16 bytes)
  259.         $this->_resize($key16true);
  260.  
  261.         // convert key to long
  262.         $n_key_long $this->_str2long(0$key$key_long);
  263.  
  264.         // decrypt the long data with the key
  265.         $data   '';
  266.         $w      = array0);
  267.         $j      = 0;
  268.         $len    = 0;
  269.         $k      = array000);
  270.         $pos    = 0;
  271.  
  272.         for ($i = 0; $i $n_enc_data_long$i += 2{
  273.             // get next key part of 128 bits
  274.             if ($j + 4 <= $n_key_long{
  275.                 $k[0$key_long[$j];
  276.                 $k[1$key_long[$j + 1];
  277.                 $k[2$key_long[$j + 2];
  278.                 $k[3$key_long[$j + 3];
  279.             else {
  280.                 $k[0$key_long[$j $n_key_long];
  281.                 $k[1$key_long[($j + 1$n_key_long];
  282.                 $k[2$key_long[($j + 2$n_key_long];
  283.                 $k[3$key_long[($j + 3$n_key_long];
  284.             }
  285.             $j ($j + 4$n_key_long;
  286.  
  287.             $this->_decipherLong($enc_data_long[$i]$enc_data_long[$i + 1]$w$k);
  288.  
  289.             // append the deciphered longs to the result data (remove padding)
  290.             if (0 == $i{
  291.                 $len $w[0];
  292.                 if (4 <= $len{
  293.                     $data .= $this->_long2str($w[1]);
  294.                 else {
  295.                     $data .= substr$this->_long2str($w[1])0$len % 4 );
  296.                 }
  297.             else {
  298.                 $pos ($i - 1* 4;
  299.                 if ($pos + 4 <= $len{
  300.                     $data .= $this->_long2str($w[0]);
  301.  
  302.                     if ($pos + 8 <= $len{
  303.                         $data .= $this->_long2str($w[1]);
  304.                     elseif ($pos + 4 < $len{
  305.                         $data .= substr$this->_long2str($w[1])0$len % 4 );
  306.                     }
  307.                 else {
  308.                     $data .= substr$this->_long2str($w[0])0$len % 4 );
  309.                 }
  310.             }
  311.         }
  312.         return $data;
  313.     }
  314.  
  315.     // }}}
  316.     // {{{ _encipherLong()
  317.  
  318.     /**
  319.      *  Encipher a single long (32-bit) value.
  320.      *
  321.      *  @param  integer $y  32 bits of data.
  322.      *  @param  integer $z  32 bits of data.
  323.      *  @param  array   &$w Placeholder for enciphered 64 bits (in w[0] and w[1]).
  324.      *  @param  array   &$k Key 128 bits (in k[0]-k[3]).
  325.      *
  326.      *  @access private
  327.      *  @author         Jeroen Derks <jeroen@derks.it>
  328.      *  @see            $n_iter, _add(), _rshift(), _decipherLong()
  329.      */
  330.     private function _encipherLong($y$z&$w&$k{
  331.         $sum    = (integer) 0;
  332.         $delta  = (integer) 0x9E3779B9;
  333.         $n      = (integer) $this->n_iter;
  334.  
  335.         while ($n-- > 0{
  336.             $y      $this->_add($y,
  337.                                   $this->_add($z << 4 ^ $this->_rshift($z5)$z^
  338.                                     $this->_add($sum$k[$sum 3]));
  339.             $sum    $this->_add($sum$delta);
  340.             $z      $this->_add($z,
  341.                                   $this->_add($y << 4 ^ $this->_rshift($y5)$y^
  342.                                     $this->_add($sum$k[$this->_rshift($sum113]));
  343.         }
  344.  
  345.         $w[0$y;
  346.         $w[1$z;
  347.     }
  348.  
  349.     // }}}
  350.     // {{{ _decipherLong()
  351.  
  352.     /**
  353.      *  Decipher a single long (32-bit) value.
  354.      *
  355.      *  @param  integer $y  32 bits of enciphered data.
  356.      *  @param  integer $z  32 bits of enciphered data.
  357.      *  @param  array   &$w Placeholder for deciphered 64 bits (in w[0] and w[1]).
  358.      *  @param  array   &$k Key 128 bits (in k[0]-k[3]).
  359.      *
  360.      *  @access private
  361.      *  @author         Jeroen Derks <jeroen@derks.it>
  362.      *  @see            $n_iter, _add(), _rshift(), _decipherLong()
  363.      */
  364.     private function _decipherLong($y$z&$w&$k{
  365.         // sum = delta<<5, in general sum = delta * n
  366.         $sum    = (integer) 0xC6EF3720;
  367.         $delta  = (integer) 0x9E3779B9;
  368.         $n      = (integer) $this->n_iter;
  369.  
  370.         while ($n-- > 0{
  371.             $z      $this->_add($z,
  372.                                   -($this->_add($y << 4 ^ $this->_rshift($y5)$y^
  373.                                         $this->_add($sum$k[$this->_rshift($sum113])));
  374.             $sum    $this->_add($sum-$delta);
  375.             $y      $this->_add($y,
  376.                                   -($this->_add($z << 4 ^ $this->_rshift($z5)$z^
  377.                                         $this->_add($sum$k[$sum 3])));
  378.         }
  379.  
  380.         $w[0$y;
  381.         $w[1$z;
  382.     }
  383.  
  384.     // }}}
  385.     // {{{ _resize()
  386.  
  387.     /**
  388.      *  Resize data string to a multiple of specified size.
  389.      *
  390.      *  @param  string  $data   Data string to resize to specified size.
  391.      *  @param  integer $size   Size in bytes to align data to.
  392.      *  @param  boolean $nonull Set to true if padded bytes should not be zero.
  393.      *
  394.      *  @return integer         Length of supplied data string.
  395.      *
  396.      *  @access private
  397.      *  @author         Jeroen Derks <jeroen@derks.it>
  398.      */
  399.     private function _resize(&$data$size$nonull = false{
  400.         $n      strlen($data);
  401.         $nmod   $n $size;
  402.  
  403.         if ($nmod > 0{
  404.             if ($nonull{
  405.                 for ($i $n$i $n $nmod $size; ++$i{
  406.                     $data[$i$data[$i $n];
  407.                 }
  408.             else {
  409.                 for ($i $n$i $n $nmod $size; ++$i{
  410.                     $data[$ichr(0);
  411.                 }
  412.             }
  413.         }
  414.         return $n;
  415.     }
  416.  
  417.     // }}}
  418.     // {{{ _hex2bin()
  419.  
  420.     /**
  421.      *  Convert a hexadecimal string to a binary string (e.g. convert "616263" to "abc").
  422.      *
  423.      *  @param  string  $str    Hexadecimal string to convert to binary string.
  424.      *
  425.      *  @return string          Binary string.
  426.      *
  427.      *  @access private
  428.      *  @author         Jeroen Derks <jeroen@derks.it>
  429.      */
  430.     private function _hex2bin($str{
  431.         $len strlen($str);
  432.         return pack('H' $len$str);
  433.     }
  434.  
  435.     // }}}
  436.     // {{{ _str2long()
  437.  
  438.     /**
  439.      *  Convert string to array of long.
  440.      *
  441.      *  @param  integer $start      Index into $data_long for output.
  442.      *  @param  string  &$data      Input string.
  443.      *  @param  array   &$data_long Output array of long.
  444.      *
  445.      *  @return integer             Index from which to optionally continue.
  446.      *
  447.      *  @access private
  448.      *  @author         Jeroen Derks <jeroen@derks.it>
  449.      */
  450.     private function _str2long($start&$data&$data_long{
  451.         $n strlen($data);
  452.  
  453.         $tmp    unpack('N*'$data);
  454.         $j      $start;
  455.  
  456.         foreach ($tmp as $value)
  457.             $data_long[$j++$value;
  458.  
  459.         return $j;
  460.     }
  461.  
  462.     // }}}
  463.     // {{{ _long2str()
  464.  
  465.     /**
  466.      *  Convert long to character string.
  467.      *
  468.      *  @param  long    $l  Long to convert to character string.
  469.      *
  470.      *  @return string      Character string.
  471.      *
  472.      *  @access private
  473.      *  @author         Jeroen Derks <jeroen@derks.it>
  474.      */
  475.     private function _long2str($l{
  476.         return pack'N'$l );
  477.     }
  478.  
  479.     // }}}
  480.     // {{{ _rshift()
  481.     
  482.     /**
  483.      *  Handle proper unsigned right shift, dealing with PHP's signed shift.
  484.      *
  485.      *  @access private
  486.      *  @since          2004/Sep/06
  487.      *  @author         Jeroen Derks <jeroen@derks.it>
  488.      */
  489.     private function _rshift($integer$n{
  490.         if (0 > (integer) $integer{
  491.             $integer $integer >> $n;              // shift
  492.             $integer &= ~(0x80000000 >> ($n - 1));  // remove shifted-in sign bits
  493.         else {
  494.             $integer >>= $n;                         // use normal shift
  495.         }
  496.  
  497.         return $integer;
  498.     }
  499.  
  500.     // }}}
  501.     // {{{ _add()
  502.     
  503.     /**
  504.      *  Handle proper unsigned add, dealing with PHP's signed add.
  505.      *
  506.      *  @access private
  507.      *  @since          2004/Sep/06
  508.      *  @author         Jeroen Derks <jeroen@derks.it>
  509.      */
  510.     private function _add($i1$i2{
  511.         $result = 0.0;
  512.  
  513.         foreach (func_get_args(as $value{
  514.             // remove sign if necessary
  515.             if (0.0 > $value{
  516.                 $value += 0xffffffff + 1.0;
  517.             }
  518.  
  519.             $result += $value;
  520.         }
  521.  
  522.         // convert to 32 bit
  523.         if (0xffffffff < $result{
  524.             $result fmod($result0xffffffff + 1);
  525.         }
  526.  
  527.         return (integer) $result;
  528.     }
  529.  
  530.     // }}}
  531. }
  532.  
  533. ?>

Documentation generated on Mon, 11 Mar 2019 13:55:48 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.