Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
103 - 1
<?php
2
 
3
/**
4
 * Pure-PHP implementation of Rijndael.
5
 *
6
 * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
7
 *
8
 * PHP version 5
9
 *
10
 * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits.  If
11
 * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12
 * {@link self::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's
13
 * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
14
 * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
15
 *
16
 * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length.  mcrypt, for example,
17
 * does not.  AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
18
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
19
 * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224.  Indeed, 160 and 224
20
 * are first defined as valid key / block lengths in
21
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
22
 * Extensions: Other block and Cipher Key lengths.
23
 * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
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 'vendor/autoload.php';
32
 *
33
 *    $rijndael = new \phpseclib\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
 * @category  Crypt
48
 * @package   Rijndael
49
 * @author    Jim Wigginton <terrafrost@php.net>
50
 * @copyright 2008 Jim Wigginton
51
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
52
 * @link      http://phpseclib.sourceforge.net
53
 */
54
 
55
namespace phpseclib\Crypt;
56
 
57
/**
58
 * Pure-PHP implementation of Rijndael.
59
 *
60
 * @package Rijndael
61
 * @author  Jim Wigginton <terrafrost@php.net>
62
 * @access  public
63
 */
64
class Rijndael extends Base
65
{
66
    /**
67
     * The mcrypt specific name of the cipher
68
     *
69
     * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
70
     * \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable
71
     * or not for the current $block_size/$key_length.
72
     * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
73
     *
74
     * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
75
     * @see \phpseclib\Crypt\Base::engine
76
     * @see self::isValidEngine()
77
     * @var string
78
     * @access private
79
     */
80
    var $cipher_name_mcrypt = 'rijndael-128';
81
 
82
    /**
83
     * The default salt used by setPassword()
84
     *
85
     * @see \phpseclib\Crypt\Base::password_default_salt
86
     * @see \phpseclib\Crypt\Base::setPassword()
87
     * @var string
88
     * @access private
89
     */
90
    var $password_default_salt = 'phpseclib';
91
 
92
    /**
93
     * The Key Schedule
94
     *
95
     * @see self::_setup()
96
     * @var array
97
     * @access private
98
     */
99
    var $w;
100
 
101
    /**
102
     * The Inverse Key Schedule
103
     *
104
     * @see self::_setup()
105
     * @var array
106
     * @access private
107
     */
108
    var $dw;
109
 
110
    /**
111
     * The Block Length divided by 32
112
     *
113
     * @see self::setBlockLength()
114
     * @var int
115
     * @access private
116
     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4.  Exists in conjunction with $block_size
117
     *    because the encryption / decryption / key schedule creation requires this number and not $block_size.  We could
118
     *    derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
119
     *    of that, we'll just precompute it once.
120
     */
121
    var $Nb = 4;
122
 
123
    /**
124
     * The Key Length (in bytes)
125
     *
126
     * @see self::setKeyLength()
127
     * @var int
128
     * @access private
129
     * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $Nk
130
     *    because the encryption / decryption / key schedule creation requires this number and not $key_length.  We could
131
     *    derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
132
     *    of that, we'll just precompute it once.
133
     */
134
    var $key_length = 16;
135
 
136
    /**
137
     * The Key Length divided by 32
138
     *
139
     * @see self::setKeyLength()
140
     * @var int
141
     * @access private
142
     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
143
     */
144
    var $Nk = 4;
145
 
146
    /**
147
     * The Number of Rounds
148
     *
149
     * @var int
150
     * @access private
151
     * @internal The max value is 14, the min value is 10.
152
     */
153
    var $Nr;
154
 
155
    /**
156
     * Shift offsets
157
     *
158
     * @var array
159
     * @access private
160
     */
161
    var $c;
162
 
163
    /**
164
     * Holds the last used key- and block_size information
165
     *
166
     * @var array
167
     * @access private
168
     */
169
    var $kl;
170
 
171
    /**
172
     * Sets the key length.
173
     *
174
     * Valid key lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
175
     * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
176
     *
177
     * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
178
     *       and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
179
     *       192/256 bits as, for example, mcrypt will do.
180
     *
181
     *       That said, if you want be compatible with other Rijndael and AES implementations,
182
     *       you should not setKeyLength(160) or setKeyLength(224).
183
     *
184
     * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
185
     *             the mcrypt php extension, even if available.
186
     *             This results then in slower encryption.
187
     *
188
     * @access public
189
     * @param int $length
190
     */
191
    function setKeyLength($length)
192
    {
193
        switch (true) {
194
            case $length <= 128:
195
                $this->key_length = 16;
196
                break;
197
            case $length <= 160:
198
                $this->key_length = 20;
199
                break;
200
            case $length <= 192:
201
                $this->key_length = 24;
202
                break;
203
            case $length <= 224:
204
                $this->key_length = 28;
205
                break;
206
            default:
207
                $this->key_length = 32;
208
        }
209
 
210
        parent::setKeyLength($length);
211
    }
212
 
213
    /**
214
     * Sets the block length
215
     *
216
     * Valid block lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
217
     * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
218
     *
219
     * @access public
220
     * @param int $length
221
     */
222
    function setBlockLength($length)
223
    {
224
        $length >>= 5;
225
        if ($length > 8) {
226
            $length = 8;
227
        } elseif ($length < 4) {
228
            $length = 4;
229
        }
230
        $this->Nb = $length;
231
        $this->block_size = $length << 2;
232
        $this->changed = true;
233
        $this->_setEngine();
234
    }
235
 
236
    /**
237
     * Test for engine validity
238
     *
239
     * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
240
     *
241
     * @see \phpseclib\Crypt\Base::__construct()
242
     * @param int $engine
243
     * @access public
244
     * @return bool
245
     */
246
    function isValidEngine($engine)
247
    {
248
        switch ($engine) {
249
            case self::ENGINE_OPENSSL:
250
                if ($this->block_size != 16) {
251
                    return false;
252
                }
253
                $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
254
                $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
255
                break;
256
            case self::ENGINE_MCRYPT:
257
                $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
258
                if ($this->key_length % 8) { // is it a 160/224-bit key?
259
                    // mcrypt is not usable for them, only for 128/192/256-bit keys
260
                    return false;
261
                }
262
        }
263
 
264
        return parent::isValidEngine($engine);
265
    }
266
 
267
    /**
268
     * Encrypts a block
269
     *
270
     * @access private
271
     * @param string $in
272
     * @return string
273
     */
274
    function _encryptBlock($in)
275
    {
276
        static $tables;
277
        if (empty($tables)) {
278
            $tables = &$this->_getTables();
279
        }
280
        $t0   = $tables[0];
281
        $t1   = $tables[1];
282
        $t2   = $tables[2];
283
        $t3   = $tables[3];
284
        $sbox = $tables[4];
285
 
286
        $state = array();
287
        $words = unpack('N*', $in);
288
 
289
        $c = $this->c;
290
        $w = $this->w;
291
        $Nb = $this->Nb;
292
        $Nr = $this->Nr;
293
 
294
        // addRoundKey
295
        $wc = $Nb - 1;
296
        foreach ($words as $word) {
297
            $state[] = $word ^ $w[++$wc];
298
        }
299
 
300
        // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
301
        // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
302
        // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
303
        // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
304
        // Unfortunately, the description given there is not quite correct.  Per aes.spec.v316.pdf#page=19 [1],
305
        // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
306
 
307
        // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
308
        $temp = array();
309
        for ($round = 1; $round < $Nr; ++$round) {
310
            $i = 0; // $c[0] == 0
311
            $j = $c[1];
312
            $k = $c[2];
313
            $l = $c[3];
314
 
315
            while ($i < $Nb) {
316
                $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
317
                            $t1[$state[$j] >> 16 & 0x000000FF] ^
318
                            $t2[$state[$k] >>  8 & 0x000000FF] ^
319
                            $t3[$state[$l]       & 0x000000FF] ^
320
                            $w[++$wc];
321
                ++$i;
322
                $j = ($j + 1) % $Nb;
323
                $k = ($k + 1) % $Nb;
324
                $l = ($l + 1) % $Nb;
325
            }
326
            $state = $temp;
327
        }
328
 
329
        // subWord
330
        for ($i = 0; $i < $Nb; ++$i) {
331
            $state[$i] =   $sbox[$state[$i]       & 0x000000FF]        |
332
                          ($sbox[$state[$i] >>  8 & 0x000000FF] <<  8) |
333
                          ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
334
                          ($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
335
        }
336
 
337
        // shiftRows + addRoundKey
338
        $i = 0; // $c[0] == 0
339
        $j = $c[1];
340
        $k = $c[2];
341
        $l = $c[3];
342
        while ($i < $Nb) {
343
            $temp[$i] = ($state[$i] & 0xFF000000) ^
344
                        ($state[$j] & 0x00FF0000) ^
345
                        ($state[$k] & 0x0000FF00) ^
346
                        ($state[$l] & 0x000000FF) ^
347
                         $w[$i];
348
            ++$i;
349
            $j = ($j + 1) % $Nb;
350
            $k = ($k + 1) % $Nb;
351
            $l = ($l + 1) % $Nb;
352
        }
353
 
354
        switch ($Nb) {
355
            case 8:
356
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
357
            case 7:
358
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
359
            case 6:
360
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
361
            case 5:
362
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
363
            default:
364
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
365
        }
366
    }
367
 
368
    /**
369
     * Decrypts a block
370
     *
371
     * @access private
372
     * @param string $in
373
     * @return string
374
     */
375
    function _decryptBlock($in)
376
    {
377
        static $invtables;
378
        if (empty($invtables)) {
379
            $invtables = &$this->_getInvTables();
380
        }
381
        $dt0   = $invtables[0];
382
        $dt1   = $invtables[1];
383
        $dt2   = $invtables[2];
384
        $dt3   = $invtables[3];
385
        $isbox = $invtables[4];
386
 
387
        $state = array();
388
        $words = unpack('N*', $in);
389
 
390
        $c  = $this->c;
391
        $dw = $this->dw;
392
        $Nb = $this->Nb;
393
        $Nr = $this->Nr;
394
 
395
        // addRoundKey
396
        $wc = $Nb - 1;
397
        foreach ($words as $word) {
398
            $state[] = $word ^ $dw[++$wc];
399
        }
400
 
401
        $temp = array();
402
        for ($round = $Nr - 1; $round > 0; --$round) {
403
            $i = 0; // $c[0] == 0
404
            $j = $Nb - $c[1];
405
            $k = $Nb - $c[2];
406
            $l = $Nb - $c[3];
407
 
408
            while ($i < $Nb) {
409
                $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
410
                            $dt1[$state[$j] >> 16 & 0x000000FF] ^
411
                            $dt2[$state[$k] >>  8 & 0x000000FF] ^
412
                            $dt3[$state[$l]       & 0x000000FF] ^
413
                            $dw[++$wc];
414
                ++$i;
415
                $j = ($j + 1) % $Nb;
416
                $k = ($k + 1) % $Nb;
417
                $l = ($l + 1) % $Nb;
418
            }
419
            $state = $temp;
420
        }
421
 
422
        // invShiftRows + invSubWord + addRoundKey
423
        $i = 0; // $c[0] == 0
424
        $j = $Nb - $c[1];
425
        $k = $Nb - $c[2];
426
        $l = $Nb - $c[3];
427
 
428
        while ($i < $Nb) {
429
            $word = ($state[$i] & 0xFF000000) |
430
                    ($state[$j] & 0x00FF0000) |
431
                    ($state[$k] & 0x0000FF00) |
432
                    ($state[$l] & 0x000000FF);
433
 
434
            $temp[$i] = $dw[$i] ^ ($isbox[$word       & 0x000000FF]        |
435
                                  ($isbox[$word >>  8 & 0x000000FF] <<  8) |
436
                                  ($isbox[$word >> 16 & 0x000000FF] << 16) |
437
                                  ($isbox[$word >> 24 & 0x000000FF] << 24));
438
            ++$i;
439
            $j = ($j + 1) % $Nb;
440
            $k = ($k + 1) % $Nb;
441
            $l = ($l + 1) % $Nb;
442
        }
443
 
444
        switch ($Nb) {
445
            case 8:
446
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
447
            case 7:
448
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
449
            case 6:
450
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
451
            case 5:
452
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
453
            default:
454
                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
455
        }
456
    }
457
 
458
    /**
459
     * Setup the key (expansion)
460
     *
461
     * @see \phpseclib\Crypt\Base::_setupKey()
462
     * @access private
463
     */
464
    function _setupKey()
465
    {
466
        // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
467
        // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
468
        static $rcon = array(0,
469
            0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
470
            0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
471
            0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
472
            0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
473
            0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
474
            0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
475
        );
476
 
477
        if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
478
            // already expanded
479
            return;
480
        }
481
        $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
482
 
483
        $this->Nk = $this->key_length >> 2;
484
        // see Rijndael-ammended.pdf#page=44
485
        $this->Nr = max($this->Nk, $this->Nb) + 6;
486
 
487
        // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
488
        //     "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
489
        // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
490
        //     "Table 2: Shift offsets for different block lengths"
491
        switch ($this->Nb) {
492
            case 4:
493
            case 5:
494
            case 6:
495
                $this->c = array(0, 1, 2, 3);
496
                break;
497
            case 7:
498
                $this->c = array(0, 1, 2, 4);
499
                break;
500
            case 8:
501
                $this->c = array(0, 1, 3, 4);
502
        }
503
 
504
        $w = array_values(unpack('N*words', $this->key));
505
 
506
        $length = $this->Nb * ($this->Nr + 1);
507
        for ($i = $this->Nk; $i < $length; $i++) {
508
            $temp = $w[$i - 1];
509
            if ($i % $this->Nk == 0) {
510
                // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
511
                // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
512
                // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
513
                // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
514
                $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
515
                $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
516
            } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
517
                $temp = $this->_subWord($temp);
518
            }
519
            $w[$i] = $w[$i - $this->Nk] ^ $temp;
520
        }
521
 
522
        // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
523
        // and generate the inverse key schedule.  more specifically,
524
        // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
525
        // "The key expansion for the Inverse Cipher is defined as follows:
526
        //        1. Apply the Key Expansion.
527
        //        2. Apply InvMixColumn to all Round Keys except the first and the last one."
528
        // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
529
        list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
530
        $temp = $this->w = $this->dw = array();
531
        for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
532
            if ($col == $this->Nb) {
533
                if ($row == 0) {
534
                    $this->dw[0] = $this->w[0];
535
                } else {
536
                    // subWord + invMixColumn + invSubWord = invMixColumn
537
                    $j = 0;
538
                    while ($j < $this->Nb) {
539
                        $dw = $this->_subWord($this->w[$row][$j]);
540
                        $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
541
                                    $dt1[$dw >> 16 & 0x000000FF] ^
542
                                    $dt2[$dw >>  8 & 0x000000FF] ^
543
                                    $dt3[$dw       & 0x000000FF];
544
                        $j++;
545
                    }
546
                    $this->dw[$row] = $temp;
547
                }
548
 
549
                $col = 0;
550
                $row++;
551
            }
552
            $this->w[$row][$col] = $w[$i];
553
        }
