Rijndael.php 39 KB

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