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.12 2004/10/04 19:51: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.12 $
  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.  
  218.         // convert key to long
  219.         $n_key_long $this->_str2long(0$key$key_long);
  220.  
  221.         // encrypt the long data with the key
  222.         $enc_data   '';
  223.         $w          = array(00);
  224.         $j          = 0;
  225.         $k          = array(0000);
  226.         for ($i = 0; $i $n_data_long; ++$i{
  227.             // get next key part of 128 bits
  228.             if ($j + 4 <= $n_key_long{
  229.                 $k[0$key_long[$j];
  230.                 $k[1$key_long[$j + 1];
  231.                 $k[2$key_long[$j + 2];
  232.                 $k[3$key_long[$j + 3];
  233.             else {
  234.                 $k[0$key_long[$j $n_key_long];
  235.                 $k[1$key_long[($j + 1$n_key_long];
  236.                 $k[2$key_long[($j + 2$n_key_long];
  237.                 $k[3$key_long[($j + 3$n_key_long];
  238.             }
  239.             $j ($j + 4$n_key_long;
  240.  
  241.             $this->_encipherLong($data_long[$i]$data_long[++$i]$w$k);
  242.  
  243.             // append the enciphered longs to the result
  244.             $enc_data .= $this->_long2str($w[0]);
  245.             $enc_data .= $this->_long2str($w[1]);
  246.         }
  247.  
  248.         return $enc_data;
  249.     }
  250.  
  251.     // }}}
  252.     // {{{ decrypt()
  253.  
  254.     /**
  255.      *  Decrypt an encrypted string using a specific key.
  256.      *
  257.      *  @param  string  $data   Encrypted data to decrypt.
  258.      *  @param  string  $key    Key to decrypt encrypted data with (binary string).
  259.      *
  260.      *  @return string          Binary decrypted character string.
  261.      *
  262.      *  @access public
  263.      *  @author         Jeroen Derks <jeroen@derks.it>
  264.      *  @see            _encipherLong(), encrypt(), _resize(), _str2long()
  265.      */
  266.     function decrypt($enc_data$key)
  267.     {
  268.         // convert data to long
  269.         $n_enc_data_long $this->_str2long(0$enc_data$enc_data_long);
  270.  
  271.         // resize key to a multiple of 128 bits (16 bytes)
  272.         $this->_resize($key16true);
  273.  
  274.         // convert key to long
  275.         $n_key_long $this->_str2long(0$key$key_long);
  276.  
  277.         // decrypt the long data with the key
  278.         $data   '';
  279.         $w      = array(00);
  280.         $j      = 0;
  281.         $len    = 0;
  282.         $k      = array(0000);
  283.         $pos    = 0;
  284.  
  285.         for ($i = 0; $i $n_enc_data_long$i += 2{
  286.             // get next key part of 128 bits
  287.             if ($j + 4 <= $n_key_long{
  288.                 $k[0$key_long[$j];
  289.                 $k[1$key_long[$j + 1];
  290.                 $k[2$key_long[$j + 2];
  291.                 $k[3$key_long[$j + 3];
  292.             else {
  293.                 $k[0$key_long[$j $n_key_long];
  294.                 $k[1$key_long[($j + 1$n_key_long];
  295.                 $k[2$key_long[($j + 2$n_key_long];
  296.                 $k[3$key_long[($j + 3$n_key_long];
  297.             }
  298.             $j ($j + 4$n_key_long;
  299.  
  300.             $this->_decipherLong($enc_data_long[$i]$enc_data_long[$i + 1]$w$k);
  301.  
  302.             // append the deciphered longs to the result data (remove padding)
  303.             if (0 == $i{
  304.                 $len $w[0];
  305.                 if (4 <= $len{
  306.                     $data .= $this->_long2str($w[1]);
  307.                 else {
  308.                     $data .= substr($this->_long2str($w[1])0$len % 4);
  309.                 }
  310.             else {
  311.                 $pos ($i - 1* 4;
  312.                 if ($pos + 4 <= $len{
  313.                     $data .= $this->_long2str($w[0]);
  314.  
  315.                     if ($pos + 8 <= $len{
  316.                         $data .= $this->_long2str($w[1]);
  317.                     elseif ($pos + 4 < $len{
  318.                         $data .= substr($this->_long2str($w[1])0$len % 4);
  319.                     }
  320.                 else {
  321.                     $data .= substr($this->_long2str($w[0])0$len % 4);
  322.                 }
  323.             }
  324.         }
  325.         return $data;
  326.     }
  327.  
  328.     // }}}
  329.     // {{{ _encipherLong()
  330.  
  331.     /**
  332.      *  Encipher a single long (32-bit) value.
  333.      *
  334.      *  @param  integer $y  32 bits of data.
  335.      *  @param  integer $z  32 bits of data.
  336.      *  @param  array   &$w Placeholder for enciphered 64 bits (in w[0] and w[1]).
  337.      *  @param  array   &$k Key 128 bits (in k[0]-k[3]).
  338.      *
  339.      *  @access private
  340.      *  @author         Jeroen Derks <jeroen@derks.it>
  341.      *  @see            $n_iter, _add(), _rshift(), _decipherLong()
  342.      */
  343.     function _encipherLong($y$z&$w&$k)
  344.     {
  345.         $sum    = (integer) 0;
  346.         $delta  = (integer) 0x9E3779B9;
  347.         $n      = (integer) $this->n_iter;
  348.  
  349.         while ($n-- > 0{
  350.             $y      $this->_add($y,
  351.                                   $this->_add($z << 4 ^ $this->_rshift($z5)$z^
  352.                                     $this->_add($sum$k[$sum 3]));
  353.             $sum    $this->_add($sum$delta);
  354.             $z      $this->_add($z,
  355.                                   $this->_add($y << 4 ^ $this->_rshift($y5)$y^
  356.                                     $this->_add($sum$k[$this->_rshift($sum113]));
  357.         }
  358.  
  359.         $w[0$y;
  360.         $w[1$z;
  361.     }
  362.  
  363.     // }}}
  364.     // {{{ _decipherLong()
  365.  
  366.     /**
  367.      *  Decipher a single long (32-bit) value.
  368.      *
  369.      *  @param  integer $y  32 bits of enciphered data.
  370.      *  @param  integer $z  32 bits of enciphered data.
  371.      *  @param  array   &$w Placeholder for deciphered 64 bits (in w[0] and w[1]).
  372.      *  @param  array   &$k Key 128 bits (in k[0]-k[3]).
  373.      *
  374.      *  @access private
  375.      *  @author         Jeroen Derks <jeroen@derks.it>
  376.      *  @see            $n_iter, _add(), _rshift(), _decipherLong()
  377.      */
  378.     function _decipherLong($y$z&$w&$k)
  379.     {
  380.         // sum = delta<<5, in general sum = delta * n
  381.         $sum    = (integer) 0xC6EF3720;
  382.         $delta  = (integer) 0x9E3779B9;
  383.         $n      = (integer) $this->n_iter;
  384.  
  385.         while ($n-- > 0{
  386.             $z      $this->_add($z,
  387.                                   -($this->_add($y << 4 ^ $this->_rshift($y5)$y^
  388.                                         $this->_add($sum$k[$this->_rshift($sum113])));
  389.             $sum    $this->_add($sum-$delta);
  390.             $y      $this->_add($y,
  391.                                   -($this->_add($z << 4 ^ $this->_rshift($z5)$z^
  392.                                         $this->_add($sum$k[$sum 3])));
  393.         }
  394.  
  395.         $w[0$y;
  396.         $w[1$z;
  397.     }
  398.  
  399.     // }}}
  400.     // {{{ _resize()
  401.  
  402.     /**
  403.      *  Resize data string to a multiple of specified size.
  404.      *
  405.      *  @param  string  $data   Data string to resize to specified size.
  406.      *  @param  integer $size   Size in bytes to align data to.
  407.      *  @param  boolean $nonull Set to true if padded bytes should not be zero.
  408.      *
  409.      *  @return integer         Length of supplied data string.
  410.      *
  411.      *  @access private
  412.      *  @author         Jeroen Derks <jeroen@derks.it>
  413.      */
  414.     function _resize(&$data$size$nonull = false)
  415.     {
  416.         $n      strlen($data);
  417.         $nmod   $n $size;
  418.  
  419.         if ($nmod > 0{
  420.             if ($nonull{
  421.                 for ($i $n$i $n $nmod $size; ++$i{
  422.                     $data[$i$data[$i $n];
  423.                 }
  424.             else {
  425.                 for ($i $n$i $n $nmod $size; ++$i{
  426.                     $data[$ichr(0);
  427.                 }
  428.             }
  429.         }
  430.         return $n;
  431.     }
  432.  
  433.     // }}}
  434.     // {{{ _hex2bin()
  435.  
  436.     /**
  437.      *  Convert a hexadecimal string to a binary string (e.g. convert "616263" to "abc").
  438.      *
  439.      *  @param  string  $str    Hexadecimal string to convert to binary string.
  440.      *
  441.      *  @return string          Binary string.
  442.      *
  443.      *  @access private
  444.      *  @author         Jeroen Derks <jeroen@derks.it>
  445.      */
  446.     function _hex2bin($str)
  447.     {
  448.         $len strlen($str);
  449.         return pack('H' $len$str);
  450.     }
  451.  
  452.     // }}}
  453.     // {{{ _str2long()
  454.  
  455.     /**
  456.      *  Convert string to array of long.
  457.      *
  458.      *  @param  integer $start      Index into $data_long for output.
  459.      *  @param  string  &$data      Input string.
  460.      *  @param  array   &$data_long Output array of long.
  461.      *
  462.      *  @return integer             Index from which to optionally continue.
  463.      *
  464.      *  @access private
  465.      *  @author         Jeroen Derks <jeroen@derks.it>
  466.      */
  467.     function _str2long($start&$data&$data_long)
  468.     {
  469.         $n strlen($data);
  470.  
  471.         $tmp    unpack('N*'$data);
  472.         $j      $start;
  473.  
  474.         foreach ($tmp as $value)
  475.             $data_long[$j++$value;
  476.  
  477.         return $j;
  478.     }
  479.  
  480.     // }}}
  481.     // {{{ _long2str()
  482.  
  483.     /**
  484.      *  Convert long to character string.
  485.      *
  486.      *  @param  long    $l  Long to convert to character string.
  487.      *
  488.      *  @return string      Character string.
  489.      *
  490.      *  @access private
  491.      *  @author         Jeroen Derks <jeroen@derks.it>
  492.      */
  493.     function _long2str($l)
  494.     {
  495.         return pack('N'$l);
  496.     }
  497.  
  498.     // }}}
  499.     // {{{ _rshift()
  500.     
  501.     /**
  502.      *  Handle proper unsigned right shift, dealing with PHP's signed shift.
  503.      *
  504.      *  @access private
  505.      *  @since          2004/Sep/06
  506.      *  @author         Jeroen Derks <jeroen@derks.it>
  507.      */
  508.     function _rshift($integer$n)
  509.     {
  510.         // convert to 32 bits
  511.         if (0xffffffff < $integer || -0xffffffff > $integer{
  512.             $integer fmod($integer0xffffffff + 1);
  513.         }
  514.  
  515.         // convert to unsigned integer
  516.         if (0x7fffffff < $integer{
  517.             $integer -= 0xffffffff + 1.0;
  518.         elseif (-0x80000000 > $integer{
  519.             $integer += 0xffffffff + 1.0;
  520.         }
  521.  
  522.         // do right shift
  523.         if (0 > $integer{
  524.             $integer &= 0x7fffffff;                     // remove sign bit before shift
  525.             $integer >>= $n;                            // right shift
  526.             $integer |= 1 << (31 - $n);                 // set shifted sign bit
  527.         else {
  528.             $integer >>= $n;                            // use normal right shift
  529.         }
  530.  
  531.         return $integer;
  532.     }
  533.  
  534.     // }}}
  535.     // {{{ _add()
  536.     
  537.     /**
  538.      *  Handle proper unsigned add, dealing with PHP's signed add.
  539.      *
  540.      *  @access private
  541.      *  @since          2004/Sep/06
  542.      *  @author         Jeroen Derks <jeroen@derks.it>
  543.      */
  544.     function _add($i1$i2)
  545.     {
  546.         $result = 0.0;
  547.  
  548.         foreach (func_get_args(as $value{
  549.             // remove sign if necessary
  550.             if (0.0 > $value{
  551.                 $value -= 1.0 + 0xffffffff;
  552.             }
  553.  
  554.             $result += $value;
  555.         }
  556.  
  557.         // convert to 32 bits
  558.         if (0xffffffff < $result || -0xffffffff > $result{
  559.             $result fmod($result0xffffffff + 1);
  560.         }
  561.  
  562.         // convert to signed integer
  563.         if (0x7fffffff < $result{
  564.             $result -= 0xffffffff + 1.0;
  565.         elseif (-0x80000000 > $result{
  566.             $result += 0xffffffff + 1.0;
  567.         }
  568.  
  569.         return $result;
  570.     }
  571.  
  572.     // }}}
  573. }
  574.  
  575. ?>

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