Advertisement
Guest User

AES en/de -cryption

a guest
Jun 13th, 2012
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 22.72 KB | None | 0 0
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3.  
  4. /**
  5.  * Pure-PHP implementation of AES.
  6.  *
  7.  * Uses mcrypt, if available, and an internal implementation, otherwise.
  8.  *
  9.  * PHP versions 4 and 5
  10.  *
  11.  * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
  12.  * {@link Crypt_AES::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's 136-bits
  13.  * it'll be null-padded to 160-bits and 160 bits will be the key length until {@link Crypt_Rijndael::setKey() setKey()}
  14.  * is called, again, at which point, it'll be recalculated.
  15.  *
  16.  * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
  17.  * make a whole lot of sense.  {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance.  Calling that function,
  18.  * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
  19.  *
  20.  * Here's a short example of how to use this library:
  21.  * <code>
  22.  * <?php
  23.  *    include('Crypt/AES.php');
  24.  *
  25.  *    $aes = new Crypt_AES();
  26.  *
  27.  *    $aes->setKey('abcdefghijklmnop');
  28.  *
  29.  *    $size = 10 * 1024;
  30.  *    $plaintext = '';
  31.  *    for ($i = 0; $i < $size; $i++) {
  32.  *        $plaintext.= 'a';
  33.  *    }
  34.  *
  35.  *    echo $aes->decrypt($aes->encrypt($plaintext));
  36.  * ?>
  37.  * </code>
  38.  *
  39.  * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
  40.  * of this software and associated documentation files (the "Software"), to deal
  41.  * in the Software without restriction, including without limitation the rights
  42.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  43.  * copies of the Software, and to permit persons to whom the Software is
  44.  * furnished to do so, subject to the following conditions:
  45.  *
  46.  * The above copyright notice and this permission notice shall be included in
  47.  * all copies or substantial portions of the Software.
  48.  *
  49.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  50.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  51.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  52.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  53.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  54.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  55.  * THE SOFTWARE.
  56.  *
  57.  * @category   Crypt
  58.  * @package    Crypt_AES
  59.  * @author     Jim Wigginton <terrafrost@php.net>
  60.  * @copyright  MMVIII Jim Wigginton
  61.  * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
  62.  * @version    $Id: AES.php,v 1.7 2010/02/09 06:10:25 terrafrost Exp $
  63.  * @link       http://phpseclib.sourceforge.net
  64.  */
  65.  
  66. /**
  67.  * Include Crypt_Rijndael
  68.  */
  69. require_once 'Rijndael.php';
  70.  
  71. /**#@+
  72.  * @access public
  73.  * @see Crypt_AES::encrypt()
  74.  * @see Crypt_AES::decrypt()
  75.  */
  76. /**
  77.  * Encrypt / decrypt using the Counter mode.
  78.  *
  79.  * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
  80.  *
  81.  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
  82.  */
  83. define('CRYPT_AES_MODE_CTR', -1);
  84. /**
  85.  * Encrypt / decrypt using the Electronic Code Book mode.
  86.  *
  87.  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
  88.  */
  89. define('CRYPT_AES_MODE_ECB', 1);
  90. /**
  91.  * Encrypt / decrypt using the Code Book Chaining mode.
  92.  *
  93.  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
  94.  */
  95. define('CRYPT_AES_MODE_CBC', 2);
  96. /**
  97.  * Encrypt / decrypt using the Cipher Feedback mode.
  98.  *
  99.  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
  100.  */
  101. define('CRYPT_AES_MODE_CFB', 3);
  102. /**
  103.  * Encrypt / decrypt using the Cipher Feedback mode.
  104.  *
  105.  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
  106.  */
  107. define('CRYPT_AES_MODE_OFB', 4);
  108. /**#@-*/
  109.  
  110. /**#@+
  111.  * @access private
  112.  * @see Crypt_AES::Crypt_AES()
  113.  */
  114. /**
  115.  * Toggles the internal implementation
  116.  */
  117. define('CRYPT_AES_MODE_INTERNAL', 1);
  118. /**
  119.  * Toggles the mcrypt implementation
  120.  */
  121. define('CRYPT_AES_MODE_MCRYPT', 2);
  122. /**#@-*/
  123.  
  124. /**
  125.  * Pure-PHP implementation of AES.
  126.  *
  127.  * @author  Jim Wigginton <terrafrost@php.net>
  128.  * @version 0.1.0
  129.  * @access  public
  130.  * @package Crypt_AES
  131.  */
  132. class Crypt_AES extends Crypt_Rijndael {
  133.     /**
  134.      * mcrypt resource for encryption
  135.      *
  136.      * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
  137.      * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
  138.      *
  139.      * @see Crypt_AES::encrypt()
  140.      * @var String
  141.      * @access private
  142.      */
  143.     var $enmcrypt;
  144.  
  145.     /**
  146.      * mcrypt resource for decryption
  147.      *
  148.      * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
  149.      * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
  150.      *
  151.      * @see Crypt_AES::decrypt()
  152.      * @var String
  153.      * @access private
  154.      */
  155.     var $demcrypt;
  156.  
  157.     /**
  158.      * mcrypt resource for CFB mode
  159.      *
  160.      * @see Crypt_AES::encrypt()
  161.      * @see Crypt_AES::decrypt()
  162.      * @var String
  163.      * @access private
  164.      */
  165.     var $ecb;
  166.  
  167.     /**
  168.      * Default Constructor.
  169.      *
  170.      * Determines whether or not the mcrypt extension should be used.  $mode should only, at present, be
  171.      * CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC.  If not explictly set, CRYPT_AES_MODE_CBC will be used.
  172.      *
  173.      * @param optional Integer $mode
  174.      * @return Crypt_AES
  175.      * @access public
  176.      */
  177.     function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
  178.     {
  179.         if ( !defined('CRYPT_AES_MODE') ) {
  180.             switch (true) {
  181.                 case extension_loaded('mcrypt'):
  182.                     // i'd check to see if aes was supported, by doing in_array('des', mcrypt_list_algorithms('')),
  183.                     // but since that can be changed after the object has been created, there doesn't seem to be
  184.                     // a lot of point...
  185.                     define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
  186.                     break;
  187.                 default:
  188.                     define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
  189.             }
  190.         }
  191.  
  192.         switch ( CRYPT_AES_MODE ) {
  193.             case CRYPT_AES_MODE_MCRYPT:
  194.                 switch ($mode) {
  195.                     case CRYPT_AES_MODE_ECB:
  196.                         $this->paddable = true;
  197.                         $this->mode = MCRYPT_MODE_ECB;
  198.                         break;
  199.                     case CRYPT_AES_MODE_CTR:
  200.                         // ctr doesn't have a constant associated with it even though it appears to be fairly widely
  201.                         // supported.  in lieu of knowing just how widely supported it is, i've, for now, opted not to
  202.                         // include a compatibility layer.  the layer has been implemented but, for now, is commented out.
  203.                         $this->mode = 'ctr';
  204.                         //$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
  205.                         break;
  206.                     case CRYPT_AES_MODE_CFB:
  207.                         $this->mode = 'ncfb';
  208.                         break;
  209.                     case CRYPT_AES_MODE_OFB:
  210.                         $this->mode = MCRYPT_MODE_NOFB;
  211.                         break;
  212.                     case CRYPT_AES_MODE_CBC:
  213.                     default:
  214.                         $this->paddable = true;
  215.                         $this->mode = MCRYPT_MODE_CBC;
  216.                 }
  217.  
  218.                 $this->debuffer = $this->enbuffer = '';
  219.  
  220.                 break;
  221.             default:
  222.                 switch ($mode) {
  223.                     case CRYPT_AES_MODE_ECB:
  224.                         $this->paddable = true;
  225.                         $this->mode = CRYPT_RIJNDAEL_MODE_ECB;
  226.                         break;
  227.                     case CRYPT_AES_MODE_CTR:
  228.                         $this->mode = CRYPT_RIJNDAEL_MODE_CTR;
  229.                         break;
  230.                     case CRYPT_AES_MODE_CFB:
  231.                         $this->mode = CRYPT_RIJNDAEL_MODE_CFB;
  232.                         break;
  233.                     case CRYPT_AES_MODE_OFB:
  234.                         $this->mode = CRYPT_RIJNDAEL_MODE_OFB;
  235.                         break;
  236.                     case CRYPT_AES_MODE_CBC:
  237.                     default:
  238.                         $this->paddable = true;
  239.                         $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
  240.                 }
  241.         }
  242.  
  243.         if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
  244.             parent::Crypt_Rijndael($this->mode);
  245.         }
  246.     }
  247.  
  248.     /**
  249.      * Dummy function
  250.      *
  251.      * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
  252.      *
  253.      * @access public
  254.      * @param Integer $length
  255.      */
  256.     function setBlockLength($length)
  257.     {
  258.         return;
  259.     }
  260.  
  261.     /**
  262.      * Encrypts a message.
  263.      *
  264.      * $plaintext will be padded with up to 16 additional bytes.  Other AES implementations may or may not pad in the
  265.      * same manner.  Other common approaches to padding and the reasons why it's necessary are discussed in the following
  266.      * URL:
  267.      *
  268.      * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
  269.      *
  270.      * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
  271.      * strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
  272.      * length.
  273.      *
  274.      * @see Crypt_AES::decrypt()
  275.      * @access public
  276.      * @param String $plaintext
  277.      */
  278.     function encrypt($plaintext)
  279.     {
  280.         if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
  281.             $changed = $this->changed;
  282.             $this->_mcryptSetup();
  283.             /*
  284.             if ($this->mode == CRYPT_AES_MODE_CTR) {
  285.                 $iv = $this->encryptIV;
  286.                 $xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($plaintext), $iv));
  287.                 $ciphertext = $plaintext ^ $xor;
  288.                 if ($this->continuousBuffer) {
  289.                     $this->encryptIV = $iv;
  290.                 }
  291.                 return $ciphertext;
  292.             }
  293.             */
  294.             // re: http://phpseclib.sourceforge.net/cfb-demo.phps
  295.             // using mcrypt's default handing of CFB the above would output two different things.  using phpseclib's
  296.             // rewritten CFB implementation the above outputs the same thing twice.
  297.             if ($this->mode == 'ncfb') {
  298.                 if ($changed) {
  299.                     $this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
  300.                     mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
  301.                 }
  302.  
  303.                 if (strlen($this->enbuffer)) {
  304.                     $ciphertext = $plaintext ^ substr($this->encryptIV, strlen($this->enbuffer));
  305.                     $this->enbuffer.= $ciphertext;
  306.                     if (strlen($this->enbuffer) == 16) {
  307.                         $this->encryptIV = $this->enbuffer;
  308.                         $this->enbuffer = '';
  309.                         mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
  310.                     }
  311.                     $plaintext = substr($plaintext, strlen($ciphertext));
  312.                 } else {
  313.                     $ciphertext = '';
  314.                 }
  315.  
  316.                 $last_pos = strlen($plaintext) & 0xFFFFFFF0;
  317.                 $ciphertext.= $last_pos ? mcrypt_generic($this->enmcrypt, substr($plaintext, 0, $last_pos)) : '';
  318.  
  319.                 if (strlen($plaintext) & 0xF) {
  320.                     if (strlen($ciphertext)) {
  321.                         $this->encryptIV = substr($ciphertext, -16);
  322.                     }
  323.                     $this->encryptIV = mcrypt_generic($this->ecb, $this->encryptIV);
  324.                     $this->enbuffer = substr($plaintext, $last_pos) ^ $this->encryptIV;
  325.                     $ciphertext.= $this->enbuffer;
  326.                 }
  327.  
  328.                 return $ciphertext;
  329.             }
  330.  
  331.             if ($this->paddable) {
  332.                 $plaintext = $this->_pad($plaintext);
  333.             }
  334.  
  335.             $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
  336.  
  337.             if (!$this->continuousBuffer) {
  338.                 mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
  339.             }
  340.  
  341.             return $ciphertext;
  342.         }
  343.  
  344.         return parent::encrypt($plaintext);
  345.     }
  346.  
  347.     /**
  348.      * Decrypts a message.
  349.      *
  350.      * If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
  351.      *
  352.      * @see Crypt_AES::encrypt()
  353.      * @access public
  354.      * @param String $ciphertext
  355.      */
  356.     function decrypt($ciphertext)
  357.     {
  358.         if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
  359.             $changed = $this->changed;
  360.             $this->_mcryptSetup();
  361.             /*
  362.             if ($this->mode == CRYPT_AES_MODE_CTR) {
  363.                 $iv = $this->decryptIV;
  364.                 $xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($ciphertext), $iv));
  365.                 $plaintext = $ciphertext ^ $xor;
  366.                 if ($this->continuousBuffer) {
  367.                     $this->decryptIV = $iv;
  368.                 }
  369.                 return $plaintext;
  370.             }
  371.             */
  372.             if ($this->mode == 'ncfb') {
  373.                 if ($changed) {
  374.                     $this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
  375.                     mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
  376.                 }
  377.  
  378.                 if (strlen($this->debuffer)) {
  379.                     $plaintext = $ciphertext ^ substr($this->decryptIV, strlen($this->debuffer));
  380.  
  381.                     $this->debuffer.= substr($ciphertext, 0, strlen($plaintext));
  382.                     if (strlen($this->debuffer) == 16) {
  383.                         $this->decryptIV = $this->debuffer;
  384.                         $this->debuffer = '';
  385.                         mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
  386.                     }
  387.                     $ciphertext = substr($ciphertext, strlen($plaintext));
  388.                 } else {
  389.                     $plaintext = '';
  390.                 }
  391.  
  392.                 $last_pos = strlen($ciphertext) & 0xFFFFFFF0;
  393.                 $plaintext.= $last_pos ? mdecrypt_generic($this->demcrypt, substr($ciphertext, 0, $last_pos)) : '';
  394.  
  395.                 if (strlen($ciphertext) & 0xF) {
  396.                     if (strlen($plaintext)) {
  397.                         $this->decryptIV = substr($ciphertext, $last_pos - 16, 16);
  398.                     }
  399.                     $this->decryptIV = mcrypt_generic($this->ecb, $this->decryptIV);
  400.                     $this->debuffer = substr($ciphertext, $last_pos);
  401.                     $plaintext.= $this->debuffer ^ $this->decryptIV;
  402.                 }
  403.  
  404.                 return $plaintext;
  405.             }
  406.  
  407.             if ($this->paddable) {
  408.                 // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :
  409.                 // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
  410.                 $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
  411.             }
  412.  
  413.             $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
  414.  
  415.             if (!$this->continuousBuffer) {
  416.                 mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
  417.             }
  418.  
  419.             return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
  420.         }
  421.  
  422.         return parent::decrypt($ciphertext);
  423.     }
  424.  
  425.     /**
  426.      * Setup mcrypt
  427.      *
  428.      * Validates all the variables.
  429.      *
  430.      * @access private
  431.      */
  432.     function _mcryptSetup()
  433.     {
  434.         if (!$this->changed) {
  435.             return;
  436.         }
  437.  
  438.         if (!$this->explicit_key_length) {
  439.             // this just copied from Crypt_Rijndael::_setup()
  440.             $length = strlen($this->key) >> 2;
  441.             if ($length > 8) {
  442.                 $length = 8;
  443.             } else if ($length < 4) {
  444.                 $length = 4;
  445.             }
  446.             $this->Nk = $length;
  447.             $this->key_size = $length << 2;
  448.         }
  449.  
  450.         switch ($this->Nk) {
  451.             case 4: // 128
  452.                 $this->key_size = 16;
  453.                 break;
  454.             case 5: // 160
  455.             case 6: // 192
  456.                 $this->key_size = 24;
  457.                 break;
  458.             case 7: // 224
  459.             case 8: // 256
  460.                 $this->key_size = 32;
  461.         }
  462.  
  463.         $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
  464.         $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
  465.  
  466.         if (!isset($this->enmcrypt)) {
  467.             $mode = $this->mode;
  468.             //$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
  469.  
  470.             $this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
  471.             $this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
  472.         } // else should mcrypt_generic_deinit be called?
  473.  
  474.         mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
  475.         mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
  476.  
  477.         $this->changed = false;
  478.     }
  479.  
  480.     /**
  481.      * Encrypts a block
  482.      *
  483.      * Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
  484.      *
  485.      * @see Crypt_Rijndael::_encryptBlock()
  486.      * @access private
  487.      * @param String $in
  488.      * @return String
  489.      */
  490.     function _encryptBlock($in)
  491.     {
  492.         $state = unpack('N*word', $in);
  493.  
  494.         $Nr = $this->Nr;
  495.         $w = $this->w;
  496.         $t0 = $this->t0;
  497.         $t1 = $this->t1;
  498.         $t2 = $this->t2;
  499.         $t3 = $this->t3;
  500.  
  501.         // addRoundKey and reindex $state
  502.         $state = array(
  503.             $state['word1'] ^ $w[0][0],
  504.             $state['word2'] ^ $w[0][1],
  505.             $state['word3'] ^ $w[0][2],
  506.             $state['word4'] ^ $w[0][3]
  507.         );
  508.  
  509.         // shiftRows + subWord + mixColumns + addRoundKey
  510.         // we could loop unroll this and use if statements to do more rounds as necessary, but, in my tests, that yields
  511.         // only a marginal improvement.  since that also, imho, hinders the readability of the code, i've opted not to do it.
  512.         for ($round = 1; $round < $this->Nr; $round++) {
  513.             $state = array(
  514.                 $t0[$state[0] & 0xFF000000] ^ $t1[$state[1] & 0x00FF0000] ^ $t2[$state[2] & 0x0000FF00] ^ $t3[$state[3] & 0x000000FF] ^ $w[$round][0],
  515.                 $t0[$state[1] & 0xFF000000] ^ $t1[$state[2] & 0x00FF0000] ^ $t2[$state[3] & 0x0000FF00] ^ $t3[$state[0] & 0x000000FF] ^ $w[$round][1],
  516.                 $t0[$state[2] & 0xFF000000] ^ $t1[$state[3] & 0x00FF0000] ^ $t2[$state[0] & 0x0000FF00] ^ $t3[$state[1] & 0x000000FF] ^ $w[$round][2],
  517.                 $t0[$state[3] & 0xFF000000] ^ $t1[$state[0] & 0x00FF0000] ^ $t2[$state[1] & 0x0000FF00] ^ $t3[$state[2] & 0x000000FF] ^ $w[$round][3]
  518.             );
  519.  
  520.         }
  521.  
  522.         // subWord
  523.         $state = array(
  524.             $this->_subWord($state[0]),
  525.             $this->_subWord($state[1]),
  526.             $this->_subWord($state[2]),
  527.             $this->_subWord($state[3])
  528.         );
  529.  
  530.         // shiftRows + addRoundKey
  531.         $state = array(
  532.             ($state[0] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[3] & 0x000000FF) ^ $this->w[$this->Nr][0],
  533.             ($state[1] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[0] & 0x000000FF) ^ $this->w[$this->Nr][1],
  534.             ($state[2] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[1] & 0x000000FF) ^ $this->w[$this->Nr][2],
  535.             ($state[3] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[2] & 0x000000FF) ^ $this->w[$this->Nr][3]
  536.         );
  537.  
  538.         return pack('N*', $state[0], $state[1], $state[2], $state[3]);
  539.     }
  540.  
  541.     /**
  542.      * Decrypts a block
  543.      *
  544.      * Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
  545.      *
  546.      * @see Crypt_Rijndael::_decryptBlock()
  547.      * @access private
  548.      * @param String $in
  549.      * @return String
  550.      */
  551.     function _decryptBlock($in)
  552.     {
  553.         $state = unpack('N*word', $in);
  554.  
  555.         $Nr = $this->Nr;
  556.         $dw = $this->dw;
  557.         $dt0 = $this->dt0;
  558.         $dt1 = $this->dt1;
  559.         $dt2 = $this->dt2;
  560.         $dt3 = $this->dt3;
  561.  
  562.         // addRoundKey and reindex $state
  563.         $state = array(
  564.             $state['word1'] ^ $dw[$this->Nr][0],
  565.             $state['word2'] ^ $dw[$this->Nr][1],
  566.             $state['word3'] ^ $dw[$this->Nr][2],
  567.             $state['word4'] ^ $dw[$this->Nr][3]
  568.         );
  569.  
  570.  
  571.         // invShiftRows + invSubBytes + invMixColumns + addRoundKey
  572.         for ($round = $this->Nr - 1; $round > 0; $round--) {
  573.             $state = array(
  574.                 $dt0[$state[0] & 0xFF000000] ^ $dt1[$state[3] & 0x00FF0000] ^ $dt2[$state[2] & 0x0000FF00] ^ $dt3[$state[1] & 0x000000FF] ^ $dw[$round][0],
  575.                 $dt0[$state[1] & 0xFF000000] ^ $dt1[$state[0] & 0x00FF0000] ^ $dt2[$state[3] & 0x0000FF00] ^ $dt3[$state[2] & 0x000000FF] ^ $dw[$round][1],
  576.                 $dt0[$state[2] & 0xFF000000] ^ $dt1[$state[1] & 0x00FF0000] ^ $dt2[$state[0] & 0x0000FF00] ^ $dt3[$state[3] & 0x000000FF] ^ $dw[$round][2],
  577.                 $dt0[$state[3] & 0xFF000000] ^ $dt1[$state[2] & 0x00FF0000] ^ $dt2[$state[1] & 0x0000FF00] ^ $dt3[$state[0] & 0x000000FF] ^ $dw[$round][3]
  578.             );
  579.         }
  580.  
  581.         // invShiftRows + invSubWord + addRoundKey
  582.         $state = array(
  583.             $this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $dw[0][0],
  584.             $this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $dw[0][1],
  585.             $this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $dw[0][2],
  586.             $this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $dw[0][3]
  587.         );
  588.  
  589.         return pack('N*', $state[0], $state[1], $state[2], $state[3]);
  590.     }
  591. }
  592.  
  593. // vim: ts=4:sw=4:et:
  594. // vim6: fdl=1:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement