Вход Регистрация
Файл: oc-includes/phpseclib/Crypt/Rijndael.php
Строк: 875
<?php

/**
 * Pure-PHP implementation of Rijndael.
 *
 * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
 *
 * PHP versions 4 and 5
 *
 * If {@link Crypt_Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits.  If
 * {@link Crypt_Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
 * {@link Crypt_Rijndael::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's
 * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
 * {@link Crypt_Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated.
 *
 * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length.  mcrypt, for example,
 * does not.  AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
 * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224.  Indeed, 160 and 224
 * are first defined as valid key / block lengths in
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
 * Extensions: Other block and Cipher Key lengths.
 * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
 *
 * {@internal The variable names are the same as those in
 * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'Crypt/Rijndael.php';
 *
 *    $rijndael = new Crypt_Rijndael();
 *
 *    $rijndael->setKey('abcdefghijklmnop');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $rijndael->decrypt($rijndael->encrypt($plaintext));
 * ?>
 * </code>
 *
 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @category  Crypt
 * @package   Crypt_Rijndael
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2008 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */

/**
 * Include Crypt_Base
 *
 * Base cipher class
 */
if (!class_exists('Crypt_Base')) {
    include_once 
'Base.php';
}

/**#@+
 * @access public
 * @see Crypt_Rijndael::encrypt()
 * @see Crypt_Rijndael::decrypt()
 */
/**
 * Encrypt / decrypt using the Counter mode.
 *
 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
 *
 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
 */
define('CRYPT_RIJNDAEL_MODE_CTR'CRYPT_MODE_CTR);
/**
 * Encrypt / decrypt using the Electronic Code Book mode.
 *
 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
 */
define('CRYPT_RIJNDAEL_MODE_ECB'CRYPT_MODE_ECB);
/**
 * Encrypt / decrypt using the Code Book Chaining mode.
 *
 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
 */
define('CRYPT_RIJNDAEL_MODE_CBC'CRYPT_MODE_CBC);
/**
 * Encrypt / decrypt using the Cipher Feedback mode.
 *
 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
 */
define('CRYPT_RIJNDAEL_MODE_CFB'CRYPT_MODE_CFB);
/**
 * Encrypt / decrypt using the Cipher Feedback mode.
 *
 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
 */
define('CRYPT_RIJNDAEL_MODE_OFB'CRYPT_MODE_OFB);
/**#@-*/

/**
 * Pure-PHP implementation of Rijndael.
 *
 * @package Crypt_Rijndael
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Crypt_Rijndael extends Crypt_Base
{
    
/**
     * The default password key_size used by setPassword()
     *
     * @see Crypt_Base::password_key_size
     * @see Crypt_Base::setPassword()
     * @var Integer
     * @access private
     */
    
var $password_key_size 16;

    
/**
     * The namespace used by the cipher for its constants.
     *
     * @see Crypt_Base::const_namespace
     * @var String
     * @access private
     */
    
var $const_namespace 'RIJNDAEL';

    
/**
     * The mcrypt specific name of the cipher
     *
     * Mcrypt is useable for 128/192/256-bit $block_size/$key_size. For 160/224 not.
     * Crypt_Rijndael determines automatically whether mcrypt is useable
     * or not for the current $block_size/$key_size.
     * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
     *
     * @see Crypt_Base::cipher_name_mcrypt
     * @see Crypt_Base::engine
     * @see isValidEngine()
     * @var String
     * @access private
     */
    
var $cipher_name_mcrypt 'rijndael-128';

    
/**
     * The default salt used by setPassword()
     *
     * @see Crypt_Base::password_default_salt
     * @see Crypt_Base::setPassword()
     * @var String
     * @access private
     */
    
var $password_default_salt 'phpseclib';

    
/**
     * Has the key length explicitly been set or should it be derived from the key, itself?
     *
     * @see setKeyLength()
     * @var Boolean
     * @access private
     */
    
var $explicit_key_length false;

    
/**
     * The Key Schedule
     *
     * @see _setup()
     * @var Array
     * @access private
     */
    
var $w;

    
/**
     * The Inverse Key Schedule
     *
     * @see _setup()
     * @var Array
     * @access private
     */
    
var $dw;

    
/**
     * The Block Length divided by 32
     *
     * @see setBlockLength()
     * @var Integer
     * @access private
     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4.  Exists in conjunction with $block_size
     *    because the encryption / decryption / key schedule creation requires this number and not $block_size.  We could
     *    derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.
     */
    
var $Nb 4;

    
/**
     * The Key Length
     *
     * @see setKeyLength()
     * @var Integer
     * @access private
     * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $Nk
     *    because the encryption / decryption / key schedule creation requires this number and not $key_size.  We could
     *    derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.
     */
    
var $key_size 16;

    
/**
     * The Key Length divided by 32
     *
     * @see setKeyLength()
     * @var Integer
     * @access private
     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
     */
    
var $Nk 4;

    
/**
     * The Number of Rounds
     *
     * @var Integer
     * @access private
     * @internal The max value is 14, the min value is 10.
     */
    
var $Nr;

    
/**
     * Shift offsets
     *
     * @var Array
     * @access private
     */
    
var $c;

    
/**
     * Holds the last used key- and block_size information
     *
     * @var Array
     * @access private
     */
    
var $kl;

    
/**
     * Default Constructor.
     *
     * Determines whether or not the mcrypt extension should be used.
     *
     * $mode could be:
     *
     * - CRYPT_RIJNDAEL_MODE_ECB
     *
     * - CRYPT_RIJNDAEL_MODE_CBC
     *
     * - CRYPT_RIJNDAEL_MODE_CTR
     *
     * - CRYPT_RIJNDAEL_MODE_CFB
     *
     * - CRYPT_RIJNDAEL_MODE_OFB
     *
     * If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
     *
     * @see Crypt_Base::Crypt_Base()
     * @param optional Integer $mode
     * @access public
     */
    
function Crypt_Rijndael($mode CRYPT_RIJNDAEL_MODE_CBC)
    {
        
parent::Crypt_Base($mode);
    }

    
/**
     * Sets the key.
     *
     * Keys can be of any length.  Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
     * whose length is a multiple of 32.  If the key is less than 256-bits and the key length isn't set, we round the length
     * up to the closest valid key length, padding $key with null bytes.  If the key is more than 256-bits, we trim the
     * excess bits.
     *
     * If the key is not explicitly set, it'll be assumed to be all null bytes.
     *
     * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
     *
     * @see Crypt_Base:setKey()
     * @see setKeyLength()
     * @access public
     * @param String $key
     */
    
function setKey($key)
    {
        if (!
$this->explicit_key_length) {
            
$length strlen($key);
            switch (
true) {
                case 
$length <= 16:
                    
$this->key_size 16;
                    break;
                case 
$length <= 20:
                    
$this->key_size 20;
                    break;
                case 
$length <= 24:
                    
$this->key_size 24;
                    break;
                case 
$length <= 28:
                    
$this->key_size 28;
                    break;
                default:
                    
$this->key_size 32;
            }
        }
        
parent::setKey($key);
    }

    
/**
     * Sets the key length
     *
     * Valid key lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
     * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
     *
     * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
     *       and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
     *       192/256 bits as, for example, mcrypt will do.
     *
     *       That said, if you want be compatible with other Rijndael and AES implementations,
     *       you should not setKeyLength(160) or setKeyLength(224).
     *
     * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
     *             the mcrypt php extension, even if available.
     *             This results then in slower encryption.
     *
     * @access public
     * @param Integer $length
     */
    
function setKeyLength($length)
    {
        switch (
true) {
            case 
$length == 160:
                
$this->key_size 20;
                break;
            case 
$length == 224:
                
$this->key_size 28;
                break;
            case 
$length <= 128:
                
$this->key_size 16;
                break;
            case 
$length <= 192:
                
$this->key_size 24;
                break;
            default:
                
$this->key_size 32;
        }

        
$this->explicit_key_length true;
        
$this->changed true;
        
$this->_setEngine();
    }

    
/**
     * Sets the block length
     *
     * Valid block lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
     * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
     *
     * @access public
     * @param Integer $length
     */
    
function setBlockLength($length)
    {
        
$length >>= 5;
        if (
$length 8) {
            
$length 8;
        } elseif (
$length 4) {
            
$length 4;
        }
        
$this->Nb $length;
        
$this->block_size $length << 2;
        
$this->changed true;
        
$this->_setEngine();
    }

    
/**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
     *
     * @see Crypt_Base::Crypt_Base()
     * @param Integer $engine
     * @access public
     * @return Boolean
     */
    
function isValidEngine($engine)
    {
        switch (
$engine) {
            case 
CRYPT_ENGINE_OPENSSL:
                if (
$this->block_size != 16) {
                    return 
false;
                }
                
$this->cipher_name_openssl_ecb 'aes-' . ($this->key_size << 3) . '-ecb';
                
$this->cipher_name_openssl 'aes-' . ($this->key_size << 3) . '-' $this->_openssl_translate_mode();
                break;
            case 
CRYPT_ENGINE_MCRYPT:
                
$this->cipher_name_mcrypt 'rijndael-' . ($this->block_size << 3);
                if (
$this->key_size 8) { // is it a 160/224-bit key?
                    // mcrypt is not usable for them, only for 128/192/256-bit keys
                    
return false;
                }
        }

        return 
parent::isValidEngine($engine);
    }

    
/**
     * Setup the CRYPT_ENGINE_MCRYPT $engine
     *
     * @see Crypt_Base::_setupMcrypt()
     * @access private
     */
    
function _setupMcrypt()
    {
        
$this->key str_pad(substr($this->key0$this->key_size), $this->key_size"");
        
parent::_setupMcrypt();
    }

    
/**
     * Encrypts a block
     *
     * @access private
     * @param String $in
     * @return String
     */
    
function _encryptBlock($in)
    {
        static 
$tables;
        if (empty(
$tables)) {
            
$tables = &$this->_getTables();
        }
        
$t0   $tables[0];
        
$t1   $tables[1];
        
$t2   $tables[2];
        
$t3   $tables[3];
        
$sbox $tables[4];

        
$state = array();
        
$words unpack('N*'$in);

        
$c $this->c;
        
$w $this->w;
        
$Nb $this->Nb;
        
$Nr $this->Nr;

        
// addRoundKey
        
$wc $Nb 1;
        foreach (
$words as $word) {
            
$state[] = $word $w[++$wc];
        }

        
// fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
        // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
        // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
        // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
        // Unfortunately, the description given there is not quite correct.  Per aes.spec.v316.pdf#page=19 [1],
        // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.

        // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
        
$temp = array();
        for (
$round 1$round $Nr; ++$round) {
            
$i 0// $c[0] == 0
            
$j $c[1];
            
$k $c[2];
            
$l $c[3];

            while (
$i $Nb) {
                
$temp[$i] = $t0[$state[$i] >> 24 0x000000FF] ^
                            
$t1[$state[$j] >> 16 0x000000FF] ^
                            
$t2[$state[$k] >>  0x000000FF] ^
                            
$t3[$state[$l]       & 0x000000FF] ^
                            
$w[++$wc];
                ++
$i;
                
$j = ($j 1) % $Nb;
                
$k = ($k 1) % $Nb;
                
$l = ($l 1) % $Nb;
            }
            
$state $temp;
        }

        
// subWord
        
for ($i 0$i $Nb; ++$i) {
            
$state[$i] =   $sbox[$state[$i]       & 0x000000FF]        |
                          (
$sbox[$state[$i] >>  0x000000FF] <<  8) |
                          (
$sbox[$state[$i] >> 16 0x000000FF] << 16) |
                          (
$sbox[$state[$i] >> 24 0x000000FF] << 24);
        }

        
// shiftRows + addRoundKey
        
$i 0// $c[0] == 0
        
$j $c[1];
        
$k $c[2];
        
$l $c[3];
        while (
$i $Nb) {
            
$temp[$i] = ($state[$i] & 0xFF000000) ^
                        (
$state[$j] & 0x00FF0000) ^
                        (
$state[$k] & 0x0000FF00) ^
                        (
$state[$l] & 0x000000FF) ^
                         
$w[$i];
            ++
$i;
            
$j = ($j 1) % $Nb;
            
$k = ($k 1) % $Nb;
            
$l = ($l 1) % $Nb;
        }

        switch (
$Nb) {
            case 
8:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
            case 
7:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
            case 
6:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
            case 
5:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
            default:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3]);
        }
    }

    
/**
     * Decrypts a block
     *
     * @access private
     * @param String $in
     * @return String
     */
    
function _decryptBlock($in)
    {
        static 
$invtables;
        if (empty(
$invtables)) {
            
$invtables = &$this->_getInvTables();
        }
        
$dt0   $invtables[0];
        
$dt1   $invtables[1];
        
$dt2   $invtables[2];
        
$dt3   $invtables[3];
        
$isbox $invtables[4];

        
$state = array();
        
$words unpack('N*'$in);

        
$c  $this->c;
        
$dw $this->dw;
        
$Nb $this->Nb;
        
$Nr $this->Nr;

        
// addRoundKey
        
$wc $Nb 1;
        foreach (
$words as $word) {
            
$state[] = $word $dw[++$wc];
        }

        
$temp = array();
        for (
$round $Nr 1$round 0; --$round) {
            
$i 0// $c[0] == 0
            
$j $Nb $c[1];
            
$k $Nb $c[2];
            
$l $Nb $c[3];

            while (
$i $Nb) {
                
$temp[$i] = $dt0[$state[$i] >> 24 0x000000FF] ^
                            
$dt1[$state[$j] >> 16 0x000000FF] ^
                            
$dt2[$state[$k] >>  0x000000FF] ^
                            
$dt3[$state[$l]       & 0x000000FF] ^
                            
$dw[++$wc];
                ++
$i;
                
$j = ($j 1) % $Nb;
                
$k = ($k 1) % $Nb;
                
$l = ($l 1) % $Nb;
            }
            
$state $temp;
        }

        
// invShiftRows + invSubWord + addRoundKey
        
$i 0// $c[0] == 0
        
$j $Nb $c[1];
        
$k $Nb $c[2];
        
$l $Nb $c[3];

        while (
$i $Nb) {
            
$word = ($state[$i] & 0xFF000000) |
                    (
$state[$j] & 0x00FF0000) |
                    (
$state[$k] & 0x0000FF00) |
                    (
$state[$l] & 0x000000FF);

            
$temp[$i] = $dw[$i] ^ ($isbox[$word       0x000000FF]        |
                                  (
$isbox[$word >>  0x000000FF] <<  8) |
                                  (
$isbox[$word >> 16 0x000000FF] << 16) |
                                  (
$isbox[$word >> 24 0x000000FF] << 24));
            ++
$i;
            
$j = ($j 1) % $Nb;
            
$k = ($k 1) % $Nb;
            
$l = ($l 1) % $Nb;
        }

        switch (
$Nb) {
            case 
8:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
            case 
7:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
            case 
6:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
            case 
5:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
            default:
                return 
pack('N*'$temp[0], $temp[1], $temp[2], $temp[3]);
        }
    }

    
/**
     * Setup the key (expansion)
     *
     * @see Crypt_Base::_setupKey()
     * @access private
     */
    
