Passed
Branch development (e0e718)
by Nils
04:45
created

Cipher_Rijndael   D

Complexity

Total Complexity 87

Size/Duplication

Total Lines 1018
Duplicated Lines 17.19 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 175
loc 1018
rs 4.4378
c 0
b 0
f 0
wmc 87
lcom 1
cbo 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Cipher_Rijndael often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Cipher_Rijndael, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * Author: Ryan Gilfether
4
 * URL: http://www.gilfether.com/phpCrypt
5
 * Date: April 3, 2013
6
 * Copyright (C) 2013 Ryan Gilfether
7
 *
8
 * This file is part of phpCrypt
9
 *
10
 * phpCrypt is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
namespace PHP_CRYPT;
25
require_once(dirname(__FILE__)."/../Cipher.php");
26
27
28
/**
29
 * Base class to implement Rijndael (and AES)
30
 * This class can not be used directly, instead one
31
 * one of the child classes that inherit this class
32
 * should be used.
33
 * References used to implement this cipher:
34
 * http://www.net-security.org/dl/articles/AESbyExample.pdf
35
 * http://www.quadibloc.com/crypto/co040401.htm
36
 * http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors
37
 * FIPS 197 (fips-197.pdf)
38
 *
39
 * @author Ryan Gilfether
40
 * @link http://www.gilfether.com/phpcrypt
41
 * @copyright 2013 Ryan Gilfether
42
 */