554
 
555
        $this->dw[$row] = $this->w[$row];
556
 
557
        // Converting to 1-dim key arrays (both ascending)
558
        $this->dw = array_reverse($this->dw);
559
        $w  = array_pop($this->w);
560
        $dw = array_pop($this->dw);
561
        foreach ($this->w as $r => $wr) {
562
            foreach ($wr as $c => $wc) {
563
                $w[]  = $wc;
564
                $dw[] = $this->dw[$r][$c];
565
            }
566
        }
567
        $this->w  = $w;
568
        $this->dw = $dw;
569
    }
570
 
571
    /**
572
     * Performs S-Box substitutions
573
     *
574
     * @access private
575
     * @param int $word
576
     */
577
    function _subWord($word)
578
    {
579
        static $sbox;
580
        if (empty($sbox)) {
581
            list(, , , , $sbox) = $this->_getTables();
582
        }
583
 
584
        return  $sbox[$word       & 0x000000FF]        |
585
               ($sbox[$word >>  8 & 0x000000FF] <<  8) |
586
               ($sbox[$word >> 16 & 0x000000FF] << 16) |
587
               ($sbox[$word >> 24 & 0x000000FF] << 24);
588
    }
589
 
590
    /**
591
     * Provides the mixColumns and sboxes tables
592
     *
593
     * @see self::_encryptBlock()
594
     * @see self::_setupInlineCrypt()
595
     * @see self::_subWord()
596
     * @access private
597
     * @return array &$tables
598
     */