function _setupKey()
    {
        
// Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
        // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
        
static $rcon = array(0,
            
0x010000000x020000000x040000000x080000000x10000000,
            
0x200000000x400000000x800000000x1B0000000x36000000,
            
0x6C0000000xD80000000xAB0000000x4D0000000x9A000000,
            
0x2F0000000x5E0000000xBC0000000x630000000xC6000000,
            
0x970000000x350000000x6A0000000xD40000000xB3000000,
            
0x7D0000000xFA0000000xEF0000000xC50000000x91000000
        
);

        
$this->key str_pad(substr($this->key0$this->key_size), $this->key_size"");

        if (isset(
$this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) {
            
// already expanded
            
return;
        }
        
$this->kl = array('key' => $this->key'key_size' => $this->key_size'block_size' => $this->block_size);

        
$this->Nk $this->key_size >> 2;
        
// see Rijndael-ammended.pdf#page=44
        
$this->Nr max($this->Nk$this->Nb) + 6;

        
// shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
        //     "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
        // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
        //     "Table 2: Shift offsets for different block lengths"
        
switch ($this->Nb) {
            case 
4:
            case 
5:
            case 
6:
                
$this->= array(0123);
                break;
            case 
7:
                
$this->= array(0124);
                break;
            case 
8:
                
$this->= array(0134);
        }

        
$w array_values(unpack('N*words'$this->key));

        
$length $this->Nb * ($this->Nr 1);
        for (
$i $this->Nk$i $length$i++) {
            
$temp $w[$i 1];
            if (
$i $this->Nk == 0) {
                
// according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
                // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
                // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
                // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
                
$temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
                
$temp $this->_subWord($temp) ^ $rcon[$i $this->Nk];
            } elseif (
$this->Nk && $i $this->Nk == 4) {
                
$temp $this->_subWord($temp);
            }
            
$w[$i] = $w[$i $this->Nk] ^ $temp;
        }

        
// convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
        // and generate the inverse key schedule.  more specifically,
        // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
        // "The key expansion for the Inverse Cipher is defined as follows:
        //        1. Apply the Key Expansion.
        //        2. Apply InvMixColumn to all Round Keys except the first and the last one."
        // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
        
list($dt0$dt1$dt2$dt3) = $this->_getInvTables();
        
$temp $this->$this->dw = array();
        for (
$i $row $col 0$i $length$i++, $col++) {
            if (
$col == $this->Nb) {
                if (
$row == 0) {
                    
$this->dw[0] = $this->w[0];
                } else {
                    
// subWord + invMixColumn + invSubWord = invMixColumn
                    
$j 0;
                    while (
$j $this->Nb) {
                        
$dw $this->_subWord($this->w[$row][$j]);
                        
$temp[$j] = $dt0[$dw >> 24 0x000000FF] ^
                                    
$dt1[$dw >> 16 0x000000FF] ^
                                    
$dt2[$dw >>  0x000000FF] ^
                                    
$dt3[$dw       0x000000FF];
                        
$j++;
                    }
                    
$this->dw[$row] = $temp;
                }

                
$col 0;
                
$row++;
            }
            
$this->w[$row][$col] = $w[$i];
        }

        
$this->dw[$row] = $this->w[$row];

        
// Converting to 1-dim key arrays (both ascending)
        
$this->dw array_reverse($this->dw);
        
$w  array_pop($this->w);
        
$dw array_pop($this->dw);
        foreach (
$this->as $r => $wr) {
            foreach (
$wr as $c => $wc) {
                
$w[]  = $wc;
                
$dw[] = $this->dw[$r][$c];
            }
        }
        
$this->w  $w;
        
$this->dw $dw;
    }

    
/**
     * Performs S-Box substitutions
     *
     * @access private
     * @param Integer $word
     */
    
function _subWord($word)
    {
        static 
$sbox;
        if (empty(
$sbox)) {
            list(,,,, 
$sbox) = $this->_getTables();
        }

        return  
$sbox[$word       0x000000FF]        |
               (
$sbox[$word >>  0x000000FF] <<  8) |
               (
$sbox[$word >> 16 0x000000FF] << 16) |
               (
$sbox[$word >> 24 0x000000FF] << 24);
    }

    
/**
     * Provides the mixColumns and sboxes tables
     *
     * @see Crypt_Rijndael:_encryptBlock()
     * @see Crypt_Rijndael:_setupInlineCrypt()
     * @see Crypt_Rijndael:_subWord()
     * @access private
     * @return Array &$tables
     */
    
function &_getTables()
    {
        static 
$tables;
        if (empty(
$tables)) {
            
// according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
            // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
            // those are the names we'll use.
            
$t3 array_map('intval', array(
                
// with array_map('intval', ...) we ensure we have only int's and not
                // some slower floats converted by php automatically on high values
                
0x6363A5C60x7C7C84F80x777799EE0x7B7B8DF60xF2F20DFF0x6B6BBDD60x6F6FB1DE0xC5C55491,
                
0x303050600x010103020x6767A9CE0x2B2B7D560xFEFE19E70xD7D762B50xABABE64D0x76769AEC,
                
0xCACA458F0x82829D1F0xC9C940890x7D7D87FA0xFAFA15EF0x5959EBB20x4747C98E0xF0F00BFB,
                
0xADADEC410xD4D467B30xA2A2FD5F0xAFAFEA450x9C9CBF230xA4A4F7530x727296E40xC0C05B9B,
                
0xB7B7C2750xFDFD1CE10x9393AE3D0x26266A4C0x36365A6C0x3F3F417E0xF7F702F50xCCCC4F83,
                
0x34345C680xA5A5F4510xE5E534D10xF1F108F90x717193E20xD8D873AB0x313153620x15153F2A,
                
0x04040C080xC7C752950x232365460xC3C35E9D0x181828300x9696A1370x05050F0A0x9A9AB52F,
                
0x0707090E0x121236240x80809B1B0xE2E23DDF0xEBEB26CD0x2727694E0xB2B2CD7F0x75759FEA,
                
0x09091B120x83839E1D0x2C2C74580x1A1A2E340x1B1B2D360x6E6EB2DC0x5A5AEEB40xA0A0FB5B,
                
0x5252F6A40x3B3B4D760xD6D661B70xB3B3CE7D0x29297B520xE3E33EDD0x2F2F715E0x84849713,
                
0x5353F5A60xD1D168B90x000000000xEDED2CC10x202060400xFCFC1FE30xB1B1C8790x5B5BEDB6,
                
0x6A6ABED40xCBCB468D0xBEBED9670x39394B720x4A4ADE940x4C4CD4980x5858E8B00xCFCF4A85,
                
0xD0D06BBB0xEFEF2AC50xAAAAE54F0xFBFB16ED0x4343C5860x4D4DD79A0x333355660x85859411,
                
0x4545CF8A0xF9F910E90x020206040x7F7F81FE0x5050F0A00x3C3C44780x9F9FBA250xA8A8E34B,
                
0x5151F3A20xA3A3FE5D0x4040C0800x8F8F8A050x9292AD3F0x9D9DBC210x383848700xF5F504F1,
                
0xBCBCDF630xB6B6C1770xDADA75AF0x212163420x101030200xFFFF1AE50xF3F30EFD0xD2D26DBF,
                
0xCDCD4C810x0C0C14180x131335260xECEC2FC30x5F5FE1BE0x9797A2350x4444CC880x1717392E,
                
0xC4C457930xA7A7F2550x7E7E82FC0x3D3D477A0x6464ACC80x5D5DE7BA0x19192B320x737395E6,
                
0x6060A0C00x818198190x4F4FD19E0xDCDC7FA30x222266440x2A2A7E540x9090AB3B0x8888830B,
                
0x4646CA8C0xEEEE29C70xB8B8D36B0x14143C280xDEDE79A70x5E5EE2BC0x0B0B1D160xDBDB76AD,
                
0xE0E03BDB0x323256640x3A3A4E740x0A0A1E140x4949DB920x06060A0C0x24246C480x5C5CE4B8,
                
0xC2C25D9F0xD3D36EBD0xACACEF430x6262A6C40x9191A8390x9595A4310xE4E437D30x79798BF2,
                
0xE7E732D50xC8C8438B0x3737596E0x6D6DB7DA0x8D8D8C010xD5D564B10x4E4ED29C0xA9A9E049,
                
0x6C6CB4D80x5656FAAC0xF4F407F30xEAEA25CF0x6565AFCA0x7A7A8EF40xAEAEE9470x08081810,
                
0xBABAD56F0x787888F00x25256F4A0x2E2E725C0x1C1C24380xA6A6F1570xB4B4C7730xC6C65197,
                
0xE8E823CB0xDDDD7CA10x74749CE80x1F1F213E0x4B4BDD960xBDBDDC610x8B8B860D0x8A8A850F,
                
0x707090E00x3E3E427C0xB5B5C4710x6666AACC0x4848D8900x030305060xF6F601F70x0E0E121C,
                
0x6161A3C20x35355F6A0x5757F9AE0xB9B9D0690x868691170xC1C158990x1D1D273A0x9E9EB927,
                
0xE1E138D90xF8F813EB0x9898B32B0x111133220x6969BBD20xD9D970A90x8E8E89070x9494A733,
                
0x9B9BB62D0x1E1E223C0x878792150xE9E920C90xCECE49870x5555FFAA0x282878500xDFDF7AA5,
                
0x8C8C8F030xA1A1F8590x898980090x0D0D171A0xBFBFDA650xE6E631D70x4242C6840x6868B8D0,
                
0x4141C3820x9999B0290x2D2D775A0x0F0F111E0xB0B0CB7B0x5454FCA80xBBBBD66D0x16163A2C
            
));

            foreach (
$t3 as $t3i) {
                
$t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >>  8) & 0x00FFFFFF);
                
$t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
                
$t2[] = (($t3i <<  8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
            }

            
$tables = array(
                
// The Precomputed mixColumns tables t0 - t3
                
$t0,
                
$t1,
                
$t2,
                
$t3,
                
// The SubByte S-Box
                
array(
                    
0x630x7C0x770x7B0xF20x6B0x6F0xC50x300x010x670x2B0xFE0xD70xAB0x76,
                    
0xCA0x820xC90x7D0xFA0x590x470xF00xAD0xD40xA20xAF0x9C0xA40x720xC0,
                    
0xB70xFD0x930x260x360x3F0xF70xCC0x340xA50xE50xF10x710xD80x310x15,
                    
0x040xC70x230xC30x180x960x050x9A0x070x120x800xE20xEB0x270xB20x75,
                    
0x090x830x2C0x1A0x1B0x6E0x5A0xA00x520x3B0xD60xB30x290xE30x2F0x84,
                    
0x530xD10x000xED0x200xFC0xB10x5B0x6A0xCB0xBE0x390x4A0x4C0x580xCF,
                    
0xD00xEF0xAA0xFB0x430x4D0x330x850x450xF90x020x7F0x500x3C0x9F0xA8,
                    
0x510xA30x400x8F0x920x9D0x380xF50xBC0xB60xDA0x210x100xFF0xF30xD2,
                    
0xCD0x0C0x130xEC0x5F0x970x440x170xC40xA70x7E0x3D0x640x5D0x190x73,
                    
0x600x810x4F0xDC0x220x2A0x900x880x460xEE0xB80x140xDE0x5E0x0B0xDB,
                    
0xE00x320x3A0x0A0x490x060x240x5C0xC20xD30xAC0x620x910x950xE40x79,
                    
0xE70xC80x370x6D0x8D0xD50x4E0xA90x6C0x560xF40xEA0x650x7A0xAE0x08,
                    
0xBA0x780x250x2E0x1C0xA60xB40xC60xE80xDD0x740x1F0x4B0xBD0x8B0x8A,
                    
0x700x3E0xB50x660x480x030xF60x0E0x610x350x570xB90x860xC10x1D0x9E,
                    
0xE10xF80x980x110x690xD90x8E0x940x9B0x1E0x870xE90xCE0x550x280xDF,
                    
0x8C0xA10x890x0D0xBF0xE60x420x680x410x990x2D0x0F0xB00x540xBB0x16
                
)
            );
        }
        return 
$tables;
    }

    
/**
     * Provides the inverse mixColumns and inverse sboxes tables
     *
     * @see Crypt_Rijndael:_decryptBlock()
     * @see Crypt_Rijndael:_setupInlineCrypt()
     * @see Crypt_Rijndael:_setupKey()
     * @access private
     * @return Array &$tables
     */
    
function &_getInvTables()
    {
        static 
$tables;
        if (empty(
$tables)) {
            
$dt3 array_map('intval', array(
                
0xF4A750510x4165537E0x17A4C31A0x275E963A0xAB6BCB3B0x9D45F11F0xFA58ABAC0xE303934B,
                
0x30FA55200x766DF6AD0xCC7691880x024C25F50xE5D7FC4F0x2ACBD7C50x354480260x62A38FB5,
                
0xB15A49DE0xBA1B67250xEA0E98450xFEC0E15D0x2F7502C30x4CF012810x4697A38D0xD3F9C66B,
                
0x8F5FE7030x929C95150x6D7AEBBF0x5259DA950xBE832DD40x7421D3580xE06929490xC9C8448E,
                
0xC2896A750x8E7978F40x583E6B990xB971DD270xE14FB6BE0x88AD17F00x20AC66C90xCE3AB47D,
                
0xDF4A18630x1A3182E50x513360970x537F45620x6477E0B10x6BAE84BB0x81A01CFE0x082B94F9,
                
0x486858700x45FD198F0xDE6C87940x7BF8B7520x73D323AB0x4B02E2720x1F8F57E30x55AB2A66,
                
0xEB2807B20xB5C2032F0xC57B9A860x3708A5D30x2887F2300xBFA5B2230x036ABA020x16825CED,
                
0xCF1C2B8A0x79B492A70x07F2F0F30x69E2A14E0xDAF4CD650x05BED5060x34621FD10xA6FE8AC4,
                
0x2E539D340xF355A0A20x8AE132050xF6EB75A40x83EC390B0x60EFAA400x719F065E0x6E1051BD,
                
0x218AF93E0xDD063D960x3E05AEDD0xE6BD464D0x548DB5910xC45D05710x06D46F040x5015FF60,
                
0x98FB24190xBDE997D60x4043CC890xD99E77670xE842BDB00x898B88070x195B38E70xC8EEDB79,
                
0x7C0A47A10x420FE97C0x841EC9F80x000000000x808683090x2BED48320x1170AC1E0x5A724E6C,
                
0x0EFFFBFD0x8538560F0xAED51E3D0x2D3927360x0FD9640A0x5CA621680x5B54D19B0x362E3A24,
                
0x0A67B10C0x57E70F930xEE96D2B40x9B919E1B0xC0C54F800xDC20A2610x774B695A0x121A161C,
                
0x93BA0AE20xA02AE5C00x22E0433C0x1B171D120x090D0B0E0x8BC7ADF20xB6A8B92D0x1EA9C814,
                
0xF11985570x75074CAF0x99DDBBEE0x7F60FDA30x01269FF70x72F5BC5C0x663BC5440xFB7E345B,
                
0x4329768B0x23C6DCCB0xEDFC68B60xE4F163B80x31DCCAD70x638510420x972240130xC6112084,
                
0x4A247D850xBB3DF8D20xF93211AE0x29A16DC70x9E2F4B1D0xB230F3DC0x8652EC0D0xC1E3D077,
                
0xB3166C2B0x70B999A90x9448FA110xE96422470xFC8CC4A80xF03F1AA00x7D2CD8560x3390EF22,
                
0x494EC7870x38D1C1D90xCAA2FE8C0xD40B36980xF581CFA60x7ADE28A50xB78E26DA0xADBFA43F,
                
0x3A9DE42C0x78920D500x5FCC9B6A0x7E4662540x8D13C2F60xD8B8E8900x39F75E2E0xC3AFF582,
                
0x5D80BE9F0xD0937C690xD52DA96F0x2512B3CF0xAC993BC80x187DA7100x9C636EE80x3BBB7BDB,
                
0x267809CD0x5918F46E0x9AB701EC0x4F9AA8830x956E65E60xFFE67EAA0xBCCF08210x15E8E6EF,
                
0xE79BD9BA0x6F36CE4A0x9F09D4EA0xB07CD6290xA4B2AF310x3F23312A0xA59430C60xA266C035,
                
0x4EBC37740x82CAA6FC0x90D0B0E00xA7D815330x04984AF10xECDAF7410xCD500E7F0x91F62F17,
                
0x4DD68D760xEFB04D430xAA4D54CC0x9604DFE40xD1B5E39E0x6A881B4C0x2C1FB8C10x65517F46,
                
0x5EEA049D0x8C355D010x877473FA0x0B412EFB0x671D5AB30xDBD252920x105633E90xD647136D,
                
0xD7618C9A0xA10C7A370xF8148E590x133C89EB0xA927EECE0x61C935B70x1CE5EDE10x47B13C7A,
                
0xD2DF599C0xF2733F550x14CE79180xC737BF730xF7CDEA530xFDAA5B5F0x3D6F14DF0x44DB8678,
                
0xAFF381CA0x68C43EB90x24342C380xA3405FC20x1DC372160xE2250CBC0x3C498B280x0D9541FF,
                
0xA80171390x0CB3DE080xB4E49CD80x56C190640xCB84617B0x32B670D50x6C5C74480xB85742D0
            
));

            foreach (
$dt3 as $dt3i) {
                
$dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >>  8) & 0x00FFFFFF);
                
$dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
                
$dt2[] = (($dt3i <<  8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
            };

            
$tables = array(
                
// The Precomputed inverse mixColumns tables dt0 - dt3
                
$dt0,
                
$dt1,
                
$dt2,
                
$dt3,
                
// The inverse SubByte S-Box
                
array(
                    
0x520x090x6A0xD50x300x360xA50x380xBF0x400xA30x9E0x810xF30xD70xFB,
                    
0x7C0xE30x390x820x9B0x2F0xFF0x870x340x8E0x430x440xC40xDE0xE90xCB,
                    
0x540x7B0x940x320xA60xC20x230x3D0xEE0x4C0x950x0B0x420xFA0xC30x4E,
                    
0x080x2E0xA10x660x280xD90x240xB20x760x5B0xA20x490x6D0x8B0xD10x25,
                    
0x720xF80xF60x640x860x680x980x160xD40xA40x5C0xCC0x5D0x650xB60x92,
                    
0x6C0x700x480x500xFD0xED0xB90xDA0x5E0x150x460x570xA70x8D0x9D0x84,
                    
0x900xD80xAB0x000x8C0xBC0xD30x0A0xF70xE40x580x050xB80xB30x450x06,
                    
0xD00x2C0x1E0x8F0xCA0x3F0x0F0x020xC10xAF0xBD0x030x010x130x8A0x6B,
                    
0x3A0x910x110x410x4F0x670xDC0xEA0x970xF20xCF0xCE0xF00xB40xE60x73,
                    
0x960xAC0x740x220xE70xAD0x350x850xE20xF90x370xE80x1C0x750xDF0x6E,
                    
0x470xF10x1A0x710x1D0x290xC50x890x6F0xB70x620x0E0xAA0x180xBE0x1B,
                    
0xFC0x560x3E0x4B0xC60xD20x790x200x9A0xDB0xC00xFE0x780xCD0x5A0xF4,
                    
0x1F0xDD0xA80x330x880x070xC70x310xB10x120x100x590x270x800xEC0x5F,
                    
0x600x510x7F0xA90x190xB50x4A0x0D0x2D0xE50x7A0x9F0x930xC90x9C0xEF,
                    
0xA00xE00x3B0x4D0xAE0x2A0xF50xB00xC80xEB0xBB0x3C0x830x530x990x61,
                    
0x170x2B0x040x7E0xBA0x770xD60x260xE10x690x140x630x550x210x0C0x7D
                
)
            );
        }
        return 
$tables;
    }

    
/**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see Crypt_Base::_setupInlineCrypt()
     * @access private
     */
    
function _setupInlineCrypt()
    {
        
// Note: _setupInlineCrypt() will be called only if $this->changed === true
        // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
        // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.

        
$lambda_functions =& Crypt_Rijndael::_getLambdaFunctions();

        
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
        // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
        // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
        
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );

        
// Generation of a uniqe hash for our generated code
        
$code_hash "Crypt_Rijndael, {$this->mode}{$this->Nr}{$this->Nb}";
        if (
$gen_hi_opt_code) {
            
$code_hash str_pad($code_hash32) . $this->_hashInlineCryptFunction($this->key);
        }

        if (!isset(
$lambda_functions[$code_hash])) {
            switch (
true) {
                case 
$gen_hi_opt_code:
                    
// The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
                    
$w  $this->w;
                    
$dw $this->dw;
                    
$init_encrypt '';
                    
$init_decrypt '';
                    break;
                default:
                    for (
$i 0$cw count($this->w); $i $cw; ++$i) {
                        
$w[]  = '$w['  $i ']';
                        
$dw[] = '$dw[' $i ']';
                    }
                    
$init_encrypt '$w  = $self->w;';
                    
$init_decrypt '$dw = $self->dw;';
            }

            
$Nr $this->Nr;
            
$Nb $this->Nb;
            
$c  $this->c;

            
// Generating encrypt code:
            
$init_encrypt.= '
                static $tables;
                if (empty($tables)) {
                    $tables = &$self->_getTables();
                }
                $t0   = $tables[0];
                $t1   = $tables[1];
                $t2   = $tables[2];
                $t3   = $tables[3];
                $sbox = $tables[4];
            '
;

            
$s  'e';
            
$e  's';
            
$wc $Nb 1;

            
// Preround: addRoundKey
            
$encrypt_block '$in = unpack("N*", $in);'."n";
            for (
$i 0$i $Nb; ++$i) {
                
$encrypt_block .= '$s'.$i.' = $in['.($i 1).'] ^ '.$w[++$wc].";n";
            }

            
// Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
            
for ($round 1$round $Nr; ++$round) {
                list(
$s$e) = array($e$s);
                for (
$i 0$i $Nb; ++$i) {
                    
$encrypt_block.=
                        
'$'.$e.$i.' =
                        $t0[($'
.$s.$i                  .' >> 24) & 0xff] ^
                        $t1[($'
.$s.(($i $c[1]) % $Nb).' >> 16) & 0xff] ^
                        $t2[($'
.$s.(($i $c[2]) % $Nb).' >>  8) & 0xff] ^
                        $t3[ $'
.$s.(($i $c[3]) % $Nb).'        & 0xff] ^
                        '
.$w[++$wc].";n";
                }
            }

            
// Finalround: subWord + shiftRows + addRoundKey
            
for ($i 0$i $Nb; ++$i) {
                
$encrypt_block.=
                    
'$'.$e.$i.' =
                     $sbox[ $'
.$e.$i.'        & 0xff]        |
                    ($sbox[($'
.$e.$i.' >>  8) & 0xff] <<  8) |
                    ($sbox[($'
.$e.$i.' >> 16) & 0xff] << 16) |
                    ($sbox[($'
.$e.$i.' >> 24) & 0xff] << 24);'."n";
            }
            
$encrypt_block .= '$in = pack("N*"'."n";
            for (
$i 0$i $Nb; ++$i) {
                
$encrypt_block.= ',
                    ($'
.$e.$i                  .' & '.((int)0xFF000000).') ^
                    ($'
.$e.(($i $c[1]) % $Nb).' &         0x00FF0000   ) ^
                    ($'
.$e.(($i $c[2]) % $Nb).' &         0x0000FF00   ) ^
                    ($'
.$e.(($i $c[3]) % $Nb).' &         0x000000FF   ) ^
                    '
.$w[$i]."n";
            }
            
$encrypt_block .= ');';

            
// Generating decrypt code:
            
$init_decrypt.= '
                static $invtables;
                if (empty($invtables)) {
                    $invtables = &$self->_getInvTables();
                }
                $dt0   = $invtables[0];
                $dt1   = $invtables[1];
                $dt2   = $invtables[2];
                $dt3   = $invtables[3];
                $isbox = $invtables[4];
            '
;

            
$s  'e';
            
$e  's';
            
$wc $Nb 1;

            
// Preround: addRoundKey
            
$decrypt_block '$in = unpack("N*", $in);'."n";
            for (
$i 0$i $Nb; ++$i) {
                
$decrypt_block .= '$s'.$i.' = $in['.($i 1).'] ^ '.$dw[++$wc].';'."n";
            }

            
// Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
            
for ($round 1$round $Nr; ++$round) {
                list(
$s$e) = array($e$s);
                for (
$i 0$i $Nb; ++$i) {
                    
$decrypt_block.=
                        
'$'.$e.$i.' =
                        $dt0[($'
.$s.$i                        .' >> 24) & 0xff] ^
                        $dt1[($'
.$s.(($Nb $i $c[1]) % $Nb).' >> 16) & 0xff] ^
                        $dt2[($'
.$s.(($Nb $i $c[2]) % $Nb).' >>  8) & 0xff] ^
                        $dt3[ $'
.$s.(($Nb $i $c[3]) % $Nb).'        & 0xff] ^
                        '
.$dw[++$wc].";n";
                }
            }

            
// Finalround: subWord + shiftRows + addRoundKey
            
for ($i 0$i $Nb; ++$i) {
                
$decrypt_block.=
                    
'$'.$e.$i.' =
                     $isbox[ $'
.$e.$i.'        & 0xff]        |
                    ($isbox[($'
.$e.$i.' >>  8) & 0xff] <<  8) |
                    ($isbox[($'
.$e.$i.' >> 16) & 0xff] << 16) |
                    ($isbox[($'
.$e.$i.' >> 24) & 0xff] << 24);'."n";
            }
            
$decrypt_block .= '$in = pack("N*"'."n";
            for (
$i 0$i $Nb; ++$i) {
                
$decrypt_block.= ',
                    ($'
.$e.$i.                        ' & '.((int)0xFF000000).') ^
                    ($'
.$e.(($Nb $i $c[1]) % $Nb).' &         0x00FF0000   ) ^
                    ($'
.$e.(($Nb $i $c[2]) % $Nb).' &         0x0000FF00   ) ^
                    ($'
.$e.(($Nb $i $c[3]) % $Nb).' &         0x000000FF   ) ^
                    '
.$dw[$i]."n";
            }
            
$decrypt_block .= ');';

            
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
                array(
                   
'init_crypt'    => '',
                   
'init_encrypt'  => $init_encrypt,
                   
'init_decrypt'  => $init_decrypt,
                   
'encrypt_block' => $encrypt_block,
                   
'decrypt_block' => $decrypt_block
                
)
            );
        }
        
$this->inline_crypt $lambda_functions[$code_hash];
    }
}
Онлайн: 0
Реклама