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

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