599
    function &_getTables()
600
    {
601
        static $tables;
602
        if (empty($tables)) {
603
            // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
604
            // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
605
            // those are the names we'll use.
606
            $t3 = array_map('intval', array(
607
                // with array_map('intval', ...) we ensure we have only int's and not
608
                // some slower floats converted by php automatically on high values
609
                0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
610
                0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
611
                0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
612
                0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
613
                0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
614
                0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
615
                0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
616
                0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
617
                0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
618
                0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
619
                0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
620
                0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
621
                0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
622
                0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
623
                0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
624
                0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
625
                0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
626
                0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
627
                0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
628
                0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
629
                0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
630
                0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
631
                0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
632
                0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
633
                0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
634
                0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
635
                0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
636
                0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
637
                0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
638
                0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
639
                0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
640
                0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
641
            ));
642
 
643
            foreach ($t3 as $t3i) {
644
                $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >>  8) & 0x00FFFFFF);
645
                $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
646
                $t2[] = (($t3i <<  8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
647
            }
648
 
649
            $tables = array(
650
                // The Precomputed mixColumns tables t0 - t3
651
                $t0,
652
                $t1,
653
                $t2,
654
                $t3,
655
                // The SubByte S-Box
656
                array(
657
                    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
658
                    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
659
                    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
660
                    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
661
                    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
662
                    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
663
                    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
664
                    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
665
                    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
666
                    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
667
                    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
668
                    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
669
                    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
670
                    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
671
                    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
672
                    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
673
                )
674
            );
675
        }
676
        return $tables;
677
    }
