PageRenderTime 64ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/AES.php

https://github.com/sezuan/core
PHP | 946 lines | 548 code | 105 blank | 293 comment | 58 complexity | 84d2b14b174490a777de9c1caa185ab0 MD5 | raw file
Possible License(s): AGPL-3.0, AGPL-1.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * Pure-PHP implementation of AES.
  5. *
  6. * Uses mcrypt, if available, and an internal implementation, otherwise.
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
  11. * {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
  12. * it'll be null-padded to 160-bits and 160 bits will be the key length until {@link Crypt_Rijndael::setKey() setKey()}
  13. * is called, again, at which point, it'll be recalculated.
  14. *
  15. * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
  16. * make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
  17. * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
  18. *
  19. * Here's a short example of how to use this library:
  20. * <code>
  21. * <?php
  22. * include('Crypt/AES.php');
  23. *
  24. * $aes = new Crypt_AES();
  25. *
  26. * $aes->setKey('abcdefghijklmnop');
  27. *
  28. * $size = 10 * 1024;
  29. * $plaintext = '';
  30. * for ($i = 0; $i < $size; $i++) {
  31. * $plaintext.= 'a';
  32. * }
  33. *
  34. * echo $aes->decrypt($aes->encrypt($plaintext));
  35. * ?>
  36. * </code>
  37. *
  38. * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
  39. * of this software and associated documentation files (the "Software"), to deal
  40. * in the Software without restriction, including without limitation the rights
  41. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  42. * copies of the Software, and to permit persons to whom the Software is
  43. * furnished to do so, subject to the following conditions:
  44. *
  45. * The above copyright notice and this permission notice shall be included in
  46. * all copies or substantial portions of the Software.
  47. *
  48. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  49. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  50. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  51. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  52. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  53. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  54. * THE SOFTWARE.
  55. *
  56. * @category Crypt
  57. * @package Crypt_AES
  58. * @author Jim Wigginton <terrafrost@php.net>
  59. * @copyright MMVIII Jim Wigginton
  60. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  61. * @version $Id: AES.php,v 1.7 2010/02/09 06:10:25 terrafrost Exp $
  62. * @link http://phpseclib.sourceforge.net
  63. */
  64. /**
  65. * Include Crypt_Rijndael
  66. */
  67. if (!class_exists('Crypt_Rijndael')) {
  68. require_once 'Rijndael.php';
  69. }
  70. /**#@+
  71. * @access public
  72. * @see Crypt_AES::encrypt()
  73. * @see Crypt_AES::decrypt()
  74. */
  75. /**
  76. * Encrypt / decrypt using the Counter mode.
  77. *
  78. * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
  79. *
  80. * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
  81. */
  82. define('CRYPT_AES_MODE_CTR', -1);
  83. /**
  84. * Encrypt / decrypt using the Electronic Code Book mode.
  85. *
  86. * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
  87. */
  88. define('CRYPT_AES_MODE_ECB', 1);
  89. /**
  90. * Encrypt / decrypt using the Code Book Chaining mode.
  91. *
  92. * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
  93. */
  94. define('CRYPT_AES_MODE_CBC', 2);
  95. /**
  96. * Encrypt / decrypt using the Cipher Feedback mode.
  97. *
  98. * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
  99. */
  100. define('CRYPT_AES_MODE_CFB', 3);
  101. /**
  102. * Encrypt / decrypt using the Cipher Feedback mode.
  103. *
  104. * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
  105. */
  106. define('CRYPT_AES_MODE_OFB', 4);
  107. /**#@-*/
  108. /**#@+
  109. * @access private
  110. * @see Crypt_AES::Crypt_AES()
  111. */
  112. /**
  113. * Toggles the internal implementation
  114. */
  115. define('CRYPT_AES_MODE_INTERNAL', 1);
  116. /**
  117. * Toggles the mcrypt implementation
  118. */
  119. define('CRYPT_AES_MODE_MCRYPT', 2);
  120. /**#@-*/
  121. /**
  122. * Pure-PHP implementation of AES.
  123. *
  124. * @author Jim Wigginton <terrafrost@php.net>
  125. * @version 0.1.0
  126. * @access public
  127. * @package Crypt_AES
  128. */
  129. class Crypt_AES extends Crypt_Rijndael {
  130. /**
  131. * mcrypt resource for encryption
  132. *
  133. * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
  134. * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
  135. *
  136. * @see Crypt_AES::encrypt()
  137. * @var String
  138. * @access private
  139. */
  140. var $enmcrypt;
  141. /**
  142. * mcrypt resource for decryption
  143. *
  144. * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
  145. * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
  146. *
  147. * @see Crypt_AES::decrypt()
  148. * @var String
  149. * @access private
  150. */
  151. var $demcrypt;
  152. /**
  153. * mcrypt resource for CFB mode
  154. *
  155. * @see Crypt_AES::encrypt()
  156. * @see Crypt_AES::decrypt()
  157. * @var String
  158. * @access private
  159. */
  160. var $ecb;
  161. /**
  162. * The SubByte S-Box
  163. *
  164. * @see Crypt_AES::_encryptBlock()
  165. * @var Array
  166. * @access intern
  167. */
  168. var $sbox = array(
  169. 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
  170. 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
  171. 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
  172. 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
  173. 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
  174. 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
  175. 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
  176. 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
  177. 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
  178. 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
  179. 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
  180. 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
  181. 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
  182. 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
  183. 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
  184. 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
  185. );
  186. /**
  187. * The inverse SubByte S-Box
  188. *
  189. * @see Crypt_AES::_decryptBlock()
  190. * @var Array
  191. * @access intern
  192. */
  193. var $isbox = array(
  194. 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
  195. 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
  196. 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
  197. 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
  198. 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
  199. 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
  200. 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
  201. 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
  202. 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
  203. 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
  204. 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
  205. 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
  206. 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
  207. 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
  208. 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
  209. 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
  210. );
  211. /**
  212. * Default Constructor.
  213. *
  214. * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
  215. * CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
  216. *
  217. * @param optional Integer $mode
  218. * @return Crypt_AES
  219. * @access public
  220. */
  221. function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
  222. {
  223. if ( !defined('CRYPT_AES_MODE') ) {
  224. switch (true) {
  225. case extension_loaded('mcrypt') && in_array('rijndael-128', mcrypt_list_algorithms()):
  226. define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
  227. break;
  228. default:
  229. define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
  230. }
  231. }
  232. switch ( CRYPT_AES_MODE ) {
  233. case CRYPT_AES_MODE_MCRYPT:
  234. switch ($mode) {
  235. case CRYPT_AES_MODE_ECB:
  236. $this->paddable = true;
  237. $this->mode = MCRYPT_MODE_ECB;
  238. break;
  239. case CRYPT_AES_MODE_CTR:
  240. // ctr doesn't have a constant associated with it even though it appears to be fairly widely
  241. // supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to
  242. // include a compatibility layer. the layer has been implemented but, for now, is commented out.
  243. $this->mode = 'ctr';
  244. //$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
  245. break;
  246. case CRYPT_AES_MODE_CFB:
  247. $this->mode = 'ncfb';
  248. break;
  249. case CRYPT_AES_MODE_OFB:
  250. $this->mode = MCRYPT_MODE_NOFB;
  251. break;
  252. case CRYPT_AES_MODE_CBC:
  253. default:
  254. $this->paddable = true;
  255. $this->mode = MCRYPT_MODE_CBC;
  256. }
  257. break;
  258. default:
  259. switch ($mode) {
  260. case CRYPT_AES_MODE_ECB:
  261. $this->paddable = true;
  262. $this->mode = CRYPT_RIJNDAEL_MODE_ECB;
  263. break;
  264. case CRYPT_AES_MODE_CTR:
  265. $this->mode = CRYPT_RIJNDAEL_MODE_CTR;
  266. break;
  267. case CRYPT_AES_MODE_CFB:
  268. $this->mode = CRYPT_RIJNDAEL_MODE_CFB;
  269. break;
  270. case CRYPT_AES_MODE_OFB:
  271. $this->mode = CRYPT_RIJNDAEL_MODE_OFB;
  272. break;
  273. case CRYPT_AES_MODE_CBC:
  274. default:
  275. $this->paddable = true;
  276. $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
  277. }
  278. }
  279. if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
  280. parent::Crypt_Rijndael($this->mode);
  281. }
  282. }
  283. /**
  284. * Extended Crypt_Rijndael::_setup()
  285. *
  286. * Optimizing the key schedule arrays ($w, $dw) for _encryptBlock() and _decryptBlock() after Crypt_Rijndael::_setup()
  287. *
  288. * @see Crypt_Rijndael::_setup()
  289. * @access private
  290. */
  291. function _setup()
  292. {
  293. if (!$this->changed) {
  294. return;
  295. }
  296. $this->w = $this->dw = array();
  297. parent::_setup();
  298. $this->dw = array_reverse($this->dw);
  299. $w = array_pop($this->w);
  300. $dw = array_pop($this->dw);
  301. foreach ($this->w as $r => $wr) {
  302. foreach ($wr as $c => $wc) {
  303. $w[] = $wc;
  304. $dw[] = $this->dw[$r][$c];
  305. }
  306. }
  307. $this->w = $w;
  308. $this->dw = $dw;
  309. }
  310. /**
  311. * Dummy function
  312. *
  313. * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
  314. *
  315. * @access public
  316. * @param Integer $length
  317. */
  318. function setBlockLength($length)
  319. {
  320. return;
  321. }
  322. /**
  323. * Sets the initialization vector. (optional)
  324. *
  325. * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
  326. * to be all zero's.
  327. *
  328. * @access public
  329. * @param String $iv
  330. */
  331. function setIV($iv)
  332. {
  333. parent::setIV($iv);
  334. if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
  335. $this->changed = true;
  336. }
  337. }
  338. /**
  339. * Encrypts a message.
  340. *
  341. * $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
  342. * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
  343. * URL:
  344. *
  345. * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
  346. *
  347. * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
  348. * strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
  349. * length.
  350. *
  351. * @see Crypt_AES::decrypt()
  352. * @access public
  353. * @param String $plaintext
  354. */
  355. function encrypt($plaintext)
  356. {
  357. if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
  358. $this->_mcryptSetup();
  359. // re: http://phpseclib.sourceforge.net/cfb-demo.phps
  360. // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
  361. // rewritten CFB implementation the above outputs the same thing twice.
  362. if ($this->mode == 'ncfb' && $this->continuousBuffer) {
  363. $iv = &$this->encryptIV;
  364. $pos = &$this->enbuffer['pos'];
  365. $len = strlen($plaintext);
  366. $ciphertext = '';
  367. $i = 0;
  368. if ($pos) {
  369. $orig_pos = $pos;
  370. $max = 16 - $pos;
  371. if ($len >= $max) {
  372. $i = $max;
  373. $len-= $max;
  374. $pos = 0;
  375. } else {
  376. $i = $len;
  377. $pos+= $len;
  378. $len = 0;
  379. }
  380. $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
  381. $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
  382. $this->enbuffer['enmcrypt_init'] = true;
  383. }
  384. if ($len >= 16) {
  385. if ($this->enbuffer['enmcrypt_init'] === false || $len > 280) {
  386. if ($this->enbuffer['enmcrypt_init'] === true) {
  387. mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
  388. $this->enbuffer['enmcrypt_init'] = false;
  389. }
  390. $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 16));
  391. $iv = substr($ciphertext, -16);
  392. $len%= 16;
  393. } else {
  394. while ($len >= 16) {
  395. $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 16);
  396. $ciphertext.= $iv;
  397. $len-= 16;
  398. $i+= 16;
  399. }
  400. }
  401. }
  402. if ($len) {
  403. $iv = mcrypt_generic($this->ecb, $iv);
  404. $block = $iv ^ substr($plaintext, -$len);
  405. $iv = substr_replace($iv, $block, 0, $len);
  406. $ciphertext.= $block;
  407. $pos = $len;
  408. }
  409. return $ciphertext;
  410. }
  411. if ($this->paddable) {
  412. $plaintext = $this->_pad($plaintext);
  413. }
  414. $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
  415. if (!$this->continuousBuffer) {
  416. mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
  417. }
  418. return $ciphertext;
  419. }
  420. return parent::encrypt($plaintext);
  421. }
  422. /**
  423. * Decrypts a message.
  424. *
  425. * If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
  426. *
  427. * @see Crypt_AES::encrypt()
  428. * @access public
  429. * @param String $ciphertext
  430. */
  431. function decrypt($ciphertext)
  432. {
  433. if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
  434. $this->_mcryptSetup();
  435. if ($this->mode == 'ncfb' && $this->continuousBuffer) {
  436. $iv = &$this->decryptIV;
  437. $pos = &$this->debuffer['pos'];
  438. $len = strlen($ciphertext);
  439. $plaintext = '';
  440. $i = 0;
  441. if ($pos) {
  442. $orig_pos = $pos;
  443. $max = 16 - $pos;
  444. if ($len >= $max) {
  445. $i = $max;
  446. $len-= $max;
  447. $pos = 0;
  448. } else {
  449. $i = $len;
  450. $pos+= $len;
  451. $len = 0;
  452. }
  453. // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
  454. $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
  455. $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
  456. }
  457. if ($len >= 16) {
  458. $cb = substr($ciphertext, $i, $len - $len % 16);
  459. $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
  460. $iv = substr($cb, -16);
  461. $len%= 16;
  462. }
  463. if ($len) {
  464. $iv = mcrypt_generic($this->ecb, $iv);
  465. $plaintext.= $iv ^ substr($ciphertext, -$len);
  466. $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
  467. $pos = $len;
  468. }
  469. return $plaintext;
  470. }
  471. if ($this->paddable) {
  472. // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
  473. // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
  474. $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
  475. }
  476. $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
  477. if (!$this->continuousBuffer) {
  478. mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
  479. }
  480. return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
  481. }
  482. return parent::decrypt($ciphertext);
  483. }
  484. /**
  485. * Setup mcrypt
  486. *
  487. * Validates all the variables.
  488. *
  489. * @access private
  490. */
  491. function _mcryptSetup()
  492. {
  493. if (!$this->changed) {
  494. return;
  495. }
  496. if (!$this->explicit_key_length) {
  497. // this just copied from Crypt_Rijndael::_setup()
  498. $length = strlen($this->key) >> 2;
  499. if ($length > 8) {
  500. $length = 8;
  501. } else if ($length < 4) {
  502. $length = 4;
  503. }
  504. $this->Nk = $length;
  505. $this->key_size = $length << 2;
  506. }
  507. switch ($this->Nk) {
  508. case 4: // 128
  509. $this->key_size = 16;
  510. break;
  511. case 5: // 160
  512. case 6: // 192
  513. $this->key_size = 24;
  514. break;
  515. case 7: // 224
  516. case 8: // 256
  517. $this->key_size = 32;
  518. }
  519. $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
  520. $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
  521. if (!isset($this->enmcrypt)) {
  522. $mode = $this->mode;
  523. //$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
  524. $this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
  525. $this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
  526. if ($mode == 'ncfb') {
  527. $this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
  528. }
  529. } // else should mcrypt_generic_deinit be called?
  530. mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
  531. mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
  532. if ($this->mode == 'ncfb') {
  533. mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
  534. }
  535. $this->changed = false;
  536. }
  537. /**
  538. * Encrypts a block
  539. *
  540. * Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
  541. *
  542. * @see Crypt_Rijndael::_encryptBlock()
  543. * @access private
  544. * @param String $in
  545. * @return String
  546. */
  547. function _encryptBlock($in)
  548. {
  549. $state = unpack('N*', $in);
  550. $sbox = $this->sbox;
  551. $w = $this->w;
  552. $t0 = $this->t0;
  553. $t1 = $this->t1;
  554. $t2 = $this->t2;
  555. $t3 = $this->t3;
  556. // addRoundKey
  557. $s0 = $state[1] ^ $w[4];
  558. $s1 = $state[2] ^ $w[5];
  559. $s2 = $state[3] ^ $w[6];
  560. $s3 = $state[4] ^ $w[7];
  561. // shiftRows + subWord + mixColumns + addRoundKey
  562. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[8];
  563. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[9];
  564. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[10];
  565. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[11];
  566. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[12];
  567. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[13];
  568. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[14];
  569. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[15];
  570. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[16];
  571. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[17];
  572. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[18];
  573. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[19];
  574. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[20];
  575. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[21];
  576. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[22];
  577. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[23];
  578. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[24];
  579. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[25];
  580. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[26];
  581. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[27];
  582. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[28];
  583. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[29];
  584. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[30];
  585. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[31];
  586. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[32];
  587. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[33];
  588. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[34];
  589. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[35];
  590. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[36];
  591. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[37];
  592. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[38];
  593. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[39];
  594. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[40];
  595. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[41];
  596. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[42];
  597. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[43];
  598. switch ($this->Nr) {
  599. case 10:
  600. break;
  601. case 14:
  602. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
  603. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
  604. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
  605. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
  606. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
  607. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
  608. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
  609. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
  610. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[52];
  611. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[53];
  612. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[54];
  613. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[55];
  614. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[56];
  615. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[57];
  616. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[58];
  617. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[59];
  618. break;
  619. case 12:
  620. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
  621. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
  622. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
  623. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
  624. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
  625. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
  626. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
  627. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
  628. break;
  629. case 13:
  630. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
  631. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
  632. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
  633. $s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
  634. $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
  635. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
  636. $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
  637. $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
  638. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[52];
  639. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[53];
  640. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[54];
  641. $e3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[55];
  642. // Note: Here we skip $s3 but using $e3
  643. $e0 = $s0;
  644. $e1 = $s1;
  645. $e2 = $s2;
  646. // $e3 = $s3;
  647. break;
  648. default: // 11
  649. $s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
  650. $s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
  651. $s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
  652. $e3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
  653. // Note: Here we skip $s3 but using $e3
  654. $e0 = $s0;
  655. $e1 = $s1;
  656. $e2 = $s2;
  657. // $e3 = $s3;
  658. }
  659. // subWord
  660. $e0 = $sbox[$e0 & 0xff] | ($sbox[($e0 >> 8) & 0xff] << 8) | ($sbox[($e0 >> 16) & 0xff] << 16) | ($sbox[($e0 >> 24) & 0xff] << 24);
  661. $e1 = $sbox[$e1 & 0xff] | ($sbox[($e1 >> 8) & 0xff] << 8) | ($sbox[($e1 >> 16) & 0xff] << 16) | ($sbox[($e1 >> 24) & 0xff] << 24);
  662. $e2 = $sbox[$e2 & 0xff] | ($sbox[($e2 >> 8) & 0xff] << 8) | ($sbox[($e2 >> 16) & 0xff] << 16) | ($sbox[($e2 >> 24) & 0xff] << 24);
  663. $e3 = $sbox[$e3 & 0xff] | ($sbox[($e3 >> 8) & 0xff] << 8) | ($sbox[($e3 >> 16) & 0xff] << 16) | ($sbox[($e3 >> 24) & 0xff] << 24);
  664. // shiftRows + addRoundKey
  665. return pack('N*',
  666. ($e0 & 0xFF000000) ^ ($e1 & 0x00FF0000) ^ ($e2 & 0x0000FF00) ^ ($e3 & 0x000000FF) ^ $w[0],
  667. ($e1 & 0xFF000000) ^ ($e2 & 0x00FF0000) ^ ($e3 & 0x0000FF00) ^ ($e0 & 0x000000FF) ^ $w[1],
  668. ($e2 & 0xFF000000) ^ ($e3 & 0x00FF0000) ^ ($e0 & 0x0000FF00) ^ ($e1 & 0x000000FF) ^ $w[2],
  669. ($e3 & 0xFF000000) ^ ($e0 & 0x00FF0000) ^ ($e1 & 0x0000FF00) ^ ($e2 & 0x000000FF) ^ $w[3]
  670. );
  671. }
  672. /**
  673. * Decrypts a block
  674. *
  675. * Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
  676. *
  677. * @see Crypt_Rijndael::_decryptBlock()
  678. * @access private
  679. * @param String $in
  680. * @return String
  681. */
  682. function _decryptBlock($in)
  683. {
  684. $state = unpack('N*', $in);
  685. $sbox = $this->isbox;
  686. $dw = $this->dw;
  687. $dt0 = $this->dt0;
  688. $dt1 = $this->dt1;
  689. $dt2 = $this->dt2;
  690. $dt3 = $this->dt3;
  691. // addRoundKey
  692. $s0 = $state[1] ^ $dw[4];
  693. $s1 = $state[2] ^ $dw[5];
  694. $s2 = $state[3] ^ $dw[6];
  695. $s3 = $state[4] ^ $dw[7];
  696. // invShiftRows + invSubBytes + invMixColumns + addRoundKey
  697. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[8];
  698. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[9];
  699. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[10];
  700. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[11];
  701. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[12];
  702. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[13];
  703. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[14];
  704. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[15];
  705. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[16];
  706. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[17];
  707. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[18];
  708. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[19];
  709. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[20];
  710. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[21];
  711. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[22];
  712. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[23];
  713. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[24];
  714. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[25];
  715. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[26];
  716. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[27];
  717. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[28];
  718. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[29];
  719. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[30];
  720. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[31];
  721. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[32];
  722. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[33];
  723. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[34];
  724. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[35];
  725. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[36];
  726. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[37];
  727. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[38];
  728. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[39];
  729. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[40];
  730. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[41];
  731. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[42];
  732. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[43];
  733. switch ($this->Nr) {
  734. case 10:
  735. break;
  736. case 14:
  737. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
  738. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
  739. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
  740. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
  741. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
  742. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
  743. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
  744. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
  745. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[52];
  746. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[53];
  747. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[54];
  748. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55];
  749. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[56];
  750. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[57];
  751. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[58];
  752. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[59];
  753. break;
  754. case 12:
  755. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
  756. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
  757. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
  758. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
  759. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
  760. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
  761. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
  762. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
  763. break;
  764. case 13:
  765. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
  766. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
  767. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
  768. $s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
  769. $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
  770. $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
  771. $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
  772. $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
  773. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[52];
  774. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[53];
  775. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[54];
  776. $e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55];
  777. // Note: Here we skip $s3 but using $e3
  778. $e0 = $s0;
  779. $e1 = $s1;
  780. $e2 = $s2;
  781. // $e3 = $s3;
  782. break;
  783. default: // 11
  784. $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
  785. $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
  786. $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
  787. $e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
  788. // Note: Here we skip $s3 but using $e3
  789. $e0 = $s0;
  790. $e1 = $s1;
  791. $e2 = $s2;
  792. // $e3 = $s3;
  793. }
  794. // invSubWord
  795. $e0 = $sbox[$e0 & 0xff] | ($sbox[($e0 >> 8) & 0xff] << 8) | ($sbox[($e0 >> 16) & 0xff] << 16) | ($sbox[($e0 >> 24) & 0xff] << 24);
  796. $e1 = $sbox[$e1 & 0xff] | ($sbox[($e1 >> 8) & 0xff] << 8) | ($sbox[($e1 >> 16) & 0xff] << 16) | ($sbox[($e1 >> 24) & 0xff] << 24);
  797. $e2 = $sbox[$e2 & 0xff] | ($sbox[($e2 >> 8) & 0xff] << 8) | ($sbox[($e2 >> 16) & 0xff] << 16) | ($sbox[($e2 >> 24) & 0xff] << 24);
  798. $e3 = $sbox[$e3 & 0xff] | ($sbox[($e3 >> 8) & 0xff] << 8) | ($sbox[($e3 >> 16) & 0xff] << 16) | ($sbox[($e3 >> 24) & 0xff] << 24);
  799. // invShiftRows + addRoundKey
  800. return pack('N*',
  801. ($e0 & 0xFF000000) ^ ($e3 & 0x00FF0000) ^ ($e2 & 0x0000FF00) ^ ($e1 & 0x000000FF) ^ $dw[0],
  802. ($e1 & 0xFF000000) ^ ($e0 & 0x00FF0000) ^ ($e3 & 0x0000FF00) ^ ($e2 & 0x000000FF) ^ $dw[1],
  803. ($e2 & 0xFF000000) ^ ($e1 & 0x00FF0000) ^ ($e0 & 0x0000FF00) ^ ($e3 & 0x000000FF) ^ $dw[2],
  804. ($e3 & 0xFF000000) ^ ($e2 & 0x00FF0000) ^ ($e1 & 0x0000FF00) ^ ($e0 & 0x000000FF) ^ $dw[3]
  805. );
  806. }
  807. /**
  808. * Treat consecutive "packets" as if they are a continuous buffer.
  809. *
  810. * The default behavior.
  811. *
  812. * @see Crypt_Rijndael::disableContinuousBuffer()
  813. * @access public
  814. */
  815. function enableContinuousBuffer()
  816. {
  817. parent::enableContinuousBuffer();
  818. if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
  819. $this->enbuffer['enmcrypt_init'] = true;
  820. $this->debuffer['demcrypt_init'] = true;
  821. }
  822. }
  823. /**
  824. * Treat consecutive packets as if they are a discontinuous buffer.
  825. *
  826. * The default behavior.
  827. *
  828. * @see Crypt_Rijndael::enableContinuousBuffer()
  829. * @access public
  830. */
  831. function disableContinuousBuffer()
  832. {
  833. parent::disableContinuousBuffer();
  834. if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
  835. mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
  836. mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
  837. }
  838. }
  839. }
  840. // vim: ts=4:sw=4:et:
  841. // vim6: fdl=1: