PageRenderTime 65ms CodeModel.GetById 12ms app.highlight 42ms RepoModel.GetById 2ms app.codeStats 0ms

/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Rijndael.php

https://github.com/sezuan/core
PHP | 1525 lines | 864 code | 102 blank | 559 comment | 103 complexity | 8f5bb1f10c659ab25b5e35ca3fbc8edd MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
   3
   4/**
   5 * Pure-PHP implementation of Rijndael.
   6 *
   7 * Does not use mcrypt, even when available, for reasons that are explained below.
   8 *
   9 * PHP versions 4 and 5
  10 *
  11 * If {@link Crypt_Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits.  If 
  12 * {@link Crypt_Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from 
  13 * {@link Crypt_Rijndael::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's 
  14 * 136-bits it'll be null-padded to 160-bits and 160 bits will be the key length until 
  15 * {@link Crypt_Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated.
  16 *
  17 * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length.  mcrypt, for example,
  18 * does not.  AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
  19 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
  20 * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224.  Indeed, 160 and 224
  21 * are first defined as valid key / block lengths in 
  22 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}: 
  23 * Extensions: Other block and Cipher Key lengths.
  24 *
  25 * {@internal The variable names are the same as those in 
  26 * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
  27 *
  28 * Here's a short example of how to use this library:
  29 * <code>
  30 * <?php
  31 *    include('Crypt/Rijndael.php');
  32 *
  33 *    $rijndael = new Crypt_Rijndael();
  34 *
  35 *    $rijndael->setKey('abcdefghijklmnop');
  36 *
  37 *    $size = 10 * 1024;
  38 *    $plaintext = '';
  39 *    for ($i = 0; $i < $size; $i++) {
  40 *        $plaintext.= 'a';
  41 *    }
  42 *
  43 *    echo $rijndael->decrypt($rijndael->encrypt($plaintext));
  44 * ?>
  45 * </code>
  46 *
  47 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
  48 * of this software and associated documentation files (the "Software"), to deal
  49 * in the Software without restriction, including without limitation the rights
  50 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  51 * copies of the Software, and to permit persons to whom the Software is
  52 * furnished to do so, subject to the following conditions:
  53 * 
  54 * The above copyright notice and this permission notice shall be included in
  55 * all copies or substantial portions of the Software.
  56 * 
  57 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  58 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  59 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  60 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  61 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  62 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  63 * THE SOFTWARE.
  64 *
  65 * @category   Crypt
  66 * @package    Crypt_Rijndael
  67 * @author     Jim Wigginton <terrafrost@php.net>
  68 * @copyright  MMVIII Jim Wigginton
  69 * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
  70 * @version    $Id: Rijndael.php,v 1.12 2010/02/09 06:10:26 terrafrost Exp $
  71 * @link       http://phpseclib.sourceforge.net
  72 */
  73
  74/**#@+
  75 * @access public
  76 * @see Crypt_Rijndael::encrypt()
  77 * @see Crypt_Rijndael::decrypt()
  78 */
  79/**
  80 * Encrypt / decrypt using the Counter mode.
  81 *
  82 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
  83 *
  84 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
  85 */
  86define('CRYPT_RIJNDAEL_MODE_CTR', -1);
  87/**
  88 * Encrypt / decrypt using the Electronic Code Book mode.
  89 *
  90 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
  91 */
  92define('CRYPT_RIJNDAEL_MODE_ECB', 1);
  93/**
  94 * Encrypt / decrypt using the Code Book Chaining mode.
  95 *
  96 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
  97 */
  98define('CRYPT_RIJNDAEL_MODE_CBC', 2);
  99/**
 100 * Encrypt / decrypt using the Cipher Feedback mode.
 101 *
 102 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
 103 */
 104define('CRYPT_RIJNDAEL_MODE_CFB', 3);
 105/**
 106 * Encrypt / decrypt using the Cipher Feedback mode.
 107 *
 108 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
 109 */
 110define('CRYPT_RIJNDAEL_MODE_OFB', 4);
 111/**#@-*/
 112
 113/**#@+
 114 * @access private
 115 * @see Crypt_Rijndael::Crypt_Rijndael()
 116 */
 117/**
 118 * Toggles the internal implementation
 119 */
 120define('CRYPT_RIJNDAEL_MODE_INTERNAL', 1);
 121/**
 122 * Toggles the mcrypt implementation
 123 */
 124define('CRYPT_RIJNDAEL_MODE_MCRYPT', 2);
 125/**#@-*/
 126
 127/**
 128 * Pure-PHP implementation of Rijndael.
 129 *
 130 * @author  Jim Wigginton <terrafrost@php.net>
 131 * @version 0.1.0
 132 * @access  public
 133 * @package Crypt_Rijndael
 134 */
 135class Crypt_Rijndael {
 136    /**
 137     * The Encryption Mode
 138     *
 139     * @see Crypt_Rijndael::Crypt_Rijndael()
 140     * @var Integer
 141     * @access private
 142     */
 143    var $mode;
 144
 145    /**
 146     * The Key
 147     *
 148     * @see Crypt_Rijndael::setKey()
 149     * @var String
 150     * @access private
 151     */
 152    var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 153
 154    /**
 155     * The Initialization Vector
 156     *
 157     * @see Crypt_Rijndael::setIV()
 158     * @var String
 159     * @access private
 160     */
 161    var $iv = '';
 162
 163    /**
 164     * A "sliding" Initialization Vector
 165     *
 166     * @see Crypt_Rijndael::enableContinuousBuffer()
 167     * @var String
 168     * @access private
 169     */
 170    var $encryptIV = '';
 171
 172    /**
 173     * A "sliding" Initialization Vector
 174     *
 175     * @see Crypt_Rijndael::enableContinuousBuffer()
 176     * @var String
 177     * @access private
 178     */
 179    var $decryptIV = '';
 180
 181    /**
 182     * Continuous Buffer status
 183     *
 184     * @see Crypt_Rijndael::enableContinuousBuffer()
 185     * @var Boolean
 186     * @access private
 187     */
 188    var $continuousBuffer = false;
 189
 190    /**
 191     * Padding status
 192     *
 193     * @see Crypt_Rijndael::enablePadding()
 194     * @var Boolean
 195     * @access private
 196     */
 197    var $padding = true;
 198
 199    /**
 200     * Does the key schedule need to be (re)calculated?
 201     *
 202     * @see setKey()
 203     * @see setBlockLength()
 204     * @see setKeyLength()
 205     * @var Boolean
 206     * @access private
 207     */
 208    var $changed = true;
 209
 210    /**
 211     * Has the key length explicitly been set or should it be derived from the key, itself?
 212     *
 213     * @see setKeyLength()
 214     * @var Boolean
 215     * @access private
 216     */
 217    var $explicit_key_length = false;
 218
 219    /**
 220     * The Key Schedule
 221     *
 222     * @see _setup()
 223     * @var Array
 224     * @access private
 225     */
 226    var $w;
 227
 228    /**
 229     * The Inverse Key Schedule
 230     *
 231     * @see _setup()
 232     * @var Array
 233     * @access private
 234     */
 235    var $dw;
 236
 237    /**
 238     * The Block Length
 239     *
 240     * @see setBlockLength()
 241     * @var Integer
 242     * @access private
 243     * @internal The max value is 32, the min value is 16.  All valid values are multiples of 4.  Exists in conjunction with
 244     *     $Nb because we need this value and not $Nb to pad strings appropriately.  
 245     */
 246    var $block_size = 16;
 247
 248    /**
 249     * The Block Length divided by 32
 250     *
 251     * @see setBlockLength()
 252     * @var Integer
 253     * @access private
 254     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4.  Exists in conjunction with $block_size 
 255     *    because the encryption / decryption / key schedule creation requires this number and not $block_size.  We could 
 256     *    derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
 257     *    of that, we'll just precompute it once.
 258     *
 259     */
 260    var $Nb = 4;
 261
 262    /**
 263     * The Key Length
 264     *
 265     * @see setKeyLength()
 266     * @var Integer
 267     * @access private
 268     * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $key_size
 269     *    because the encryption / decryption / key schedule creation requires this number and not $key_size.  We could 
 270     *    derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
 271     *    of that, we'll just precompute it once.
 272     */
 273    var $key_size = 16;
 274
 275    /**
 276     * The Key Length divided by 32
 277     *
 278     * @see setKeyLength()
 279     * @var Integer
 280     * @access private
 281     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
 282     */
 283    var $Nk = 4;
 284
 285    /**
 286     * The Number of Rounds
 287     *
 288     * @var Integer
 289     * @access private
 290     * @internal The max value is 14, the min value is 10.
 291     */
 292    var $Nr;
 293
 294    /**
 295     * Shift offsets
 296     *
 297     * @var Array
 298     * @access private
 299     */
 300    var $c;
 301
 302    /**
 303     * Precomputed mixColumns table
 304     *
 305     * @see Crypt_Rijndael()
 306     * @var Array
 307     * @access private
 308     */
 309    var $t0;
 310
 311    /**
 312     * Precomputed mixColumns table
 313     *
 314     * @see Crypt_Rijndael()
 315     * @var Array
 316     * @access private
 317     */
 318    var $t1;
 319
 320    /**
 321     * Precomputed mixColumns table
 322     *
 323     * @see Crypt_Rijndael()
 324     * @var Array
 325     * @access private
 326     */
 327    var $t2;
 328
 329    /**
 330     * Precomputed mixColumns table
 331     *
 332     * @see Crypt_Rijndael()
 333     * @var Array
 334     * @access private
 335     */
 336    var $t3;
 337
 338    /**
 339     * Precomputed invMixColumns table
 340     *
 341     * @see Crypt_Rijndael()
 342     * @var Array
 343     * @access private
 344     */
 345    var $dt0;
 346
 347    /**
 348     * Precomputed invMixColumns table
 349     *
 350     * @see Crypt_Rijndael()
 351     * @var Array
 352     * @access private
 353     */
 354    var $dt1;
 355
 356    /**
 357     * Precomputed invMixColumns table
 358     *
 359     * @see Crypt_Rijndael()
 360     * @var Array
 361     * @access private
 362     */
 363    var $dt2;
 364
 365    /**
 366     * Precomputed invMixColumns table
 367     *
 368     * @see Crypt_Rijndael()
 369     * @var Array
 370     * @access private
 371     */
 372    var $dt3;
 373
 374    /**
 375     * Is the mode one that is paddable?
 376     *
 377     * @see Crypt_Rijndael::Crypt_Rijndael()
 378     * @var Boolean
 379     * @access private
 380     */
 381    var $paddable = false;
 382
 383    /**
 384     * Encryption buffer for CTR, OFB and CFB modes
 385     *
 386     * @see Crypt_Rijndael::encrypt()
 387     * @var String
 388     * @access private
 389     */
 390    var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0);
 391
 392    /**
 393     * Decryption buffer for CTR, OFB and CFB modes
 394     *
 395     * @see Crypt_Rijndael::decrypt()
 396     * @var String
 397     * @access private
 398     */
 399    var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0);
 400
 401    /**
 402     * Default Constructor.
 403     *
 404     * Determines whether or not the mcrypt extension should be used.  $mode should only, at present, be
 405     * CRYPT_RIJNDAEL_MODE_ECB or CRYPT_RIJNDAEL_MODE_CBC.  If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
 406     *
 407     * @param optional Integer $mode
 408     * @return Crypt_Rijndael
 409     * @access public
 410     */
 411    function Crypt_Rijndael($mode = CRYPT_RIJNDAEL_MODE_CBC)
 412    {
 413        switch ($mode) {
 414            case CRYPT_RIJNDAEL_MODE_ECB:
 415            case CRYPT_RIJNDAEL_MODE_CBC:
 416                $this->paddable = true;
 417                $this->mode = $mode;
 418                break;
 419            case CRYPT_RIJNDAEL_MODE_CTR:
 420            case CRYPT_RIJNDAEL_MODE_CFB:
 421            case CRYPT_RIJNDAEL_MODE_OFB:
 422                $this->mode = $mode;
 423                break;
 424            default:
 425                $this->paddable = true;
 426                $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
 427        }
 428
 429        $t3 = &$this->t3;
 430        $t2 = &$this->t2;
 431        $t1 = &$this->t1;
 432        $t0 = &$this->t0;
 433
 434        $dt3 = &$this->dt3;
 435        $dt2 = &$this->dt2;
 436        $dt1 = &$this->dt1;
 437        $dt0 = &$this->dt0;
 438
 439        // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1), 
 440        // precomputed tables can be used in the mixColumns phase.  in that example, they're assigned t0...t3, so
 441        // those are the names we'll use.
 442        $t3 = array(
 443            0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, 
 444            0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 
 445            0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, 
 446            0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, 
 447            0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 
 448            0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, 
 449            0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, 
 450            0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 
 451            0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, 
 452            0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, 
 453            0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 
 454            0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, 
 455            0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, 
 456            0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 
 457            0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, 
 458            0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, 
 459            0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 
 460            0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, 
 461            0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, 
 462            0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 
 463            0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, 
 464            0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, 
 465            0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 
 466            0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, 
 467            0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, 
 468            0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 
 469            0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, 
 470            0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, 
 471            0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 
 472            0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, 
 473            0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, 
 474            0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
 475        );
 476
 477        $dt3 = array(
 478            0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, 
 479            0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 
 480            0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, 
 481            0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, 
 482            0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, 
 483            0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, 
 484            0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, 
 485            0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 
 486            0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, 
 487            0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, 
 488            0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, 
 489            0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, 
 490            0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, 
 491            0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, 
 492            0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, 
 493            0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, 
 494            0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, 
 495            0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, 
 496            0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, 
 497            0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, 
 498            0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, 
 499            0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, 
 500            0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 
 501            0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, 
 502            0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, 
 503            0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, 
 504            0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, 
 505            0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, 
 506            0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, 
 507            0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, 
 508            0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, 
 509            0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
 510        );
 511
 512        for ($i = 0; $i < 256; $i++) {
 513            $t2[] = (($t3[$i] <<  8) & 0xFFFFFF00) | (($t3[$i] >> 24) & 0x000000FF);
 514            $t1[] = (($t3[$i] << 16) & 0xFFFF0000) | (($t3[$i] >> 16) & 0x0000FFFF);
 515            $t0[] = (($t3[$i] << 24) & 0xFF000000) | (($t3[$i] >>  8) & 0x00FFFFFF);
 516
 517            $dt2[] = (($dt3[$i] <<  8) & 0xFFFFFF00) | (($dt3[$i] >> 24) & 0x000000FF);
 518            $dt1[] = (($dt3[$i] << 16) & 0xFFFF0000) | (($dt3[$i] >> 16) & 0x0000FFFF);
 519            $dt0[] = (($dt3[$i] << 24) & 0xFF000000) | (($dt3[$i] >>  8) & 0x00FFFFFF);
 520        }
 521    }
 522
 523    /**
 524     * Sets the key.
 525     *
 526     * Keys can be of any length.  Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
 527     * 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
 528     * up to the closest valid key length, padding $key with null bytes.  If the key is more than 256-bits, we trim the
 529     * excess bits.
 530     *
 531     * If the key is not explicitly set, it'll be assumed to be all null bytes.
 532     *
 533     * @access public
 534     * @param String $key
 535     */
 536    function setKey($key)
 537    {
 538        $this->key = $key;
 539        $this->changed = true;
 540    }
 541
 542    /**
 543     * Sets the initialization vector. (optional)
 544     *
 545     * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used.  If not explictly set, it'll be assumed
 546     * to be all zero's.
 547     *
 548     * @access public
 549     * @param String $iv
 550     */
 551    function setIV($iv)
 552    {
 553        $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, $this->block_size), $this->block_size, chr(0));
 554    }
 555
 556    /**
 557     * Sets the key length
 558     *
 559     * Valid key lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
 560     * 128.  If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
 561     *
 562     * @access public
 563     * @param Integer $length
 564     */
 565    function setKeyLength($length)
 566    {
 567        $length >>= 5;
 568        if ($length > 8) {
 569            $length = 8;
 570        } else if ($length < 4) {
 571            $length = 4;
 572        }
 573        $this->Nk = $length;
 574        $this->key_size = $length << 2;
 575
 576        $this->explicit_key_length = true;
 577        $this->changed = true;
 578    }
 579
 580    /**
 581     * Sets the password.
 582     *
 583     * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
 584     *     {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
 585     *         $hash, $salt, $method
 586     *     Set $dkLen by calling setKeyLength()
 587     *
 588     * @param String $password
 589     * @param optional String $method
 590     * @access public
 591     */
 592    function setPassword($password, $method = 'pbkdf2')
 593    {
 594        $key = '';
 595
 596        switch ($method) {
 597            default: // 'pbkdf2'
 598                list(, , $hash, $salt, $count) = func_get_args();
 599                if (!isset($hash)) {
 600                    $hash = 'sha1';
 601                }
 602                // WPA and WPA2 use the SSID as the salt
 603                if (!isset($salt)) {
 604                    $salt = 'phpseclib';
 605                }
 606                // RFC2898#section-4.2 uses 1,000 iterations by default
 607                // WPA and WPA2 use 4,096.
 608                if (!isset($count)) {
 609                    $count = 1000;
 610                }
 611
 612                if (!class_exists('Crypt_Hash')) {
 613                    require_once('Crypt/Hash.php');
 614                }
 615
 616                $i = 1;
 617                while (strlen($key) < $this->key_size) { // $dkLen == $this->key_size
 618                    //$dk.= $this->_pbkdf($password, $salt, $count, $i++);
 619                    $hmac = new Crypt_Hash();
 620                    $hmac->setHash($hash);
 621                    $hmac->setKey($password);
 622                    $f = $u = $hmac->hash($salt . pack('N', $i++));
 623                    for ($j = 2; $j <= $count; $j++) {
 624                        $u = $hmac->hash($u);
 625                        $f^= $u;
 626                    }
 627                    $key.= $f;
 628                }
 629        }
 630
 631        $this->setKey(substr($key, 0, $this->key_size));
 632    }
 633
 634    /**
 635     * Sets the block length
 636     *
 637     * Valid block lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
 638     * 128.  If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
 639     *
 640     * @access public
 641     * @param Integer $length
 642     */
 643    function setBlockLength($length)
 644    {
 645        $length >>= 5;
 646        if ($length > 8) {
 647            $length = 8;
 648        } else if ($length < 4) {
 649            $length = 4;
 650        }
 651        $this->Nb = $length;
 652        $this->block_size = $length << 2;
 653        $this->changed = true;
 654    }
 655
 656    /**
 657     * Generate CTR XOR encryption key
 658     *
 659     * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
 660     * plaintext / ciphertext in CTR mode.
 661     *
 662     * @see Crypt_Rijndael::decrypt()
 663     * @see Crypt_Rijndael::encrypt()
 664     * @access public
 665     * @param Integer $length
 666     * @param String $iv
 667     */
 668    function _generate_xor($length, &$iv)
 669    {
 670        $xor = '';
 671        $block_size = $this->block_size;
 672        $num_blocks = floor(($length + ($block_size - 1)) / $block_size);
 673        for ($i = 0; $i < $num_blocks; $i++) {
 674            $xor.= $iv;
 675            for ($j = 4; $j <= $block_size; $j+=4) {
 676                $temp = substr($iv, -$j, 4);
 677                switch ($temp) {
 678                    case "\xFF\xFF\xFF\xFF":
 679                        $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
 680                        break;
 681                    case "\x7F\xFF\xFF\xFF":
 682                        $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
 683                        break 2;
 684                    default:
 685                        extract(unpack('Ncount', $temp));
 686                        $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
 687                        break 2;
 688                }
 689            }
 690        }
 691
 692        return $xor;
 693    }
 694
 695    /**
 696     * Encrypts a message.
 697     *
 698     * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size.  Other Rjindael
 699     * implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's
 700     * necessary are discussed in the following
 701     * URL:
 702     *
 703     * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
 704     *
 705     * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
 706     * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
 707     * length.
 708     *
 709     * @see Crypt_Rijndael::decrypt()
 710     * @access public
 711     * @param String $plaintext
 712     */
 713    function encrypt($plaintext)
 714    {
 715        $this->_setup();
 716        if ($this->paddable) {
 717            $plaintext = $this->_pad($plaintext);
 718        }
 719
 720        $block_size = $this->block_size;
 721        $buffer = &$this->enbuffer;
 722        $ciphertext = '';
 723        switch ($this->mode) {
 724            case CRYPT_RIJNDAEL_MODE_ECB:
 725                for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 726                    $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
 727                }
 728                break;
 729            case CRYPT_RIJNDAEL_MODE_CBC:
 730                $xor = $this->encryptIV;
 731                for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 732                    $block = substr($plaintext, $i, $block_size);
 733                    $block = $this->_encryptBlock($block ^ $xor);
 734                    $xor = $block;
 735                    $ciphertext.= $block;
 736                }
 737                if ($this->continuousBuffer) {
 738                    $this->encryptIV = $xor;
 739                }
 740                break;
 741            case CRYPT_RIJNDAEL_MODE_CTR:
 742                $xor = $this->encryptIV;
 743                if (strlen($buffer['encrypted'])) {
 744                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 745                        $block = substr($plaintext, $i, $block_size);
 746                        $buffer['encrypted'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));
 747                        $key = $this->_string_shift($buffer['encrypted'], $block_size);
 748                        $ciphertext.= $block ^ $key;
 749                    }
 750                } else {
 751                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 752                        $block = substr($plaintext, $i, $block_size);
 753                        $key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));
 754                        $ciphertext.= $block ^ $key;
 755                    }
 756                }
 757                if ($this->continuousBuffer) {
 758                    $this->encryptIV = $xor;
 759                    if ($start = strlen($plaintext) % $block_size) {
 760                        $buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
 761                    }
 762                }
 763                break;
 764            case CRYPT_RIJNDAEL_MODE_CFB:
 765                // cfb loosely routines inspired by openssl's:
 766                // http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1
 767                if ($this->continuousBuffer) {
 768                    $iv = &$this->encryptIV;
 769                    $pos = &$buffer['pos'];
 770                } else {
 771                    $iv = $this->encryptIV;
 772                    $pos = 0;
 773                }
 774                $len = strlen($plaintext);
 775                $i = 0;
 776                if ($pos) {
 777                    $orig_pos = $pos;
 778                    $max = $block_size - $pos;
 779                    if ($len >= $max) {
 780                        $i = $max;
 781                        $len-= $max;
 782                        $pos = 0;
 783                    } else {
 784                        $i = $len;
 785                        $pos+= $len;
 786                        $len = 0;
 787                    }
 788                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
 789                    $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
 790                    $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
 791                }
 792                while ($len >= $block_size) {
 793                    $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
 794                    $ciphertext.= $iv;
 795                    $len-= $block_size;
 796                    $i+= $block_size;
 797                }
 798                if ($len) {
 799                    $iv = $this->_encryptBlock($iv);
 800                    $block = $iv ^ substr($plaintext, $i);
 801                    $iv = substr_replace($iv, $block, 0, $len);
 802                    $ciphertext.= $block;
 803                    $pos = $len;
 804                }
 805                break;
 806            case CRYPT_RIJNDAEL_MODE_OFB:
 807                $xor = $this->encryptIV;
 808                if (strlen($buffer['xor'])) {
 809                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 810                        $xor = $this->_encryptBlock($xor);
 811                        $buffer['xor'].= $xor;
 812                        $key = $this->_string_shift($buffer['xor'], $block_size);
 813                        $ciphertext.= substr($plaintext, $i, $block_size) ^ $key;
 814                    }
 815                } else {
 816                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 817                        $xor = $this->_encryptBlock($xor);
 818                        $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
 819                    }
 820                    $key = $xor;
 821                }
 822                if ($this->continuousBuffer) {
 823                    $this->encryptIV = $xor;
 824                    if ($start = strlen($plaintext) % $block_size) {
 825                         $buffer['xor'] = substr($key, $start) . $buffer['xor'];
 826                    }
 827                }
 828        }
 829
 830        return $ciphertext;
 831    }
 832
 833    /**
 834     * Decrypts a message.
 835     *
 836     * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
 837     * it is.
 838     *
 839     * @see Crypt_Rijndael::encrypt()
 840     * @access public
 841     * @param String $ciphertext
 842     */
 843    function decrypt($ciphertext)
 844    {
 845        $this->_setup();
 846
 847        if ($this->paddable) {
 848            // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :
 849            // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
 850            $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
 851        }
 852
 853        $block_size = $this->block_size;
 854        $buffer = &$this->debuffer;
 855        $plaintext = '';
 856        switch ($this->mode) {
 857            case CRYPT_RIJNDAEL_MODE_ECB:
 858                for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
 859                    $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
 860                }
 861                break;
 862            case CRYPT_RIJNDAEL_MODE_CBC:
 863                $xor = $this->decryptIV;
 864                for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
 865                    $block = substr($ciphertext, $i, $block_size);
 866                    $plaintext.= $this->_decryptBlock($block) ^ $xor;
 867                    $xor = $block;
 868                }
 869                if ($this->continuousBuffer) {
 870                    $this->decryptIV = $xor;
 871                }
 872                break;
 873            case CRYPT_RIJNDAEL_MODE_CTR:
 874                $xor = $this->decryptIV;
 875                if (strlen($buffer['ciphertext'])) {
 876                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
 877                        $block = substr($ciphertext, $i, $block_size);
 878                        $buffer['ciphertext'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));
 879                        $key = $this->_string_shift($buffer['ciphertext'], $block_size);
 880                        $plaintext.= $block ^ $key;
 881                    }
 882                } else {
 883                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
 884                        $block = substr($ciphertext, $i, $block_size);
 885                        $key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));
 886                        $plaintext.= $block ^ $key;
 887                    }
 888                }
 889                if ($this->continuousBuffer) {
 890                    $this->decryptIV = $xor;
 891                    if ($start = strlen($ciphertext) % $block_size) {
 892                        $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
 893                    }
 894                }
 895                break;
 896            case CRYPT_RIJNDAEL_MODE_CFB:
 897                if ($this->continuousBuffer) {
 898                    $iv = &$this->decryptIV;
 899                    $pos = &$buffer['pos'];
 900                } else {
 901                    $iv = $this->decryptIV;
 902                    $pos = 0;
 903                }
 904                $len = strlen($ciphertext);
 905                $i = 0;
 906                if ($pos) {
 907                    $orig_pos = $pos;
 908                    $max = $block_size - $pos;
 909                    if ($len >= $max) {
 910                        $i = $max;
 911                        $len-= $max;
 912                        $pos = 0;
 913                    } else {
 914                        $i = $len;
 915                        $pos+= $len;
 916                        $len = 0;
 917                    }
 918                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
 919                    $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
 920                    $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
 921                }
 922                while ($len >= $block_size) {
 923                    $iv = $this->_encryptBlock($iv);
 924                    $cb = substr($ciphertext, $i, $block_size);
 925                    $plaintext.= $iv ^ $cb;
 926                    $iv = $cb;
 927                    $len-= $block_size;
 928                    $i+= $block_size;
 929                }
 930                if ($len) {
 931                    $iv = $this->_encryptBlock($iv);
 932                    $plaintext.= $iv ^ substr($ciphertext, $i);
 933                    $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
 934                    $pos = $len;
 935                }
 936                break;
 937            case CRYPT_RIJNDAEL_MODE_OFB:
 938                $xor = $this->decryptIV;
 939                if (strlen($buffer['xor'])) {
 940                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
 941                        $xor = $this->_encryptBlock($xor);
 942                        $buffer['xor'].= $xor;
 943                        $key = $this->_string_shift($buffer['xor'], $block_size);
 944                        $plaintext.= substr($ciphertext, $i, $block_size) ^ $key;
 945                    }
 946                } else {
 947                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
 948                        $xor = $this->_encryptBlock($xor);
 949                        $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
 950                    }
 951                    $key = $xor;
 952                }
 953                if ($this->continuousBuffer) {
 954                    $this->decryptIV = $xor;
 955                    if ($start = strlen($ciphertext) % $block_size) {
 956                         $buffer['xor'] = substr($key, $start) . $buffer['xor'];
 957                    }
 958                }
 959        }
 960
 961        return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
 962    }
 963
 964    /**
 965     * Encrypts a block
 966     *
 967     * @access private
 968     * @param String $in
 969     * @return String
 970     */
 971    function _encryptBlock($in)
 972    {
 973        $state = array();
 974        $words = unpack('N*word', $in);
 975
 976        $w = $this->w;
 977        $t0 = $this->t0;
 978        $t1 = $this->t1;
 979        $t2 = $this->t2;
 980        $t3 = $this->t3;
 981        $Nb = $this->Nb;
 982        $Nr = $this->Nr;
 983        $c = $this->c;
 984
 985        // addRoundKey
 986        $i = -1;
 987        foreach ($words as $word) {
 988            $state[] = $word ^ $w[0][++$i];
 989        }
 990
 991        // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components - 
 992        // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding 
 993        // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
 994        // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
 995        // Unfortunately, the description given there is not quite correct.  Per aes.spec.v316.pdf#page=19 [1], 
 996        // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
 997
 998        // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
 999        $temp = array();
1000        for ($round = 1; $round < $Nr; ++$round) {
1001            $i = 0; // $c[0] == 0
1002            $j = $c[1];
1003            $k = $c[2];
1004            $l = $c[3];
1005
1006            while ($i < $Nb) {
1007                $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
1008                            $t1[$state[$j] >> 16 & 0x000000FF] ^
1009                            $t2[$state[$k] >>  8 & 0x000000FF] ^
1010                            $t3[$state[$l]       & 0x000000FF] ^
1011                            $w[$round][$i];
1012                ++$i;
1013                $j = ($j + 1) % $Nb;
1014                $k = ($k + 1) % $Nb;
1015                $l = ($l + 1) % $Nb;
1016            }
1017            $state = $temp;
1018        }
1019
1020        // subWord
1021        for ($i = 0; $i < $Nb; ++$i) {
1022            $state[$i] = $this->_subWord($state[$i]);
1023        }
1024
1025        // shiftRows + addRoundKey
1026        $i = 0; // $c[0] == 0
1027        $j = $c[1];
1028        $k = $c[2];
1029        $l = $c[3];
1030        while ($i < $Nb) {
1031            $temp[$i] = ($state[$i] & 0xFF000000) ^
1032                        ($state[$j] & 0x00FF0000) ^
1033                        ($state[$k] & 0x0000FF00) ^
1034                        ($state[$l] & 0x000000FF) ^
1035                         $w[$Nr][$i];
1036            ++$i;
1037            $j = ($j + 1) % $Nb;
1038            $k = ($k + 1) % $Nb;
1039            $l = ($l + 1) % $Nb;
1040        }
1041
1042        // 100% ugly switch/case code... but ~5% faster (meaning: ~half second faster de/encrypting 1MB text, tested with php5.4.9 on linux/32bit with an AMD Athlon II P360 CPU) then the commented smart code below. Don't know it's worth or not
1043        switch ($Nb) {
1044            case 8:
1045                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
1046            case 7:
1047                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
1048            case 6:
1049                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
1050            case 5:
1051                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
1052            default:
1053                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
1054        }
1055        /*
1056        $state = $temp;
1057
1058        array_unshift($state, 'N*');
1059
1060        return call_user_func_array('pack', $state);
1061        */
1062    }
1063
1064    /**
1065     * Decrypts a block
1066     *
1067     * @access private
1068     * @param String $in
1069     * @return String
1070     */
1071    function _decryptBlock($in)
1072    {
1073        $state = array();
1074        $words = unpack('N*word', $in);
1075
1076        $dw = $this->dw;
1077        $dt0 = $this->dt0;
1078        $dt1 = $this->dt1;
1079        $dt2 = $this->dt2;
1080        $dt3 = $this->dt3;
1081        $Nb = $this->Nb;
1082        $Nr = $this->Nr;
1083        $c = $this->c;
1084
1085        // addRoundKey
1086        $i = -1;
1087        foreach ($words as $word) {
1088            $state[] = $word ^ $dw[$Nr][++$i];
1089        }
1090
1091        $temp = array();
1092        for ($round = $Nr - 1; $round > 0; --$round) {
1093            $i = 0; // $c[0] == 0
1094            $j = $Nb - $c[1];
1095            $k = $Nb - $c[2];
1096            $l = $Nb - $c[3];
1097
1098            while ($i < $Nb) {
1099                $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
1100                            $dt1[$state[$j] >> 16 & 0x000000FF] ^
1101                            $dt2[$state[$k] >>  8 & 0x000000FF] ^
1102                            $dt3[$state[$l]       & 0x000000FF] ^
1103                            $dw[$round][$i];
1104                ++$i;
1105                $j = ($j + 1) % $Nb;
1106                $k = ($k + 1) % $Nb;
1107                $l = ($l + 1) % $Nb;
1108            }
1109            $state = $temp;
1110        }
1111
1112        // invShiftRows + invSubWord + addRoundKey
1113        $i = 0; // $c[0] == 0
1114        $j = $Nb - $c[1];
1115        $k = $Nb - $c[2];
1116        $l = $Nb - $c[3];
1117
1118        while ($i < $Nb) {
1119            $temp[$i] = $dw[0][$i] ^ 
1120                        $this->_invSubWord(($state[$i] & 0xFF000000) | 
1121                                           ($state[$j] & 0x00FF0000) | 
1122                                           ($state[$k] & 0x0000FF00) | 
1123                                           ($state[$l] & 0x000000FF));
1124            ++$i;
1125            $j = ($j + 1) % $Nb;
1126            $k = ($k + 1) % $Nb;
1127            $l = ($l + 1) % $Nb;
1128        }
1129
1130        switch ($Nb) {
1131            case 8:
1132                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
1133            case 7:
1134                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
1135            case 6:
1136                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
1137            case 5:
1138                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
1139            default:
1140                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
1141        }
1142        /*
1143        $state = $temp;
1144
1145        array_unshift($state, 'N*');
1146
1147        return call_user_func_array('pack', $state);
1148        */
1149    }
1150
1151    /**
1152     * Setup Rijndael
1153     *
1154     * Validates all the variables and calculates $Nr - the number of rounds that need to be performed - and $w - the key
1155     * key schedule.
1156     *
1157     * @access private
1158     */
1159    function _setup()
1160    {
1161        // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
1162        // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
1163        static $rcon = array(0,
1164            0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
1165            0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
1166            0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
1167            0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
1168            0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
1169            0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
1170        );
1171
1172        if (!$this->changed) {
1173            return;
1174        }
1175
1176        if (!$this->explicit_key_length) {
1177            // we do >> 2, here, and not >> 5, as we do above, since strlen($this->key) tells us the number of bytes - not bits
1178            $length = strlen($this->key) >> 2;
1179            if ($length > 8) {
1180                $length = 8;
1181            } else if ($length < 4) {
1182                $length = 4;
1183            }
1184            $this->Nk = $length;
1185            $this->key_size = $length << 2;
1186        }
1187
1188        $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
1189        $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, chr(0));
1190
1191        // see Rijndael-ammended.pdf#page=44
1192        $this->Nr = max($this->Nk, $this->Nb) + 6;
1193
1194        // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
1195        //     "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
1196        // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
1197        //     "Table 2: Shift offsets for different block lengths"
1198        switch ($this->Nb) {
1199            case 4:
1200            case 5:
1201            case 6:
1202                $this->c = array(0, 1, 2, 3);
1203                break;
1204            case 7:
1205                $this->c = array(0, 1, 2, 4);
1206                break;
1207            case 8:
1208                $this->c = array(0, 1, 3, 4);
1209        }
1210
1211        $key = $this->key;
1212
1213        $w = array_values(unpack('N*words', $key));
1214
1215        $length = $this->Nb * ($this->Nr + 1);
1216        for ($i = $this->Nk; $i < $length; $i++) {
1217            $temp = $w[$i - 1];
1218            if ($i % $this->Nk == 0) {
1219                // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
1220                // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
1221                // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
1222                // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
1223                $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
1224                $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
1225            } else if ($this->Nk > 6 && $i % $this->Nk == 4) {
1226                $temp = $this->_subWord($temp);
1227            }
1228            $w[$i] = $w[$i - $this->Nk] ^ $temp;
1229        }
1230
1231        // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
1232        // and generate the inverse key schedule.  more specifically,
1233        // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3), 
1234        // "The key expansion for the Inverse Cipher is defined as follows:
1235        //        1. Apply the Key Expansion.
1236        //        2. Apply InvMixColumn to all Round Keys except the first and the last one."
1237        // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
1238        $temp = array();
1239        for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
1240            if ($col == $this->Nb) {
1241                if ($row == 0) {
1242                    $this->dw[0] = $this->w[0];
1243                } else {
1244                    // subWord + invMixColumn + invSubWord = invMixColumn
1245                    $j = 0;
1246                    while ($j < $this->Nb) {
1247                        $dw = $this->_subWord($this->w[$row][$j]);
1248                        $temp[$j] = $this->dt0[$dw >> 24 & 0x000000FF] ^ 
1249                                    $this->dt1[$dw >> 16 & 0x000000FF] ^ 
1250                                    $this->dt2[$dw >>  8 & 0x000000FF] ^ 
1251                                    $this->dt3[$dw       & 0x000000FF];
1252                        $j++;
1253                    }
1254                    $this->dw[$row] = $temp;
1255                }
1256
1257                $col = 0;
1258                $row++;
1259            }
1260            $this->w[$row][$col] = $w[$i];
1261        }
1262
1263        $this->dw[$row] = $this->w[$row];
1264
1265        $this->changed = false;
1266    }
1267
1268    /**
1269     * Performs S-Box substitutions
1270     *
1271     * @access private
1272     */
1273    function _subWord($word)
1274    {
1275        static $sbox0, $sbox1, $sbox2, $sbox3;
1276
1277        if (empty($sbox0)) {
1278            $sbox0 = array(
1279                0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
1280                0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
1281                0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
1282                0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
1283                0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
1284                0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
1285                0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
1286                0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
1287                0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
1288                0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88

Large files files are truncated, but you can click here to view the full file