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

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