Rijndael.php 42 KB

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