43
abstract class Cipher_Rijndael extends Cipher
44
{
45
    /** @type string $xkey The expanded key */
46
    private $xkey = "";
47
48
    /**
49
     * @type array $_key_sizes The accepted key sizes in bytes,
50
     * this should be considered a constant
51
     */
52
    private static $_key_sizes = array(16, 24, 32);
53
54
55
    // THE FOLLOWING TABLES ARE INITIALIZED IN initTables()
56
57
    /**
58
     * @type array $_s The sbox,
59
     * this should be considered a constant
60
     */
61
    private static $_s = array();
62
63
    /**
64
     * @type array $_s_inv The inverse sbox
65
     * this should be considered a constant
66
     */
67
    private static $_s_inv = array();
68
69
    /**
70
     * @type array $_rcon The round constant,
71
     * this should be considered a constant
72
     */
73
    private static $_rcon = array();
74
75
    /**
76
     * @type array $s_matrix_mult The matrix multiplication table,
77
     * this should be considered a constant
78
     */
79
    private static $_matrix_mult = array();
80
81
    /**
82
     * @type array $_matrix_mult_inv The matrix multiplication
83
     * inverse table, this should be considered a constant
84
     */
85
    private static $_matrix_mult_inv = array();
86
87
    /*
88
	 * Galois Multiplication lookup tables,
89
	 * initialized in initTables()
90
	 */
91
    /**
92
     * @type array $_gm2 The Galois Multiplication table
93
     * for muliplying by 2, this should be considered a constant
94
     */
95
    private static $_gm2 = array();
96
97
    /**
98
     * @type array $_gm3 The Galois Multiplication table
99
     * for muliplying by 3, this should be considered a constant
100
     */
101
    private static $_gm3 = array();
102
103
    /**
104
     * @type array $_gm9 The Galois Multiplication table
105
     * for muliplying by 9, this should be considered a constant
106
     */
107
    private static $_gm9 = array();
108
109
    /**
110
     * @type array $_gm11 The Galois Multiplication table
111
     * for muliplying by 11, this should be considered a constant
112
     */
113
    private static $_gm11 = array();
114
115
    /**
116
     * @type array $_gm13 The Galois Multiplication table
117
     * for muliplying by 13, this should be considered a constant
118
     */
119
    private static $_gm13 = array();
120
121
    /**
122
     * @type array $_gm14 The Galois Multiplication table
123
     * for muliplying by 14, this should be considered a constant
124
     */
125
    private static $_gm14 = array();
126
127
128
    /**
129
     * Constructor
130
     * Sets the key used for encryption. Also sets the requied block size
131
     *
132
     * @param string The cipher name as set in a constant in the child class
133
     * @param string $key string containing the user supplied encryption key
134
     * @param integer $len Optional, the key size in bytes - used only by the AES child classes
135
     * @return void
136
     */
137
    public function __construct($cipher_name, $key, $len = 0)
138
    {
139
        // AES will pass in a $len, since it has a fixed key size, other
140
        // rijndael implementations can use variable key sizes, supported
141
        // sizes are stored in self::$_key_sizes
142
        if ($len == 0)
143
        {
144
            // the key must be one of the following lengths: 16, 24, 32 bytes
145
            $len = strlen($key);
146
            if (!in_array($len, self::$_key_sizes))
147
            {
148
                $msg  = "Incorrect key length for ".strtoupper($cipher_name).". ";
149
                $msg .= "Received $len bytes.";
150
                trigger_error($msg, E_USER_WARNING);
151
            }
152
        }
153
154
        // Setup the key
155
        parent::__construct($cipher_name, $key, $len);
156
157
        // initialize the tables used for rijndael/aes
158
        $this->initTables();
159
    }
160
161
162
    /**
163
     * Destructor
164
     *
165
     * @return void
166
     */
167
    public function __destruct()
168
    {
169
        parent::__destruct();
170
    }
171
172
173
    /**
174
     * Performs Rijndael encryption
175
     *
176
     * @param string @text The string to encrypt
177
     * @return boolean Returns true
178
     */
179
    public function encrypt(&$text)
180
    {
181
        // set the operation to decryption
182
        $this->operation(parent::ENCRYPT);
183
184
        $loops = 0;
185
        $key_sz = $this->keySize();
186
        $blk_sz = $this->blockSize();
187
188
        // if the key and block size is 16, do 10 rounds
189
        // if the key or block size is 24, and neither is longer than 24, do 12 rounds
190
        // if either key or block size is 32, do 14 rounds
191
        if ($key_sz == 16 && $blk_sz == 16) {
192
                    $loops = 10;
193
        } else if (($key_sz == 24 || $blk_sz == 24) && $key_sz <= 24 && $blk_sz <= 24) {
194
                    $loops = 12;
195
        } else if ($key_sz == 32 || $blk_sz == 32) {
196
                    $loops = 14;
197
        }
198
199
        // now begin the encryption
200
        $this->addRoundKey($text, 0);
201
202
        for ($i = 1; $i <= $loops; ++$i)
203
        {
204
            $this->byteSub($text);
205
            $this->shiftRow($text);
206
207
            // the last iteration does not use mixColumn
208
            if ($i < $loops) {
209
                            $this->mixColumn($text);
210
            }
211
212
            $this->addRoundKey($text, $i);
213
        }
214
215
        return true;
216
    }
217
218
219
    /**
220
     * Performs Rijndael decryption
221
     *
222
     * @param string @text The string to decrypt
223
     * @return boolean Returns true
224
     */
225
    public function decrypt(&$text)
226
    {
227
        // set the operation to decryption
228
        $this->operation(parent::DECRYPT);
229
230
        $loops = 0;
231
        $key_sz = $this->keySize();
232
        $blk_sz = $this->blockSize();
233
234
        // if the key and block size is 16, do 10 rounds
235
        // if the key or block size is 24, and neither is longer than 24, do 12 rounds
236
        // if either key or block size is 32, do 14 rounds
237
        if ($key_sz == 16 && $blk_sz == 16) {
238
                    $loops = 10;
239
        } else if (($key_sz == 24 || $blk_sz == 24) && $key_sz <= 24 && $blk_sz <= 24) {
240
                    $loops = 12;
241
        } else if ($key_sz == 32 || $blk_sz == 32) {
242
                    $loops = 14;
243
        }
244
245
        // now begin the decryption
246
        $this->addRoundKey($text, 0);
247
248
        for ($i = 1; $i <= $loops; ++$i)
249
        {
250
            $this->shiftRow($text);
251
            $this->byteSub($text);
252
            $this->addRoundKey($text, $i);
253
254
            // the last iteration does not use mixColumn
255
            if ($i < $loops) {
256
                            $this->mixColumn($text);
257
            }
258
        }
259
260
        return true;
261
    }
262
263
264
    /**
265
     * Indicates that this is a block cipher
266
     *
267
     * @return integer Returns Cipher::BLOCK
268
     */
269
    public function type()
270
    {
271
        return parent::BLOCK;
272
    }
273
274
275
    /**
276
     * Do the multiplication required in mixColumn()
277
     * We follow the description the multiplication from Wikipedia:
278
     * http://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_MixColumns_step
279
     *
280
     * @param integer $m A value from self::$_matrix_mult or self::$_matrix_mult_inv
281
     * @param integer $byte The value to multipy by $m
282
     * @return integer The result of the multiplication
283
     */
284
    protected function mixColumnMultiply($m, $byte)
285
    {
286
        // if multiplying by 1, then we just return the same number
287
        if ($m == 0x01) {
288
                    return $byte;
289
        }
290
291
        $hex = parent::dec2Hex($byte);
292
        $row = parent::hex2Dec($hex[0]);
293
        $col = parent::hex2Dec($hex[1]);
294
        $pos = ($row * 16) + $col;
295
296
        // multiply by 2 (comes from self::$_matrix_mult during encryption)
297
        if ($m == 0x02) {
298
                    return self::$_gm2[$pos];
299
        }
300
301
        // multiply by 3 (comes from self::$_matrix_mult during encryption)
302
        if ($m == 0x03) {
303
                    return self::$_gm3[$pos];
304
        }
305
306
        // multiply by 9 (comes from self::$_matrix_mult_inv during decryption)
307
        if ($m == 0x09) {
308
                    return self::$_gm9[$pos];
309
        }
310
311
        // multiply by 11 (comes from self::$_matrix_mult_inv during decryption)
312
        if ($m == 0x0b) {
313
                    return self::$_gm11[$pos];
314
        }
315
316
        // multiply by 13 (comes from self::$_matrix_mult_inv during decryption)
317
        if ($m == 0x0d) {
318
                    return self::$_gm13[$pos];
319
        }
320
321
        // multiply by 14 (comes from self::$_matrix_mult_inv during decryption)
322
        if ($m == 0x0e) {
323
                    return self::$_gm14[$pos];
324
        }
325
    }
326
327
328
    /**
329
     * Each time this function is called, it XORs the 16 bytes of $text
330
     * with the next 16 bytes from the $this->xkey. The expanded key
331
     * never has the same bytes used twice. Note that the first time
332
     * addRoundKey() is called, it will be outside of the rounds, so no
333
     * $round is given. Every call after that will be inside the rounds.
334
     *
335
     * @param string $text The text to encrypt/decrypt
336
     * @param integer $round The round we are on inside of rijndael()
337
     * @return void
338
     */
339
    private function addRoundKey(&$text, $round)
340
    {
341
        // length of the xkey
342
        $ek_len = strlen($this->xkey);
343
        $len = $this->blockSize();
344
345
        if ($this->operation() == parent::ENCRYPT) {
346
                    $offset = $round * $len;
347
        } else {
348
                    $offset = ($ek_len - ($round * $len)) - $len;
349
        }
350
351
        for ($i = 0; $i < $len; ++$i) {
352
                    $text[$i] = $text[$i] ^ $this->xkey[$offset + $i];
353
        }
354
    }
355
356
357
    /**
358
     * Applies the Sbox to each byte of the string passed in
359
     * This is used in key expansione
360
     *
361
     * @param string $text The string to peform the byte subsitution
362
     * @return void
363
     */
364
    private function byteSub(&$text)
365
    {
366
        $max = strlen($text);
367
        for ($i = 0; $i < $max; ++$i)
368
        {
369
            // the sbox is arrange in a 16 x 16 grid, where each row
370
            // and column is numbered in hex (from 0 - f)
371
            $hex = parent::str2Hex($text[$i]);
372
            $row = parent::hex2Dec($hex[0]);
373
            $col = parent::hex2Dec($hex[1]);
374
            $pos = ($row * 16) + $col;
375
376
            // return the corresponding value from the sbox
377
            if ($this->operation() == parent::ENCRYPT) {
378
                            $text[$i] = chr(self::$_s[$pos]);
379
            } else {
380
                // parent::DECRYPT uses the inverse sbox
381
                $text[$i] = chr(self::$_s_inv[$pos]);
382
            }
383
        }
384
    }
385
386
387
    /**
388
     * This function is hard to explain, the easiest way to understand it is to read
389
     * http://www.net-security.org/dl/articles/AESbyExample.pdf, Section 5.4
390
     *
391
     * @param string $t The string to multiply bytes by the Galois Multiplication lookup tables
392
     * @return void
393
     */
394
    private function mixColumn(&$t)
395
    {
396
        $tmp = $t;
397
398
        // the matrix we use depends on if we are encrypting or decrypting
399
        if ($this->operation() == parent::ENCRYPT) {
400
                    $m = self::$_matrix_mult;
401
        } else {
402
            // parent::DECRYPT
403
            $m = self::$_matrix_mult_inv;
404
        }
405
406
        // the number of rounds we make depends on the block size of the text
407
        // used during encryption/decryption
408
        // 128 has a 4x4 matrix, loop 4 times
409
        // 192 has a 4x6 matrix, loop 6 times
410
        // 256 has a 4x8 matrix, loop 8 times
411
        $max_col = ($this->blockSize() * 8) / 32;
412
413
        // loop through each column of the matrix
414
        for ($col = 0; $col < $max_col; ++$col)
415
        {
416
            $pos = $col * 4;
417
418
            $a = $this->mixColumnMultiply($m[0], ord($tmp[$pos + 0]));
419
            $b = $this->mixColumnMultiply($m[4], ord($tmp[$pos + 1]));
420
            $c = $this->mixColumnMultiply($m[8], ord($tmp[$pos + 2]));
421
            $d = $this->mixColumnMultiply($m[12], ord($tmp[$pos + 3]));
422
            $t[$pos + 0] = chr($a ^ $b ^ $c ^ $d);
423
424
            $a = $this->mixColumnMultiply($m[1], ord($tmp[$pos + 0]));
425
            $b = $this->mixColumnMultiply($m[5], ord($tmp[$pos + 1]));
426
            $c = $this->mixColumnMultiply($m[9], ord($tmp[$pos + 2]));
427
            $d = $this->mixColumnMultiply($m[13], ord($tmp[$pos + 3]));
428
            $t[$pos + 1] = chr($a ^ $b ^ $c ^ $d);
429
430
            $a = $this->mixColumnMultiply($m[2], ord($tmp[$pos + 0]));
431
            $b = $this->mixColumnMultiply($m[6], ord($tmp[$pos + 1]));
432
            $c = $this->mixColumnMultiply($m[10], ord($tmp[$pos + 2]));
433
            $d = $this->mixColumnMultiply($m[14], ord($tmp[$pos + 3]));
434
            $t[$pos + 2] = chr($a ^ $b ^ $c ^ $d);
435
436
            $a = $this->mixColumnMultiply($m[3], ord($tmp[$pos + 0]));
437
            $b = $this->mixColumnMultiply($m[7], ord($tmp[$pos + 1]));
438
            $c = $this->mixColumnMultiply($m[11], ord($tmp[$pos + 2]));
439
            $d = $this->mixColumnMultiply($m[15], ord($tmp[$pos + 3]));
440
            $t[$pos + 3] = chr($a ^ $b ^ $c ^ $d);
441
        }
442
    }
443
444
445
    /**
446
     * Convert the 16, 24, or 32 bytes of $text into a matrix, and shift each row
447
     * n-bytes left for encryptiong, n-bytes right if we are decrypting.
448
     * Row shifts depend on the bit size of the block $text.
449
     * Rijndael-128/AES: 4x4 matrix
450
     * Rijndael-192:	6x4 matrix
451
     * Rijndael-256:	8x4 matrix
452
     *
453
     * @param string $text A 16, 24, or 32 byte string
454
     * @return void
455
     */
456
    private function shiftRow(&$text)
457
    {
458
        /*
459
		 * Rijndael-128 / AES
460
		 */
461
        if ($this->blockSize() == 16)
462
        {
463
            if ($this->operation() == parent::ENCRYPT)
464
            {
465
                // create a 4x4 matrix
466
                // row 0 is unchanged,
467
                // shift row 1 left 1 byte
468
                // shift row 2 left 2 bytes
469
                // shift row 3 left 3 bytes
470
                $text = $text[0].$text[5].$text[10].$text[15].$text[4].$text[9].
471
                        $text[14].$text[3].$text[8].$text[13].$text[2].$text[7].
472
                        $text[12].$text[1].$text[6].$text[11];
473
            } else // parent::DECRYPT
474
            {
475
                // create a 4x4 matrix
476
                // row 0 is unchanged,
477
                // shift row 1 right 1 byte
478
                // shift row 2 right 2 bytes
479
                // shift row 3 right 3 bytes
480
                $text = $text[0].$text[13].$text[10].$text[7].$text[4].$text[1].
481
                        $text[14].$text[11].$text[8].$text[5].$text[2].$text[15].
482
                        $text[12].$text[9].$text[6].$text[3];
483
            }
484
        }
485
486
        /*
487
		 * Rijndael-192
488
		 */
489
        if ($this->blockSize() == 24)
490
        {
491
            if ($this->operation() == parent::ENCRYPT)
492
            {
493
                // create a 6x4 matrix
494
                // row 0 is unchanged
495
                // shift row 1 left 1 byte
496
                // shift row 2 left 2 bytes
497
                // shift row 3 left 3 bytes
498
                $text = $text[0].$text[5].$text[10].$text[15].$text[4].$text[9].
499
                        $text[14].$text[19].$text[8].$text[13].$text[18].$text[23].
500
                        $text[12].$text[17].$text[22].$text[3].$text[16].$text[21].
501
                        $text[2].$text[7].$text[20].$text[1].$text[6].$text[11];
502
503
            } else // parent::DECRYPT
504
            {
505
                // create a 6x4 matrix
506
                // row 0 is unchanged
507
                // shift row 1 right 1 byte
508
                // shift row 2 right 2 bytes
509
                // shift row 3 right 3 bytes
510
                $text = $text[0].$text[21].$text[18].$text[15].$text[4].$text[1].
511
                        $text[22].$text[19].$text[8].$text[5].$text[2].$text[23].
512
                        $text[12].$text[9].$text[6].$text[3].$text[16].$text[13].
513
                        $text[10].$text[7].$text[20].$text[17].$text[14].$text[11];
514
            }
515
        }
516
517
        /*
518
		 * Rijndael-256
519
		 */
520
        if ($this->blockSize() == 32)
521
        {
522
            if ($this->operation() == parent::ENCRYPT)
523
            {
524
                // create an 8x4 matrix
525
                // row 0 is unchanged
526
                // shift row 1 left 1 byte
527
                // shift row 2 left 3 bytes
528
                // shift row 3 left 4 bytes
529
                $text = $text[0].$text[5].$text[14].$text[19].$text[4].$text[9].$text[18].
530
                        $text[23].$text[8].$text[13].$text[22].$text[27].$text[12].$text[17].
531
                        $text[26].$text[31].$text[16].$text[21].$text[30].$text[3].$text[20].
532
                        $text[25].$text[2].$text[7].$text[24].$text[29].$text[6].$text[11].
533
                        $text[28].$text[1].$text[10].$text[15];
534
            } else // parent::DECRYPT
535
            {
536
                // create an 8x4 matrix
537
                // row 0 is unchanged
538
                // shift row 1 right 1 byte
539
                // shift row 2 right 3 bytes
540
                // shift row 3 right 4 bytes
541
                $text = $text[0].$text[29].$text[22].$text[19].$text[4].$text[1].$text[26].
542
                        $text[23].$text[8].$text[5].$text[30].$text[27].$text[12].$text[9].
543
                        $text[2].$text[31].$text[16].$text[13].$text[6].$text[3].$text[20].
544
                        $text[17].$text[10].$text[7].$text[24].$text[21].$text[14].$text[11].
545
                        $text[28].$text[25].$text[18].$text[15];
546
            }
547
        }
548
    }
549
550
551
    /**
552
     * Applies the Sbox to each byte of the string passed in.
553
     * This is similar to subByte(), but Unlike subByte() we do not use
554
     * the _s_inv[] table. This function is only used in expandKey(),
555
     * which is implemented by the class that inherits this class
556
     *
557
     * @param string $text The string to peform the byte subsitution
558
     * @return string The string with the subsituted bytes
559
     */
560
    private function subWord(&$text)
561
    {
562
        $max = strlen($text);
563
        for ($i = 0; $i < $max; ++$i)
564
        {
565
            // the sbox is arrange in a 16 x 16 grid, where each row
566
            // and column is numbered in hex (from 0 - f)
567
            $hex = parent::str2Hex($text[$i]);
568
            $row = parent::hex2Dec($hex[0]);
569
            $col = parent::hex2Dec($hex[1]);
570
            $pos = ($row * 16) + $col;
571
572
            $text[$i] = chr(self::$_s[$pos]);
573
        }
574
    }
575
576
577
    /**
578
     * Rotate a 4 byte block of the key, moving the first byte to
579
     * to the end, and shifting everything left
580
     * Used in key Expandsion
581
     *
582
     * @param string $key_block A 4 byte string
583
     * @return string The shifted 4 byte string
584
     */
585
    private function rotWord($key_block)
586
    {
587
        return substr($key_block, 1, 3).$key_block[0];
588
    }
589
590
591
    /**
592
     * Returns 4 bytes from the expanded key starting at the given offset
593
     * Used during expandKey()
594
     *
595
     * @param integer $offset The offset within $this->xkey to grab the 4 bytes
596
     * @return string A 4 byte string from the key
597
     */
598
    private function ek($offset)
599
    {
600
        return substr($this->xkey, $offset, 4);
601
    }
602
603
604
    /**
605
     * Returns 4 bytes of the original key from the given offset
606
     * Used during expandKey()
607
     *
608
     * @param integer $offset The offset within $this->key to grab the 4 bytes
609
     * @return string A 4 byte string from the key
610
     */
611
    private function k($offset)
612
    {
613
        return substr($this->key(), $offset, 4);
614
    }
615
616
617
    /**
618
     * Return the 4 byte round constant used during expandKey().
619
     * Gets the 1 byte value from self::$_rcon and multiplies it by
620
     * 0x01000000 to create a 4 byte value
621
     *
622
     * @param integer $pos The position in self::$_rcon array to grab 1 byte
623
     * @return integer A 4 byte value
624
     */
625
    private function rcon($pos)
626
    {
627
        return (self::$_rcon[$pos] * 0x01000000);
628
    }
629
630
631
    /**
632
     * Expands the key
633
     * The key expands based on the block size as well as the key size
634
     *
635
     * @return boolean|null
636
     */
637
    protected function expandKey()
638
    {
639
        if ($this->keySize() == 16) {
640
                    return $this->expandKey128();
641
        } else if ($this->keySize() == 24) {
642
                    return $this->expandKey192();
643
        } else if ($this->keySize() == 32) {
644
                    return $this->expandKey256();
645
        }
646
    }
647
648
649
    /**
650
     * Expand a 16 byte key, the size it is expanded to varies
651
     * based on the block size of the Rijndael implementation chosen
652
     *
653
     * @return boolean
654
     */
655
    private function expandKey128()
656
    {
657
        // clear the xkey, we're creating a new one
658
        $this->xkey = "";
659
        $max = 0;
660
661
        // the number of rounds we make depends on the block size of the text
662
        // used during encryption/decryption
663
        if ($this->blockSize() == 16) {
664
                    $max = 44;
665
        }
666
        if ($this->blockSize() == 24) {
667
                    $max = 78;
668
        }
669
        if ($this->blockSize() == 32) {
670
                    $max = 120;
671
        }
672
673
        // 16 byte key expands to 176 bytes
674
        for ($i = 0; $i < $max; ++$i)
675
        {
676
            if ($i >= 0 && $i <= 3) {
677
                            $this->xkey .= $this->k($i * 4);
678
            } else if (($i % 4) == 0)
679
            {
680
                // rotate the 4 bytes
681
                $subword = $this->rotWord($this->ek(($i - 1) * 4));
682
683
                // apply the sbox
684
                $this->subWord($subword);
685
686
                // return 4 byte value based on self::$_rcon table
687
                //$rcon = $this->rcon(($i / 4) - 1);
688
                $rcon = $this->rcon(($i / 4));
689
690
                // grab 4 bytes from $this->extended_key
691
                $ek = $this->ek(($i - 4) * 4);
692
693
                $h1 = parent::str2Hex($subword);
694
                $h2 = parent::dec2Hex($rcon);
695
                $h3 = parent::str2Hex($ek);
696
                $res = parent::xorHex($h1, $h2, $h3);
697
                $this->xkey .= parent::hex2Str($res);
698
            } else
699
            {
700
                $h1 = parent::str2Hex($this->ek(($i - 1) * 4));
701
                $h2 = parent::str2Hex($this->ek(($i - 4) * 4));
702
                $res = parent::xorHex($h1, $h2);
703
                $this->xkey .= parent::hex2Str($res);
704
            }
705
        }
706
707
        return true;
708
    }
709
710
711
    /**
712
     * Expand a 24 byte key, the size it is expanded to varies
713
     * based on the block size of the Rijndael implementation chosen
714
     *
715
     * @return boolean
716
     */
717
    private function expandKey192()
718
    {
719
        // clear the xkey, we're creating a new one
720
        $this->xkey = "";
721
        $max = 0;
722
723
        // the number of rounds we make depends on the block size of the text
724
        // used during encryption/decryption
725
        if ($this->blockSize() == 16) {
726
                    $max = 52;
727
        }
728
        if ($this->blockSize() == 24) {
729
                    $max = 78;
730
        }
731
        if ($this->blockSize() == 32) {
732
                    $max = 120;
733
        }
734
735
        // 24 byte key expands to 208 bytes
736
        for ($i = 0; $i < $max; ++$i)
737
        {
738
            if ($i >= 0 && $i <= 5) {
739
                            $this->xkey .= $this->k($i * 4);
740
            } else if (($i % 6) == 0)
741
            {
742
                // rotate the 4 bytes
743
                $subword = $this->rotWord($this->ek(($i - 1) * 4));
744
745
                // apply the sbox
746
                $this->subWord($subword);
747
748
                // return 4 byte value based on self::$_rcon table
749
                //$rcon = $this->rcon(($i / 6) - 1);
750
                $rcon = $this->rcon(($i / 6));
751
752
                // grab 4 bytes from $this->extended_key
753
                $ek = $this->ek(($i - 6) * 4);
754
755
                $h1 = parent::str2Hex($subword);
756
                $h2 = parent::dec2Hex($rcon);
757
                $h3 = parent::str2Hex($ek);
758
                $res = parent::xorHex($h1, $h2, $h3);
759
                $this->xkey .= parent::hex2Str($res);
760
            } else
761
            {
762
                $h1 = parent::str2Hex($this->ek(($i - 1) * 4));
763
                $h2 = parent::str2Hex($this->ek(($i - 6) * 4));
764
                $res = parent::xorHex($h1, $h2);
765
                $this->xkey .= parent::hex2Str($res);
766
            }
767
        }
768
769
        return true;
770
    }
771
772
773
    /**
774
     * Expand a 32 byte key, the size it is expanded to varies
775
     * based on the block size of the Rijndael implementation chosen
776
     *
777
     * @return boolean
778
     */
779
    private function expandKey256()
780
    {
781
        // clear the xkey, we're creating a new one
782
        $this->xkey = "";
783
        $max = 0;
784
785
        // the number of rounds we make depends on the block size of the text
786
        // used during encryption/decryption
787
        if ($this->blockSize() == 16) {
788
                    $max = 60;
789
        }
790
        if ($this->blockSize() == 24) {
791
                    $max = 90;
792
        }
793
        if ($this->blockSize() == 32) {
794
                    $max = 120;
795
        }
796
797
        // 32 byte key expands to 240 bytes
798
        for ($i = 0; $i < $max; ++$i)
799
        {
800
            if ($i >= 0 && $i <= 7) {
801
                            $this->xkey .= $this->k($i * 4);
802
            } else if ($i % 8 == 0)
803
            {
804
                // rotate the 4 bytes
805
                $subword = $this->rotWord($this->ek(($i - 1) * 4));
806
807
                // apply the sbox
808
                $this->subWord($subword);
809
810
                // return 4 byte value based on self::$_rcon table
811
                $rcon = $this->rcon(($i / 8));
812
813
                // grab 4 bytes from $this->extended_key
814
                $ek = $this->ek(($i - 8) * 4);
815
816
                $h1 = parent::str2Hex($subword);
817
                $h2 = parent::dec2Hex($rcon);
818
                $h3 = parent::str2Hex($ek);
819
                $res = parent::xorHex($h1, $h2, $h3);
820
                $this->xkey .= parent::hex2Str($res);
821
            } else if ($i % 4 == 0)
822
            {
823
                // get the subsitution from the s-box
824
                $subword = $this->ek(($i - 1) * 4);
825
                $this->subWord($subword);
826
827
                // get the extended key part
828
                $ek = $this->ek(($i - 8) * 4);
829
830
                // xor the two parts
831
                $h1 = parent::str2Hex($subword);
832
                $h2 = parent::str2Hex($ek);
833
                $res = parent::xorHex($h1, $h2);
834
                $this->xkey .= parent::hex2Str($res);
835
            } else
836
            {
837
                $h1 = parent::str2Hex($this->ek(($i - 1) * 4));
838
                $h2 = parent::str2Hex($this->ek(($i - 8) * 4));
839
                $res = parent::xorHex($h1, $h2);
840
                $this->xkey .= parent::hex2Str($res);
841
            }
842
        }
843
844
        return true;
845
    }
846
847
848
    /**
849
     * Initalizes the tables used for Rijndael/AES encryption
850
     *
851
     * @return void
852
     */
853
    private function initTables()
854
    {
855
        // the sbox used for encryption
856
        self::$_s = array(
857
            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
858
            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
859
            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
860
            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
861
            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
862
            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
863
            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
864
            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
865
            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
866
            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
867
            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
868
            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
869
            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
870
            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
871
            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
872
            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
873
        );
874
875
        // the inverse sbox used for decryption
876
        self::$_s_inv = array(
877
            0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
878
            0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
879
            0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
880
            0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
881
            0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
882
            0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
883
            0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
884
            0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
885
            0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
886
            0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
887
            0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
888
            0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
889
            0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
890
            0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
891
            0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
892
            0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
893
        );
894
895
        // used in mixColumn() during encryption
896
        self::$_matrix_mult = array(
897
            0x02, 0x01, 0x01, 0x03,
898
            0x03, 0x02, 0x01, 0x01,
899
            0x01, 0x03, 0x02, 0x01,
900
            0x01, 0x01, 0x03, 0x02
901
        );
902
903
        // used in mixColumn() during decryption
904
        self::$_matrix_mult_inv = array(
905
            0x0e, 0x09, 0x0d, 0x0b,
906
            0x0b, 0x0e, 0x09, 0x0d,
907
            0x0d, 0x0b, 0x0e, 0x09,
908
            0x09, 0x0d, 0x0b, 0x0e
909
        );
910
911
        // The round constants, each round is a 1 byte value which should be multiplied by 0x01000000
912
        // to create a 4 byte value before being used in expandKey(). This is done in rcon()
913
        // NOTE: AES only needs the first row of values, since AES only uses 16 byte blocks,
914
        // the other values are used for larger block/key combinations supported by Rijndael
915
        // NOTE: self::$_rcon[0] is never used
916
        self::$_rcon = array(
917
            0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
918
            0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
919
            0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
920
            0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
921
            0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
922
            0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
923
            0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
924
            0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
925
            0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
926
            0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
927
            0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
928
            0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
929
            0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
930
            0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
931
            0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
932
            0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d
933
        );
934
935
        /*
936
		 * Galois Multiplication lookup tables
937
		 * See http://en.wikipedia.org/wiki/Rijndael_mix_columns#InverseMixColumns
938
		 */
939
940
        // multiply a byte by 2 (the value 2 will come from self::$_matrix_mult)
941
        self::$_gm2 = array(
942
            0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
943
            0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
944
            0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
945
            0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
946
            0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
947
            0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
948
            0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
949
            0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
950
            0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
951
            0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
952
            0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
953
            0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
954
            0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
955
            0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
956
            0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
957
            0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
958
        );
959
960
        // multiply a byte by 3 (the value 3 will come from self::$_matrix_mult)
961
        self::$_gm3 = array(
962
            0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
963
            0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
964
            0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
965
            0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
966
            0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
967
            0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
968
            0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
969
            0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
970
            0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
971
            0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
972
            0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
973
            0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
974
            0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
975
            0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
976
            0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
977
            0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
978
        );
979
980
        // multiply a byte by 9 (the value 9 will come from self::$_matrix_mult_inv)
981
        self::$_gm9 = array(
982
            0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
983
            0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
984
            0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
985
            0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
986
            0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
987
            0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
988
            0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
989
            0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
990
            0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
991
            0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
992
            0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
993
            0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
994
            0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
995
            0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
996
            0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
997
            0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
998
        );
999
1000
        // multiply a byte by 11 (the value 11 will come from self::$_matrix_mult_inv)
1001
        self::$_gm11 = array(
1002
            0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
1003
            0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
1004
            0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
1005
            0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
1006
            0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
1007
            0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
1008
            0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
1009
            0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
1010
            0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
1011
            0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
1012
            0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
1013
            0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
1014
            0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
1015
            0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
1016
            0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
1017
            0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
1018
        );
1019
1020
        // multiply a byte by 13 (the value 13 will come from self::$_matrix_mult_inv)
1021
        self::$_gm13 = array(
1022
            0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
1023
            0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
1024
            0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
1025
            0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
1026
            0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
1027
            0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
1028
            0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
1029
            0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
1030
            0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
1031
            0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
1032
            0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
1033
            0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
1034
            0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
1035
            0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
1036
            0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
1037
            0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
1038
        );
1039
1040
        // multiply a byte by 14 (the value 14 will come from self::$_matrix_mult_inv)
1041
        self::$_gm14 = array(
1042
            0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
1043
            0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
1044
            0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
1045
            0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
1046
            0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
1047
            0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
1048
            0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
1049
            0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
1050
            0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
1051
            0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
1052
            0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
1053
            0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
1054
            0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
1055
            0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
1056
            0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
1057
            0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
1058
        );
1059
    }
1060
}
1061
?>
1062