678
 
679
    /**
680
     * Provides the inverse mixColumns and inverse sboxes tables
681
     *
682
     * @see self::_decryptBlock()
683
     * @see self::_setupInlineCrypt()
684
     * @see self::_setupKey()
685
     * @access private
686
     * @return array &$tables
687
     */
688
    function &_getInvTables()
689
    {
690
        static $tables;
691
        if (empty($tables)) {
692
            $dt3 = array_map('intval', array(
693
                0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
694
                0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
695
                0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
696
                0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
697
                0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
698
                0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
699
                0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
700
                0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
701
                0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
702
                0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
703
                0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
704
                0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
705
                0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
706
                0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
707
                0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
708
                0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
709
                0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
710
                0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
711
                0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
712
                0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
713
                0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
714
                0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
715
                0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
716
                0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
717
                0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
718
                0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
719
                0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
720
                0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
721
                0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
722
                0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
723
                0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
724
                0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
725
            ));
726
 
727
            foreach ($dt3 as $dt3i) {
728
                $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >>  8) & 0x00FFFFFF);
729
                $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
730
                $dt2[] = (($dt3i <<  8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
731
            };
732
 
733
            $tables = array(
734
                // The Precomputed inverse mixColumns tables dt0 - dt3
735
                $dt0,
736
                $dt1,
737
                $dt2,
738
                $dt3,
739
                // The inverse SubByte S-Box
740
                array(
741
                    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
742
                    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
743
                    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
744
                    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
745
                    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
746
                    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
747
                    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
748
                    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
749
                    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
750
                    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
751
                    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
752
                    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
753
                    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
754
                    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
755
                    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
756
                    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
757
                )
758
            );
759
        }
760
        return $tables;
761
    }
762
 
763
    /**
764
     * Setup the performance-optimized function for de/encrypt()
765
     *
766
     * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
767
     * @access private
768
     */
769
    function _setupInlineCrypt()
770
    {
771
        // Note: _setupInlineCrypt() will be called only if $this->changed === true
772
        // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
773
        // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
774
 
775
        $lambda_functions =& self::_getLambdaFunctions();
776
 
777
        // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
778
        // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
779
        // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
780
        $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
781
 
782
        // Generation of a uniqe hash for our generated code
783
        $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
784
        if ($gen_hi_opt_code) {
785
            $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
786
        }
787
 
788
        if (!isset($lambda_functions[$code_hash])) {
789
            switch (true) {
790
                case $gen_hi_opt_code:
791
                    // The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
792
                    $w  = $this->w;
793
                    $dw = $this->dw;
794
                    $init_encrypt = '';
795
                    $init_decrypt = '';
796
                    break;
797
                default:
798
                    for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
799
                        $w[]  = '$w['  . $i . ']';
800
                        $dw[] = '$dw[' . $i . ']';
801
                    }
802
                    $init_encrypt = '$w  = $self->w;';
803
                    $init_decrypt = '$dw = $self->dw;';
804
            }
805
 
806
            $Nr = $this->Nr;
807
            $Nb = $this->Nb;
808
            $c  = $this->c;
809
 
810
            // Generating encrypt code:
811
            $init_encrypt.= '
812
                static $tables;
813
                if (empty($tables)) {
814
                    $tables = &$self->_getTables();
815
                }
816
                $t0   = $tables[0];
817
                $t1   = $tables[1];
818
                $t2   = $tables[2];
819
                $t3   = $tables[3];
820
                $sbox = $tables[4];
821
            ';
822
 
823
            $s  = 'e';
824
            $e  = 's';
825
            $wc = $Nb - 1;
826
 
827
            // Preround: addRoundKey
828
            $encrypt_block = '$in = unpack("N*", $in);'."\n";
829
            for ($i = 0; $i < $Nb; ++$i) {
830
                $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";
831
            }
832
 
833
            // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
834
            for ($round = 1; $round < $Nr; ++$round) {
835
                list($s, $e) = array($e, $s);
836
                for ($i = 0; $i < $Nb; ++$i) {
837
                    $encrypt_block.=
838
                        '$'.$e.$i.' =
839
                        $t0[($'.$s.$i                  .' >> 24) & 0xff] ^
840
                        $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
841
                        $t2[($'.$s.(($i + $c[2]) % $Nb).' >>  8) & 0xff] ^
842
                        $t3[ $'.$s.(($i + $c[3]) % $Nb).'        & 0xff] ^
843
                        '.$w[++$wc].";\n";
844
                }
845
            }
846
 
847
            // Finalround: subWord + shiftRows + addRoundKey
848
            for ($i = 0; $i < $Nb; ++$i) {
849
                $encrypt_block.=
850
                    '$'.$e.$i.' =
851
                     $sbox[ $'.$e.$i.'        & 0xff]        |
852
                    ($sbox[($'.$e.$i.' >>  8) & 0xff] <<  8) |
853
                    ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
854
                    ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
855
            }
856
            $encrypt_block .= '$in = pack("N*"'."\n";
857
            for ($i = 0; $i < $Nb; ++$i) {
858
                $encrypt_block.= ',
859
                    ($'.$e.$i                  .' & '.((int)0xFF000000).') ^
860
                    ($'.$e.(($i + $c[1]) % $Nb).' &         0x00FF0000   ) ^
861
                    ($'.$e.(($i + $c[2]) % $Nb).' &         0x0000FF00   ) ^
862
                    ($'.$e.(($i + $c[3]) % $Nb).' &         0x000000FF   ) ^
863
                    '.$w[$i]."\n";
864
            }
865
            $encrypt_block .= ');';
866
 
867
            // Generating decrypt code:
868
            $init_decrypt.= '
869
                static $invtables;
870
                if (empty($invtables)) {
871
                    $invtables = &$self->_getInvTables();
872
                }
873
                $dt0   = $invtables[0];
874
                $dt1   = $invtables[1];
875
                $dt2   = $invtables[2];
876
                $dt3   = $invtables[3];
877
                $isbox = $invtables[4];
878
            ';
879
 
880
            $s  = 'e';
881
            $e  = 's';
882
            $wc = $Nb - 1;
883
 
884
            // Preround: addRoundKey
885
            $decrypt_block = '$in = unpack("N*", $in);'."\n";
886
            for ($i = 0; $i < $Nb; ++$i) {
887
                $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";
888
            }
889
 
890
            // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
891
            for ($round = 1; $round < $Nr; ++$round) {
892
                list($s, $e) = array($e, $s);
893
                for ($i = 0; $i < $Nb; ++$i) {
894
                    $decrypt_block.=
895
                        '$'.$e.$i.' =
896
                        $dt0[($'.$s.$i                        .' >> 24) & 0xff] ^
897
                        $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
898
                        $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >>  8) & 0xff] ^
899
                        $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).'        & 0xff] ^
