Rijndael.php 45 KB

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