900
                        '.$dw[++$wc].";\n";
901
                }
902
            }
903
 
904
            // Finalround: subWord + shiftRows + addRoundKey
905
            for ($i = 0; $i < $Nb; ++$i) {
906
                $decrypt_block.=
907
                    '$'.$e.$i.' =
908
                     $isbox[ $'.$e.$i.'        & 0xff]        |
909
                    ($isbox[($'.$e.$i.' >>  8) & 0xff] <<  8) |
910
                    ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
911
                    ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
912
            }
913
            $decrypt_block .= '$in = pack("N*"'."\n";
914
            for ($i = 0; $i < $Nb; ++$i) {
915
                $decrypt_block.= ',
916
                    ($'.$e.$i.                        ' & '.((int)0xFF000000).') ^
917
                    ($'.$e.(($Nb + $i - $c[1]) % $Nb).' &         0x00FF0000   ) ^
918
                    ($'.$e.(($Nb + $i - $c[2]) % $Nb).' &         0x0000FF00   ) ^
919
                    ($'.$e.(($Nb + $i - $c[3]) % $Nb).' &         0x000000FF   ) ^
920
                    '.$dw[$i]."\n";
921
            }
922
            $decrypt_block .= ');';
923
 
924
            $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
925
                array(
926
                   'init_crypt'    => '',
927
                   'init_encrypt'  => $init_encrypt,
928
                   'init_decrypt'  => $init_decrypt,
929
                   'encrypt_block' => $encrypt_block,
930
                   'decrypt_block' => $decrypt_block
931
                )
932
            );
933
        }
934
        $this->inline_crypt = $lambda_functions[$code_hash];
935
    }
936
}