PluginProbe
Contact Forms by Cimatti / 1.9.2
Contact Forms by Cimatti v1.9.2
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
← All changes | phpseclib-crypt/Rijndael.php +599 -1027 1.31.9.2 View file →
@@ -1,35 +1,35 @@
1 1 <?php
2 -/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3 2
4 3 /**
5 4 * Pure-PHP implementation of Rijndael.
6 5 *
7 - * Does not use mcrypt, even when available, for reasons that are explained below.
6 + * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
8 7 *
9 8 * PHP versions 4 and 5
10 9 *
11 - * If {@link Crypt_Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
12 - * {@link Crypt_Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
13 - * {@link Crypt_Rijndael::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
14 - * 136-bits it'll be null-padded to 160-bits and 160 bits will be the key length until
15 - * {@link Crypt_Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated.
10 + * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
11 + * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12 + * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
13 + * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
14 + * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
16 15 *
17 16 * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
18 17 * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
19 18 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
20 19 * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224. Indeed, 160 and 224
21 - * are first defined as valid key / block lengths in
22 - * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
20 + * are first defined as valid key / block lengths in
21 + * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
23 22 * Extensions: Other block and Cipher Key lengths.
23 + * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
24 24 *
25 - * {@internal The variable names are the same as those in
25 + * {@internal The variable names are the same as those in
26 26 * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
27 27 *
28 28 * Here's a short example of how to use this library:
29 29 * <code>
30 30 * <?php
31 - * include('Crypt/Rijndael.php');
31 + * include 'Crypt/Rijndael.php';
32 32 *
33 33 * $rijndael = new Crypt_Rijndael();
34 34 *
35 35 * $rijndael->setKey('abcdefghijklmnop');
@@ -49,12 +49,12 @@
49 49 * in the Software without restriction, including without limitation the rights
50 50 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
51 51 * copies of the Software, and to permit persons to whom the Software is
52 52 * furnished to do so, subject to the following conditions:
53 - *
53 + *
54 54 * The above copyright notice and this permission notice shall be included in
55 55 * all copies or substantial portions of the Software.
56 - *
56 + *
57 57 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58 58 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
59 59 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
60 60 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
@@ -61,21 +61,29 @@
61 61 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62 62 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63 63 * THE SOFTWARE.
64 64 *
65 - * @category Crypt
66 - * @package Crypt_Rijndael
67 - * @author Jim Wigginton <terrafrost@php.net>
68 - * @copyright MMVIII Jim Wigginton
69 - * @license http://www.opensource.org/licenses/mit-license.html MIT License
70 - * @version $Id: Rijndael.php,v 1.12 2010/02/09 06:10:26 terrafrost Exp $
71 - * @link http://phpseclib.sourceforge.net
65 + * @category Crypt
66 + * @package Crypt_Rijndael
67 + * @author Jim Wigginton <terrafrost@php.net>
68 + * @copyright 2008 Jim Wigginton
69 + * @license http://www.opensource.org/licenses/mit-license.html MIT License
70 + * @link http://phpseclib.sourceforge.net
72 71 */
73 72
73 +/**
74 + * Include Crypt_Base
75 + *
76 + * Base cipher class
77 + */
78 +if (!class_exists('Crypt_Base')) {
79 + include_once 'Base.php';
80 +}
81 +
74 82 /**#@+
75 83 * @access public
76 - * @see Crypt_Rijndael::encrypt()
77 - * @see Crypt_Rijndael::decrypt()
84 + * @see self::encrypt()
85 + * @see self::decrypt()
78 86 */
79 87 /**
80 88 * Encrypt / decrypt using the Counter mode.
81 89 *
@@ -82,146 +90,84 @@
82 90 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
83 91 *
84 92 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
85 93 */
86 -define('CRYPT_RIJNDAEL_MODE_CTR', -1);
94 +define('CRYPT_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR);
87 95 /**
88 96 * Encrypt / decrypt using the Electronic Code Book mode.
89 97 *
90 98 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
91 99 */
92 -define('CRYPT_RIJNDAEL_MODE_ECB', 1);
100 +define('CRYPT_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB);
93 101 /**
94 102 * Encrypt / decrypt using the Code Book Chaining mode.
95 103 *
96 104 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
97 105 */
98 -define('CRYPT_RIJNDAEL_MODE_CBC', 2);
106 +define('CRYPT_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC);
99 107 /**
100 108 * Encrypt / decrypt using the Cipher Feedback mode.
101 109 *
102 110 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
103 111 */
104 -define('CRYPT_RIJNDAEL_MODE_CFB', 3);
112 +define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB);
105 113 /**
106 114 * Encrypt / decrypt using the Cipher Feedback mode.
107 115 *
108 116 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
109 117 */
110 -define('CRYPT_RIJNDAEL_MODE_OFB', 4);
118 +define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
111 119 /**#@-*/
112 120
113 -/**#@+
114 - * @access private
115 - * @see Crypt_Rijndael::Crypt_Rijndael()
116 - */
117 121 /**
118 - * Toggles the internal implementation
119 - */
120 -define('CRYPT_RIJNDAEL_MODE_INTERNAL', 1);
121 -/**
122 - * Toggles the mcrypt implementation
123 - */
124 -define('CRYPT_RIJNDAEL_MODE_MCRYPT', 2);
125 -/**#@-*/
126 -
127 -/**
128 122 * Pure-PHP implementation of Rijndael.
129 123 *
124 + * @package Crypt_Rijndael
130 125 * @author Jim Wigginton <terrafrost@php.net>
131 - * @version 0.1.0
132 126 * @access public
133 - * @package Crypt_Rijndael
134 127 */
135 -class Crypt_Rijndael {
128 +class Crypt_Rijndael extends Crypt_Base
129 +{
136 130 /**
137 - * The Encryption Mode
131 + * The namespace used by the cipher for its constants.
138 132 *
139 - * @see Crypt_Rijndael::Crypt_Rijndael()
140 - * @var Integer
133 + * @see Crypt_Base::const_namespace
134 + * @var string
141 135 * @access private
142 136 */
143 - var $mode;
137 + var $const_namespace = 'RIJNDAEL';
144 138
145 139 /**
146 - * The Key
140 + * The mcrypt specific name of the cipher
147 141 *
148 - * @see Crypt_Rijndael::setKey()
149 - * @var String
150 - * @access private
151 - */
152 - var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
153 -
154 - /**
155 - * The Initialization Vector
142 + * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
143 + * Crypt_Rijndael determines automatically whether mcrypt is useable
144 + * or not for the current $block_size/$key_length.
145 + * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
156 146 *
157 - * @see Crypt_Rijndael::setIV()
158 - * @var String
147 + * @see Crypt_Base::cipher_name_mcrypt
148 + * @see Crypt_Base::engine
149 + * @see self::isValidEngine()
150 + * @var string
159 151 * @access private
160 152 */
161 - var $iv = '';
153 + var $cipher_name_mcrypt = 'rijndael-128';
162 154
163 155 /**
164 - * A "sliding" Initialization Vector
156 + * The default salt used by setPassword()
165 157 *
166 - * @see Crypt_Rijndael::enableContinuousBuffer()
167 - * @var String
158 + * @see Crypt_Base::password_default_salt
159 + * @see Crypt_Base::setPassword()
160 + * @var string
168 161 * @access private
169 162 */
170 - var $encryptIV = '';
163 + var $password_default_salt = 'phpseclib';
171 164
172 165 /**
173 - * A "sliding" Initialization Vector
174 - *
175 - * @see Crypt_Rijndael::enableContinuousBuffer()
176 - * @var String
177 - * @access private
178 - */
179 - var $decryptIV = '';
180 -
181 - /**
182 - * Continuous Buffer status
183 - *
184 - * @see Crypt_Rijndael::enableContinuousBuffer()
185 - * @var Boolean
186 - * @access private
187 - */
188 - var $continuousBuffer = false;
189 -
190 - /**
191 - * Padding status
192 - *
193 - * @see Crypt_Rijndael::enablePadding()
194 - * @var Boolean
195 - * @access private
196 - */
197 - var $padding = true;
198 -
199 - /**
200 - * Does the key schedule need to be (re)calculated?
201 - *
202 - * @see setKey()
203 - * @see setBlockLength()
204 - * @see setKeyLength()
205 - * @var Boolean
206 - * @access private
207 - */
208 - var $changed = true;
209 -
210 - /**
211 - * Has the key length explicitly been set or should it be derived from the key, itself?
212 - *
213 - * @see setKeyLength()
214 - * @var Boolean
215 - * @access private
216 - */
217 - var $explicit_key_length = false;
218 -
219 - /**
220 166 * The Key Schedule
221 167 *
222 - * @see _setup()
223 - * @var Array
168 + * @see self::_setup()
169 + * @var array
224 170 * @access private
225 171 */
226 172 var $w;
227 173
@@ -227,57 +173,45 @@
227 173
228 174 /**
229 175 * The Inverse Key Schedule
230 176 *
231 - * @see _setup()
232 - * @var Array
177 + * @see self::_setup()
178 + * @var array
233 179 * @access private
234 180 */
235 181 var $dw;
236 182
237 183 /**
238 - * The Block Length
239 - *
240 - * @see setBlockLength()
241 - * @var Integer
242 - * @access private
243 - * @internal The max value is 32, the min value is 16. All valid values are multiples of 4. Exists in conjunction with
244 - * $Nb because we need this value and not $Nb to pad strings appropriately.
245 - */
246 - var $block_size = 16;
247 -
248 - /**
249 184 * The Block Length divided by 32
250 185 *
251 - * @see setBlockLength()
252 - * @var Integer
186 + * @see self::setBlockLength()
187 + * @var int
253 188 * @access private
254 - * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
255 - * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
189 + * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
190 + * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
256 191 * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
257 192 * of that, we'll just precompute it once.
258 - *
259 193 */
260 194 var $Nb = 4;
261 195
262 196 /**
263 - * The Key Length
197 + * The Key Length (in bytes)
264 198 *
265 - * @see setKeyLength()
266 - * @var Integer
199 + * @see self::setKeyLength()
200 + * @var int
267 201 * @access private
268 - * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $key_size
269 - * because the encryption / decryption / key schedule creation requires this number and not $key_size. We could
270 - * derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
202 + * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
203 + * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
204 + * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
271 205 * of that, we'll just precompute it once.
272 206 */
273 - var $key_size = 16;
207 + var $key_length = 16;
274 208
275 209 /**
276 210 * The Key Length divided by 32
277 211 *
278 - * @see setKeyLength()
279 - * @var Integer
212 + * @see self::setKeyLength()
213 + * @var int
280 214 * @access private
281 215 * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
282 216 */
283 217 var $Nk = 4;
@@ -284,9 +218,9 @@
284 218
285 219 /**
286 220 * The Number of Rounds
287 221 *
288 - * @var Integer
222 + * @var int
289 223 * @access private
290 224 * @internal The max value is 14, the min value is 10.
291 225 */
292 226 var $Nr;
@@ -293,235 +227,22 @@
293 227
294 228 /**
295 229 * Shift offsets
296 230 *
297 - * @var Array
231 + * @var array
298 232 * @access private
299 233 */
300 234 var $c;
301 235
302 236 /**
303 - * Precomputed mixColumns table
237 + * Holds the last used key- and block_size information
304 238 *
305 - * @see Crypt_Rijndael()
306 - * @var Array
239 + * @var array
307 240 * @access private
308 241 */
309 - var $t0;
242 + var $kl;
310 243
311 244 /**
312 - * Precomputed mixColumns table
313 - *
314 - * @see Crypt_Rijndael()
315 - * @var Array
316 - * @access private
317 - */
318 - var $t1;
319 -
320 - /**
321 - * Precomputed mixColumns table
322 - *
323 - * @see Crypt_Rijndael()
324 - * @var Array
325 - * @access private
326 - */
327 - var $t2;
328 -
329 - /**
330 - * Precomputed mixColumns table
331 - *
332 - * @see Crypt_Rijndael()
333 - * @var Array
334 - * @access private
335 - */
336 - var $t3;
337 -
338 - /**
339 - * Precomputed invMixColumns table
340 - *
341 - * @see Crypt_Rijndael()
342 - * @var Array
343 - * @access private
344 - */
345 - var $dt0;
346 -
347 - /**
348 - * Precomputed invMixColumns table
349 - *
350 - * @see Crypt_Rijndael()
351 - * @var Array
352 - * @access private
353 - */
354 - var $dt1;
355 -
356 - /**
357 - * Precomputed invMixColumns table
358 - *
359 - * @see Crypt_Rijndael()
360 - * @var Array
361 - * @access private
362 - */
363 - var $dt2;
364 -
365 - /**
366 - * Precomputed invMixColumns table
367 - *
368 - * @see Crypt_Rijndael()
369 - * @var Array
370 - * @access private
371 - */
372 - var $dt3;
373 -
374 - /**
375 - * Is the mode one that is paddable?
376 - *
377 - * @see Crypt_Rijndael::Crypt_Rijndael()
378 - * @var Boolean
379 - * @access private
380 - */
381 - var $paddable = false;
382 -
383 - /**
384 - * Encryption buffer for CTR, OFB and CFB modes
385 - *
386 - * @see Crypt_Rijndael::encrypt()
387 - * @var String
388 - * @access private
389 - */
390 - var $enbuffer = array('encrypted' => '', 'xor' => '');
391 -
392 - /**
393 - * Decryption buffer for CTR, OFB and CFB modes
394 - *
395 - * @see Crypt_Rijndael::decrypt()
396 - * @var String
397 - * @access private
398 - */
399 - var $debuffer = array('ciphertext' => '');
400 -
401 - /**
402 - * Default Constructor.
403 - *
404 - * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
405 - * CRYPT_RIJNDAEL_MODE_ECB or CRYPT_RIJNDAEL_MODE_CBC. If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
406 - *
407 - * @param optional Integer $mode
408 - * @return Crypt_Rijndael
409 - * @access public
410 - */
411 - function Crypt_Rijndael($mode = CRYPT_RIJNDAEL_MODE_CBC)
412 - {
413 - switch ($mode) {
414 - case CRYPT_RIJNDAEL_MODE_ECB:
415 - case CRYPT_RIJNDAEL_MODE_CBC:
416 - $this->paddable = true;
417 - $this->mode = $mode;
418 - break;
419 - case CRYPT_RIJNDAEL_MODE_CTR:
420 - case CRYPT_RIJNDAEL_MODE_CFB:
421 - case CRYPT_RIJNDAEL_MODE_OFB:
422 - $this->mode = $mode;
423 - break;
424 - default:
425 - $this->paddable = true;
426 - $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
427 - }
428 -
429 - $t3 = &$this->t3;
430 - $t2 = &$this->t2;
431 - $t1 = &$this->t1;
432 - $t0 = &$this->t0;
433 -
434 - $dt3 = &$this->dt3;
435 - $dt2 = &$this->dt2;
436 - $dt1 = &$this->dt1;
437 - $dt0 = &$this->dt0;
438 -
439 - // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
440 - // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
441 - // those are the names we'll use.
442 - $t3 = array(
443 - 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
444 - 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
445 - 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
446 - 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
447 - 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
448 - 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
449 - 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
450 - 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
451 - 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
452 - 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
453 - 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
454 - 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
455 - 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
456 - 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
457 - 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
458 - 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
459 - 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
460 - 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
461 - 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
462 - 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
463 - 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
464 - 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
465 - 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
466 - 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
467 - 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
468 - 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
469 - 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
470 - 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
471 - 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
472 - 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
473 - 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
474 - 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
475 - );
476 -
477 - $dt3 = array(
478 - 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
479 - 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
480 - 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
481 - 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
482 - 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
483 - 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
484 - 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
485 - 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
486 - 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
487 - 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
488 - 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
489 - 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
490 - 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
491 - 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
492 - 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
493 - 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
494 - 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
495 - 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
496 - 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
497 - 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
498 - 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
499 - 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
500 - 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
501 - 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
502 - 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
503 - 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
504 - 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
505 - 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
506 - 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
507 - 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
508 - 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
509 - 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
510 - );
511 -
512 - for ($i = 0; $i < 256; $i++) {
513 - $t2[$i << 8] = (($t3[$i] << 8) & 0xFFFFFF00) | (($t3[$i] >> 24) & 0x000000FF);
514 - $t1[$i << 16] = (($t3[$i] << 16) & 0xFFFF0000) | (($t3[$i] >> 16) & 0x0000FFFF);
515 - $t0[$i << 24] = (($t3[$i] << 24) & 0xFF000000) | (($t3[$i] >> 8) & 0x00FFFFFF);
516 -
517 - $dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($dt3[$i] >> 24) & 0x000000FF);
518 - $dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($dt3[$i] >> 16) & 0x0000FFFF);
519 - $dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($dt3[$i] >> 8) & 0x00FFFFFF);
520 - }
521 - }
522 -
523 - /**
524 245 * Sets the key.
525 246 *
526 247 * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
527 248 * 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
@@ -529,107 +250,79 @@
529 250 * excess bits.
530 251 *
531 252 * If the key is not explicitly set, it'll be assumed to be all null bytes.
532 253 *
254 + * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
255 + *
256 + * @see Crypt_Base:setKey()
257 + * @see self::setKeyLength()
533 258 * @access public
534 - * @param String $key
259 + * @param string $key
535 260 */
536 261 function setKey($key)
537 262 {
538 - $this->key = $key;
539 - $this->changed = true;
263 + if (!$this->explicit_key_length) {
264 + $length = strlen($key);
265 + switch (true) {
266 + case $length <= 16:
267 + $this->key_size = 16;
268 + break;
269 + case $length <= 20:
270 + $this->key_size = 20;
271 + break;
272 + case $length <= 24:
273 + $this->key_size = 24;
274 + break;
275 + case $length <= 28:
276 + $this->key_size = 28;
277 + break;
278 + default:
279 + $this->key_size = 32;
280 + }
281 + }
282 + parent::setKey($key);
540 283 }
541 284
542 285 /**
543 - * Sets the initialization vector. (optional)
544 - *
545 - * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
546 - * to be all zero's.
547 - *
548 - * @access public
549 - * @param String $iv
550 - */
551 - function setIV($iv)
552 - {
553 - $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, $this->block_size), $this->block_size, chr(0));
554 - }
555 -
556 - /**
557 286 * Sets the key length
558 287 *
559 288 * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
560 - * 128. If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
289 + * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
561 290 *
562 - * @access public
563 - * @param Integer $length
564 - */
565 - function setKeyLength($length)
566 - {
567 - $length >>= 5;
568 - if ($length > 8) {
569 - $length = 8;
570 - } else if ($length < 4) {
571 - $length = 4;
572 - }
573 - $this->Nk = $length;
574 - $this->key_size = $length << 2;
575 -
576 - $this->explicit_key_length = true;
577 - $this->changed = true;
578 - }
579 -
580 - /**
581 - * Sets the password.
291 + * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
292 + * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
293 + * 192/256 bits as, for example, mcrypt will do.
582 294 *
583 - * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
584 - * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
585 - * $hash, $salt, $count
586 - * Set $dkLen by calling setKeyLength()
295 + * That said, if you want be compatible with other Rijndael and AES implementations,
296 + * you should not setKeyLength(160) or setKeyLength(224).
587 297 *
588 - * @param String $password
589 - * @param optional String $method
298 + * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
299 + * the mcrypt php extension, even if available.
300 + * This results then in slower encryption.
301 + *
590 302 * @access public
303 + * @param int $length
591 304 */
592 - function setPassword($password, $method = 'pbkdf2')
305 + function setKeyLength($length)
593 306 {
594 - $key = '';
595 -
596 - switch ($method) {
597 - default: // 'pbkdf2'
598 - list(, , $hash, $salt, $count) = func_get_args();
599 - if (!isset($hash)) {
600 - $hash = 'sha1';
601 - }
602 - // WPA and WPA use the SSID as the salt
603 - if (!isset($salt)) {
604 - $salt = 'phpseclib/salt';
605 - }
606 - // RFC2898#section-4.2 uses 1,000 iterations by default
607 - // WPA and WPA2 use 4,096.
608 - if (!isset($count)) {
609 - $count = 1000;
610 - }
611 -
612 - if (!class_exists('Crypt_Hash')) {
613 - require_once('Crypt/Hash.php');
614 - }
615 -
616 - $i = 1;
617 - while (strlen($key) < $this->key_size) { // $dkLen == $this->key_size
618 - //$dk.= $this->_pbkdf($password, $salt, $count, $i++);
619 - $hmac = new Crypt_Hash();
620 - $hmac->setHash($hash);
621 - $hmac->setKey($password);
622 - $f = $u = $hmac->hash($salt . pack('N', $i++));
623 - for ($j = 2; $j <= $count; $j++) {
624 - $u = $hmac->hash($u);
625 - $f^= $u;
626 - }
627 - $key.= $f;
628 - }
307 + switch (true) {
308 + case $length <= 128:
309 + $this->key_length = 16;
310 + break;
311 + case $length <= 160:
312 + $this->key_length = 20;
313 + break;
314 + case $length <= 192:
315 + $this->key_length = 24;
316 + break;
317 + case $length <= 224:
318 + $this->key_length = 28;
319 + break;
320 + default:
321 + $this->key_length = 32;
629 322 }
630 323
631 - $this->setKey(substr($key, 0, $this->key_size));
324 + parent::setKeyLength($length);
632 325 }
633 326
634 327 /**
635 328 * Sets the block length
@@ -634,12 +327,12 @@
634 327 /**
635 328 * Sets the block length
636 329 *
637 330 * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
638 - * 128. If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
331 + * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
639 332 *
640 333 * @access public
641 - * @param Integer $length
334 + * @param int $length
642 335 */
643 336 function setBlockLength($length)
644 337 {
645 338 $length >>= 5;
@@ -644,365 +337,116 @@
644 337 {
645 338 $length >>= 5;
646 339 if ($length > 8) {
647 340 $length = 8;
648 - } else if ($length < 4) {
341 + } elseif ($length < 4) {
649 342 $length = 4;
650 343 }
651 344 $this->Nb = $length;
652 345 $this->block_size = $length << 2;
653 346 $this->changed = true;
347 + $this->_setEngine();
654 348 }
655 349
656 350 /**
657 - * Generate CTR XOR encryption key
351 + * Test for engine validity
658 352 *
659 - * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
660 - * plaintext / ciphertext in CTR mode.
353 + * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
661 354 *
662 - * @see Crypt_Rijndael::decrypt()
663 - * @see Crypt_Rijndael::encrypt()
355 + * @see Crypt_Base::Crypt_Base()
356 + * @param int $engine
664 357 * @access public
665 - * @param Integer $length
666 - * @param String $iv
358 + * @return bool
667 359 */
668 - function _generate_xor($length, &$iv)
360 + function isValidEngine($engine)
669 361 {
670 - $xor = '';
671 - $block_size = $this->block_size;
672 - $num_blocks = floor(($length + ($block_size - 1)) / $block_size);
673 - for ($i = 0; $i < $num_blocks; $i++) {
674 - $xor.= $iv;
675 - for ($j = 4; $j <= $block_size; $j+=4) {
676 - $temp = substr($iv, -$j, 4);
677 - switch ($temp) {
678 - case "\xFF\xFF\xFF\xFF":
679 - $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
680 - break;
681 - case "\x7F\xFF\xFF\xFF":
682 - $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
683 - break 2;
684 - default:
685 - extract(unpack('Ncount', $temp));
686 - $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
687 - break 2;
362 + switch ($engine) {
363 + case CRYPT_ENGINE_OPENSSL:
364 + if ($this->block_size != 16) {
365 + return false;
688 366 }
689 - }
690 - }
691 -
692 - return $xor;
693 - }
694 -
695 - /**
696 - * Encrypts a message.
697 - *
698 - * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other Rjindael
699 - * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
700 - * necessary are discussed in the following
701 - * URL:
702 - *
703 - * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
704 - *
705 - * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
706 - * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
707 - * length.
708 - *
709 - * @see Crypt_Rijndael::decrypt()
710 - * @access public
711 - * @param String $plaintext
712 - */
713 - function encrypt($plaintext)
714 - {
715 - $this->_setup();
716 - if ($this->paddable) {
717 - $plaintext = $this->_pad($plaintext);
718 - }
719 -
720 - $block_size = $this->block_size;
721 - $buffer = &$this->enbuffer;
722 - $continuousBuffer = $this->continuousBuffer;
723 - $ciphertext = '';
724 - switch ($this->mode) {
725 - case CRYPT_RIJNDAEL_MODE_ECB:
726 - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
727 - $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
728 - }
367 + $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
368 + $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
729 369 break;
730 - case CRYPT_RIJNDAEL_MODE_CBC:
731 - $xor = $this->encryptIV;
732 - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
733 - $block = substr($plaintext, $i, $block_size);
734 - $block = $this->_encryptBlock($block ^ $xor);
735 - $xor = $block;
736 - $ciphertext.= $block;
370 + case CRYPT_ENGINE_MCRYPT:
371 + $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
372 + if ($this->key_length % 8) { // is it a 160/224-bit key?
373 + // mcrypt is not usable for them, only for 128/192/256-bit keys
374 + return false;
737 375 }
738 - if ($this->continuousBuffer) {
739 - $this->encryptIV = $xor;
740 - }
741 - break;
742 - case CRYPT_RIJNDAEL_MODE_CTR:
743 - $xor = $this->encryptIV;
744 - if (!empty($buffer['encrypted'])) {
745 - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
746 - $block = substr($plaintext, $i, $block_size);
747 - $buffer['encrypted'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));
748 - $key = $this->_string_shift($buffer['encrypted'], $block_size);
749 - $ciphertext.= $block ^ $key;
750 - }
751 - } else {
752 - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
753 - $block = substr($plaintext, $i, $block_size);
754 - $key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));
755 - $ciphertext.= $block ^ $key;
756 - }
757 - }
758 - if ($this->continuousBuffer) {
759 - $this->encryptIV = $xor;
760 - if ($start = strlen($plaintext) % $block_size) {
761 - $buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
762 - }
763 - }
764 - break;
765 - case CRYPT_RIJNDAEL_MODE_CFB:
766 - if (!empty($buffer['xor'])) {
767 - $ciphertext = $plaintext ^ $buffer['xor'];
768 - $iv = $buffer['encrypted'] . $ciphertext;
769 - $start = strlen($ciphertext);
770 - $buffer['encrypted'].= $ciphertext;
771 - $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
772 - } else {
773 - $ciphertext = '';
774 - $iv = $this->encryptIV;
775 - $start = 0;
776 - }
777 -
778 - for ($i = $start; $i < strlen($plaintext); $i+=$block_size) {
779 - $block = substr($plaintext, $i, $block_size);
780 - $xor = $this->_encryptBlock($iv);
781 - $iv = $block ^ $xor;
782 - if ($continuousBuffer && strlen($iv) != $block_size) {
783 - $buffer = array(
784 - 'encrypted' => $iv,
785 - 'xor' => substr($xor, strlen($iv))
786 - );
787 - }
788 - $ciphertext.= $iv;
789 - }
790 -
791 - if ($this->continuousBuffer) {
792 - $this->encryptIV = $iv;
793 - }
794 - break;
795 - case CRYPT_RIJNDAEL_MODE_OFB:
796 - $xor = $this->encryptIV;
797 - if (strlen($buffer)) {
798 - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
799 - $xor = $this->_encryptBlock($xor);
800 - $buffer.= $xor;
801 - $key = $this->_string_shift($buffer, $block_size);
802 - $ciphertext.= substr($plaintext, $i, $block_size) ^ $key;
803 - }
804 - } else {
805 - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
806 - $xor = $this->_encryptBlock($xor);
807 - $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
808 - }
809 - $key = $xor;
810 - }
811 - if ($this->continuousBuffer) {
812 - $this->encryptIV = $xor;
813 - if ($start = strlen($plaintext) % $block_size) {
814 - $buffer = substr($key, $start) . $buffer;
815 - }
816 - }
817 376 }
818 377
819 - return $ciphertext;
378 + return parent::isValidEngine($engine);
820 379 }
821 380
822 381 /**
823 - * Decrypts a message.
824 - *
825 - * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
826 - * it is.
827 - *
828 - * @see Crypt_Rijndael::encrypt()
829 - * @access public
830 - * @param String $ciphertext
831 - */
832 - function decrypt($ciphertext)
833 - {
834 - $this->_setup();
835 -
836 - if ($this->paddable) {
837 - // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
838 - // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
839 - $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
840 - }
841 -
842 - $block_size = $this->block_size;
843 - $buffer = &$this->debuffer;
844 - $continuousBuffer = $this->continuousBuffer;
845 - $plaintext = '';
846 - switch ($this->mode) {
847 - case CRYPT_RIJNDAEL_MODE_ECB:
848 - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
849 - $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
850 - }
851 - break;
852 - case CRYPT_RIJNDAEL_MODE_CBC:
853 - $xor = $this->decryptIV;
854 - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
855 - $block = substr($ciphertext, $i, $block_size);
856 - $plaintext.= $this->_decryptBlock($block) ^ $xor;
857 - $xor = $block;
858 - }
859 - if ($this->continuousBuffer) {
860 - $this->decryptIV = $xor;
861 - }
862 - break;
863 - case CRYPT_RIJNDAEL_MODE_CTR:
864 - $xor = $this->decryptIV;
865 - if (!empty($buffer['ciphertext'])) {
866 - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
867 - $block = substr($ciphertext, $i, $block_size);
868 - $buffer['ciphertext'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));
869 - $key = $this->_string_shift($buffer['ciphertext'], $block_size);
870 - $plaintext.= $block ^ $key;
871 - }
872 - } else {
873 - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
874 - $block = substr($ciphertext, $i, $block_size);
875 - $key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));
876 - $plaintext.= $block ^ $key;
877 - }
878 - }
879 - if ($this->continuousBuffer) {
880 - $this->decryptIV = $xor;
881 - if ($start = strlen($ciphertext) % $block_size) {
882 - $buffer['ciphertext'] = substr($key, $start) . $buffer['encrypted'];
883 - }
884 - }
885 - break;
886 - case CRYPT_RIJNDAEL_MODE_CFB:
887 - if (!empty($buffer['ciphertext'])) {
888 - $plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext']));
889 - $buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext));
890 - if (strlen($buffer['ciphertext']) == $block_size) {
891 - $xor = $this->_encryptBlock($buffer['ciphertext']);
892 - $buffer['ciphertext'] = '';
893 - }
894 - $start = strlen($plaintext);
895 - $block = $this->decryptIV;
896 - } else {
897 - $plaintext = '';
898 - $xor = $this->_encryptBlock($this->decryptIV);
899 - $start = 0;
900 - }
901 -
902 - for ($i = $start; $i < strlen($ciphertext); $i+=$block_size) {
903 - $block = substr($ciphertext, $i, $block_size);
904 - $plaintext.= $block ^ $xor;
905 - if ($continuousBuffer && strlen($block) != $block_size) {
906 - $buffer['ciphertext'].= $block;
907 - $block = $xor;
908 - } else if (strlen($block) == $block_size) {
909 - $xor = $this->_encryptBlock($block);
910 - }
911 - }
912 - if ($this->continuousBuffer) {
913 - $this->decryptIV = $block;
914 - }
915 - break;
916 - case CRYPT_RIJNDAEL_MODE_OFB:
917 - $xor = $this->decryptIV;
918 - if (strlen($buffer)) {
919 - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
920 - $xor = $this->_encryptBlock($xor);
921 - $buffer.= $xor;
922 - $key = $this->_string_shift($buffer, $block_size);
923 - $plaintext.= substr($ciphertext, $i, $block_size) ^ $key;
924 - }
925 - } else {
926 - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
927 - $xor = $this->_encryptBlock($xor);
928 - $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
929 - }
930 - $key = $xor;
931 - }
932 - if ($this->continuousBuffer) {
933 - $this->decryptIV = $xor;
934 - if ($start = strlen($ciphertext) % $block_size) {
935 - $buffer = substr($key, $start) . $buffer;
936 - }
937 - }
938 - }
939 -
940 - return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
941 - }
942 -
943 - /**
944 382 * Encrypts a block
945 383 *
946 384 * @access private
947 - * @param String $in
948 - * @return String
385 + * @param string $in
386 + * @return string
949 387 */
950 388 function _encryptBlock($in)
951 389 {
390 + static $tables;
391 + if (empty($tables)) {
392 + $tables = &$this->_getTables();
393 + }
394 + $t0 = $tables[0];
395 + $t1 = $tables[1];
396 + $t2 = $tables[2];
397 + $t3 = $tables[3];
398 + $sbox = $tables[4];
399 +
952 400 $state = array();
953 - $words = unpack('N*word', $in);
401 + $words = unpack('N*', $in);
954 402
403 + $c = $this->c;
955 404 $w = $this->w;
956 - $t0 = $this->t0;
957 - $t1 = $this->t1;
958 - $t2 = $this->t2;
959 - $t3 = $this->t3;
960 405 $Nb = $this->Nb;
961 406 $Nr = $this->Nr;
962 - $c = $this->c;
963 407
964 408 // addRoundKey
965 - $i = 0;
409 + $wc = $Nb - 1;
966 410 foreach ($words as $word) {
967 - $state[] = $word ^ $w[0][$i++];
411 + $state[] = $word ^ $w[++$wc];
968 412 }
969 413
970 - // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
971 - // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
414 + // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
415 + // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
972 416 // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
973 417 // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
974 - // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
418 + // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
975 419 // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
976 420
977 421 // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
978 422 $temp = array();
979 - for ($round = 1; $round < $Nr; $round++) {
423 + for ($round = 1; $round < $Nr; ++$round) {
980 424 $i = 0; // $c[0] == 0
981 425 $j = $c[1];
982 426 $k = $c[2];
983 427 $l = $c[3];
984 428
985 - while ($i < $this->Nb) {
986 - $temp[$i] = $t0[$state[$i] & 0xFF000000] ^
987 - $t1[$state[$j] & 0x00FF0000] ^
988 - $t2[$state[$k] & 0x0000FF00] ^
989 - $t3[$state[$l] & 0x000000FF] ^
990 - $w[$round][$i];
991 - $i++;
429 + while ($i < $Nb) {
430 + $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
431 + $t1[$state[$j] >> 16 & 0x000000FF] ^
432 + $t2[$state[$k] >> 8 & 0x000000FF] ^
433 + $t3[$state[$l] & 0x000000FF] ^
434 + $w[++$wc];
435 + ++$i;
992 436 $j = ($j + 1) % $Nb;
993 437 $k = ($k + 1) % $Nb;
994 438 $l = ($l + 1) % $Nb;
995 439 }
996 -
997 - for ($i = 0; $i < $Nb; $i++) {
998 - $state[$i] = $temp[$i];
999 - }
440 + $state = $temp;
1000 441 }
1001 442
1002 443 // subWord
1003 - for ($i = 0; $i < $Nb; $i++) {
1004 - $state[$i] = $this->_subWord($state[$i]);
444 + for ($i = 0; $i < $Nb; ++$i) {
445 + $state[$i] = $sbox[$state[$i] & 0x000000FF] |
446 + ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) |
447 + ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
448 + ($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
1005 449 }
1006 450
1007 451 // shiftRows + addRoundKey
1008 452 $i = 0; // $c[0] == 0
@@ -1008,24 +452,32 @@
1008 452 $i = 0; // $c[0] == 0
1009 453 $j = $c[1];
1010 454 $k = $c[2];
1011 455 $l = $c[3];
1012 - while ($i < $this->Nb) {
1013 - $temp[$i] = ($state[$i] & 0xFF000000) ^
1014 - ($state[$j] & 0x00FF0000) ^
1015 - ($state[$k] & 0x0000FF00) ^
456 + while ($i < $Nb) {
457 + $temp[$i] = ($state[$i] & 0xFF000000) ^
458 + ($state[$j] & 0x00FF0000) ^
459 + ($state[$k] & 0x0000FF00) ^
1016 460 ($state[$l] & 0x000000FF) ^
1017 - $w[$Nr][$i];
1018 - $i++;
461 + $w[$i];
462 + ++$i;
1019 463 $j = ($j + 1) % $Nb;
1020 464 $k = ($k + 1) % $Nb;
1021 465 $l = ($l + 1) % $Nb;
1022 466 }
1023 - $state = $temp;
1024 467
1025 - array_unshift($state, 'N*');
1026 -
1027 - return call_user_func_array('pack', $state);
468 + switch ($Nb) {
469 + case 8:
470 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
471 + case 7:
472 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
473 + case 6:
474 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
475 + case 5:
476 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
477 + default:
478 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
479 + }
1028 480 }
1029 481
1030 482 /**
1031 483 * Decrypts a block
@@ -1030,34 +482,39 @@
1030 482 /**
1031 483 * Decrypts a block
1032 484 *
1033 485 * @access private
1034 - * @param String $in
1035 - * @return String
486 + * @param string $in
487 + * @return string
1036 488 */
1037 489 function _decryptBlock($in)
1038 490 {
491 + static $invtables;
492 + if (empty($invtables)) {
493 + $invtables = &$this->_getInvTables();
494 + }
495 + $dt0 = $invtables[0];
496 + $dt1 = $invtables[1];
497 + $dt2 = $invtables[2];
498 + $dt3 = $invtables[3];
499 + $isbox = $invtables[4];
500 +
1039 501 $state = array();
1040 - $words = unpack('N*word', $in);
502 + $words = unpack('N*', $in);
1041 503
1042 - $num_states = count($state);
504 + $c = $this->c;
1043 505 $dw = $this->dw;
1044 - $dt0 = $this->dt0;
1045 - $dt1 = $this->dt1;
1046 - $dt2 = $this->dt2;
1047 - $dt3 = $this->dt3;
1048 506 $Nb = $this->Nb;
1049 507 $Nr = $this->Nr;
1050 - $c = $this->c;
1051 508
1052 509 // addRoundKey
1053 - $i = 0;
510 + $wc = $Nb - 1;
1054 511 foreach ($words as $word) {
1055 - $state[] = $word ^ $dw[$Nr][$i++];
512 + $state[] = $word ^ $dw[++$wc];
1056 513 }
1057 514
1058 515 $temp = array();
1059 - for ($round = $Nr - 1; $round > 0; $round--) {
516 + for ($round = $Nr - 1; $round > 0; --$round) {
1060 517 $i = 0; // $c[0] == 0
1061 518 $j = $Nb - $c[1];
1062 519 $k = $Nb - $c[2];
1063 520 $l = $Nb - $c[3];
@@ -1062,22 +519,19 @@
1062 519 $k = $Nb - $c[2];
1063 520 $l = $Nb - $c[3];
1064 521
1065 522 while ($i < $Nb) {
1066 - $temp[$i] = $dt0[$state[$i] & 0xFF000000] ^
1067 - $dt1[$state[$j] & 0x00FF0000] ^
1068 - $dt2[$state[$k] & 0x0000FF00] ^
1069 - $dt3[$state[$l] & 0x000000FF] ^
1070 - $dw[$round][$i];
1071 - $i++;
523 + $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
524 + $dt1[$state[$j] >> 16 & 0x000000FF] ^
525 + $dt2[$state[$k] >> 8 & 0x000000FF] ^
526 + $dt3[$state[$l] & 0x000000FF] ^
527 + $dw[++$wc];
528 + ++$i;
1072 529 $j = ($j + 1) % $Nb;
1073 530 $k = ($k + 1) % $Nb;
1074 531 $l = ($l + 1) % $Nb;
1075 532 }
1076 -
1077 - for ($i = 0; $i < $Nb; $i++) {
1078 - $state[$i] = $temp[$i];
1079 - }
533 + $state = $temp;
1080 534 }
1081 535
1082 536 // invShiftRows + invSubWord + addRoundKey
1083 537 $i = 0; // $c[0] == 0
@@ -1085,35 +539,44 @@
1085 539 $k = $Nb - $c[2];
1086 540 $l = $Nb - $c[3];
1087 541
1088 542 while ($i < $Nb) {
1089 - $temp[$i] = $dw[0][$i] ^
1090 - $this->_invSubWord(($state[$i] & 0xFF000000) |
1091 - ($state[$j] & 0x00FF0000) |
1092 - ($state[$k] & 0x0000FF00) |
1093 - ($state[$l] & 0x000000FF));
1094 - $i++;
543 + $word = ($state[$i] & 0xFF000000) |
544 + ($state[$j] & 0x00FF0000) |
545 + ($state[$k] & 0x0000FF00) |
546 + ($state[$l] & 0x000000FF);
547 +
548 + $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] |
549 + ($isbox[$word >> 8 & 0x000000FF] << 8) |
550 + ($isbox[$word >> 16 & 0x000000FF] << 16) |
551 + ($isbox[$word >> 24 & 0x000000FF] << 24));
552 + ++$i;
1095 553 $j = ($j + 1) % $Nb;
1096 554 $k = ($k + 1) % $Nb;
1097 555 $l = ($l + 1) % $Nb;
1098 556 }
1099 557
1100 - $state = $temp;
1101 -
1102 - array_unshift($state, 'N*');
1103 -
1104 - return call_user_func_array('pack', $state);
558 + switch ($Nb) {
559 + case 8:
560 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
561 + case 7:
562 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
563 + case 6:
564 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
565 + case 5:
566 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
567 + default:
568 + return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
569 + }
1105 570 }
1106 571
1107 572 /**
1108 - * Setup Rijndael
573 + * Setup the key (expansion)
1109 574 *
1110 - * Validates all the variables and calculates $Nr - the number of rounds that need to be performed - and $w - the key
1111 - * key schedule.
1112 - *
575 + * @see Crypt_Base::_setupKey()
1113 576 * @access private
1114 577 */
1115 - function _setup()
578 + function _setupKey()
1116 579 {
1117 580 // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
1118 581 // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
1119 582 static $rcon = array(0,
@@ -1124,27 +587,15 @@
1124 587 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
1125 588 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
1126 589 );
1127 590
1128 - if (!$this->changed) {
591 + if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
592 + // already expanded
1129 593 return;
1130 594 }
595 + $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
1131 596
1132 - if (!$this->explicit_key_length) {
1133 - // we do >> 2, here, and not >> 5, as we do above, since strlen($this->key) tells us the number of bytes - not bits
1134 - $length = strlen($this->key) >> 2;
1135 - if ($length > 8) {
1136 - $length = 8;
1137 - } else if ($length < 4) {
1138 - $length = 4;
1139 - }
1140 - $this->Nk = $length;
1141 - $this->key_size = $length << 2;
1142 - }
1143 -
1144 - $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
1145 - $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, chr(0));
1146 -
597 + $this->Nk = $this->key_length >> 2;
1147 598 // see Rijndael-ammended.pdf#page=44
1148 599 $this->Nr = max($this->Nk, $this->Nb) + 6;
1149 600
1150 601 // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
@@ -1163,12 +614,10 @@
1163 614 case 8:
1164 615 $this->c = array(0, 1, 3, 4);
1165 616 }
1166 617
1167 - $key = $this->key;
618 + $w = array_values(unpack('N*words', $this->key));
1168 619
1169 - $w = array_values(unpack('N*words', $key));
1170 -
1171 620 $length = $this->Nb * ($this->Nr + 1);
1172 621 for ($i = $this->Nk; $i < $length; $i++) {
1173 622 $temp = $w[$i - 1];
1174 623 if ($i % $this->Nk == 0) {
@@ -1177,9 +626,9 @@
1177 626 // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
1178 627 // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
1179 628 $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
1180 629 $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
1181 - } else if ($this->Nk > 6 && $i % $this->Nk == 4) {
630 + } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
1182 631 $temp = $this->_subWord($temp);
1183 632 }
1184 633 $w[$i] = $w[$i - $this->Nk] ^ $temp;
1185 634 }
@@ -1185,14 +634,15 @@
1185 634 }
1186 635
1187 636 // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
1188 637 // and generate the inverse key schedule. more specifically,
1189 - // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
638 + // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
1190 639 // "The key expansion for the Inverse Cipher is defined as follows:
1191 640 // 1. Apply the Key Expansion.
1192 641 // 2. Apply InvMixColumn to all Round Keys except the first and the last one."
1193 642 // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
1194 - $temp = array();
643 + list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
644 + $temp = $this->w = $this->dw = array();
1195 645 for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
1196 646 if ($col == $this->Nb) {
1197 647 if ($row == 0) {
1198 648 $this->dw[0] = $this->w[0];
@@ -1200,12 +650,12 @@
1200 650 // subWord + invMixColumn + invSubWord = invMixColumn
1201 651 $j = 0;
1202 652 while ($j < $this->Nb) {
1203 653 $dw = $this->_subWord($this->w[$row][$j]);
1204 - $temp[$j] = $this->dt0[$dw & 0xFF000000] ^
1205 - $this->dt1[$dw & 0x00FF0000] ^
1206 - $this->dt2[$dw & 0x0000FF00] ^
1207 - $this->dt3[$dw & 0x000000FF];
654 + $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
655 + $dt1[$dw >> 16 & 0x000000FF] ^
656 + $dt2[$dw >> 8 & 0x000000FF] ^
657 + $dt3[$dw & 0x000000FF];
1208 658 $j++;
1209 659 }
1210 660 $this->dw[$row] = $temp;
1211 661 }
@@ -1217,9 +667,20 @@
1217 667 }
1218 668
1219 669 $this->dw[$row] = $this->w[$row];
1220 670
1221 - $this->changed = false;
671 + // Converting to 1-dim key arrays (both ascending)
672 + $this->dw = array_reverse($this->dw);
673 + $w = array_pop($this->w);
674 + $dw = array_pop($this->dw);
675 + foreach ($this->w as $r => $wr) {
676 + foreach ($wr as $c => $wc) {
677 + $w[] = $wc;
678 + $dw[] = $this->dw[$r][$c];
679 + }
680 + }
681 + $this->w = $w;
682 + $this->dw = $dw;
1222 683 }
1223 684
1224 685 /**
1225 686 * Performs S-Box substitutions
@@ -1224,255 +685,366 @@
1224 685 /**
1225 686 * Performs S-Box substitutions
1226 687 *
1227 688 * @access private
689 + * @param int $word
1228 690 */
1229 691 function _subWord($word)
1230 692 {
1231 - static $sbox0, $sbox1, $sbox2, $sbox3;
1232 -
1233 - if (empty($sbox0)) {
1234 - $sbox0 = array(
1235 - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
1236 - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
1237 - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
1238 - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
1239 - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
1240 - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
1241 - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
1242 - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
1243 - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
1244 - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
1245 - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
1246 - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
1247 - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
1248 - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
1249 - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
1250 - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
1251 - );
1252 -
1253 - $sbox1 = array();
1254 - $sbox2 = array();
1255 - $sbox3 = array();
1256 -
1257 - for ($i = 0; $i < 256; $i++) {
1258 - $sbox1[$i << 8] = $sbox0[$i] << 8;
1259 - $sbox2[$i << 16] = $sbox0[$i] << 16;
1260 - $sbox3[$i << 24] = $sbox0[$i] << 24;
1261 - }
693 + static $sbox;
694 + if (empty($sbox)) {
695 + list(, , , , $sbox) = $this->_getTables();
1262 696 }
1263 697
1264 - return $sbox0[$word & 0x000000FF] |
1265 - $sbox1[$word & 0x0000FF00] |
1266 - $sbox2[$word & 0x00FF0000] |
1267 - $sbox3[$word & 0xFF000000];
698 + return $sbox[$word & 0x000000FF] |
699 + ($sbox[$word >> 8 & 0x000000FF] << 8) |
700 + ($sbox[$word >> 16 & 0x000000FF] << 16) |
701 + ($sbox[$word >> 24 & 0x000000FF] << 24);
1268 702 }
1269 703
1270 704 /**
1271 - * Performs inverse S-Box substitutions
705 + * Provides the mixColumns and sboxes tables
1272 706 *
707 + * @see Crypt_Rijndael:_encryptBlock()
708 + * @see Crypt_Rijndael:_setupInlineCrypt()
709 + * @see Crypt_Rijndael:_subWord()
1273 710 * @access private
711 + * @return array &$tables
1274 712 */
1275 - function _invSubWord($word)
713 + function &_getTables()
1276 714 {
1277 - static $sbox0, $sbox1, $sbox2, $sbox3;
715 + static $tables;
716 + if (empty($tables)) {
717 + // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
718 + // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
719 + // those are the names we'll use.
720 + $t3 = array_map('intval', array(
721 + // with array_map('intval', ...) we ensure we have only int's and not
722 + // some slower floats converted by php automatically on high values
723 + 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
724 + 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
725 + 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
726 + 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
727 + 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
728 + 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
729 + 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
730 + 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
731 + 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
732 + 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
733 + 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
734 + 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
735 + 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
736 + 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
737 + 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
738 + 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
739 + 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
740 + 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
741 + 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
742 + 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
743 + 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
744 + 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
745 + 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
746 + 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
747 + 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
748 + 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
749 + 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
750 + 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
751 + 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
752 + 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
753 + 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
754 + 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
755 + ));
1278 756
1279 - if (empty($sbox0)) {
1280 - $sbox0 = array(
1281 - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
1282 - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
1283 - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
1284 - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
1285 - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
1286 - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
1287 - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
1288 - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
1289 - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
1290 - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
1291 - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
1292 - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
1293 - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
1294 - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
1295 - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
1296 - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
757 + foreach ($t3 as $t3i) {
758 + $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF);
759 + $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
760 + $t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
761 + }
762 +
763 + $tables = array(
764 + // The Precomputed mixColumns tables t0 - t3
765 + $t0,
766 + $t1,
767 + $t2,
768 + $t3,
769 + // The SubByte S-Box
770 + array(
771 + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
772 + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
773 + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
774 + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
775 + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
776 + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
777 + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
778 + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
779 + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
780 + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
781 + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
782 + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
783 + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
784 + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
785 + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
786 + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
787 + )
1297 788 );
1298 -
1299 - $sbox1 = array();
1300 - $sbox2 = array();
1301 - $sbox3 = array();
1302 -
1303 - for ($i = 0; $i < 256; $i++) {
1304 - $sbox1[$i << 8] = $sbox0[$i] << 8;
1305 - $sbox2[$i << 16] = $sbox0[$i] << 16;
1306 - $sbox3[$i << 24] = $sbox0[$i] << 24;
1307 - }
1308 789 }
1309 -
1310 - return $sbox0[$word & 0x000000FF] |
1311 - $sbox1[$word & 0x0000FF00] |
1312 - $sbox2[$word & 0x00FF0000] |
1313 - $sbox3[$word & 0xFF000000];
790 + return $tables;
1314 791 }
1315 792
1316 793 /**
1317 - * Pad "packets".
794 + * Provides the inverse mixColumns and inverse sboxes tables
1318 795 *
1319 - * Rijndael works by encrypting between sixteen and thirty-two bytes at a time, provided that number is also a multiple
1320 - * of four. If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
1321 - * pad the input so that it is of the proper length.
1322 - *
1323 - * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
1324 - * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
1325 - * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
1326 - * transmitted separately)
1327 - *
1328 - * @see Crypt_Rijndael::disablePadding()
1329 - * @access public
796 + * @see Crypt_Rijndael:_decryptBlock()
797 + * @see Crypt_Rijndael:_setupInlineCrypt()
798 + * @see Crypt_Rijndael:_setupKey()
799 + * @access private
800 + * @return array &$tables
1330 801 */
1331 - function enablePadding()
802 + function &_getInvTables()
1332 803 {
1333 - $this->padding = true;
1334 - }
804 + static $tables;
805 + if (empty($tables)) {
806 + $dt3 = array_map('intval', array(
807 + 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
808 + 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
809 + 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
810 + 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
811 + 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
812 + 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
813 + 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
814 + 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
815 + 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
816 + 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
817 + 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
818 + 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
819 + 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
820 + 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
821 + 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
822 + 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
823 + 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
824 + 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
825 + 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
826 + 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
827 + 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
828 + 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
829 + 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
830 + 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
831 + 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
832 + 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
833 + 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
834 + 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
835 + 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
836 + 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
837 + 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
838 + 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
839 + ));
1335 840
1336 - /**
1337 - * Do not pad packets.
1338 - *
1339 - * @see Crypt_Rijndael::enablePadding()
1340 - * @access public
1341 - */
1342 - function disablePadding()
1343 - {
1344 - $this->padding = false;
841 + foreach ($dt3 as $dt3i) {
842 + $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
843 + $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
844 + $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
845 + };
846 +
847 + $tables = array(
848 + // The Precomputed inverse mixColumns tables dt0 - dt3
849 + $dt0,
850 + $dt1,
851 + $dt2,
852 + $dt3,
853 + // The inverse SubByte S-Box
854 + array(
855 + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
856 + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
857 + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
858 + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
859 + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
860 + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
861 + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
862 + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
863 + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
864 + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
865 + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
866 + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
867 + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
868 + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
869 + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
870 + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
871 + )
872 + );
873 + }
874 + return $tables;
1345 875 }
1346 876
1347 877 /**
1348 - * Pads a string
878 + * Setup the performance-optimized function for de/encrypt()
1349 879 *
1350 - * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
1351 - * $block_size - (strlen($text) % $block_size) bytes are added, each of which is equal to
1352 - * chr($block_size - (strlen($text) % $block_size)
1353 - *
1354 - * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
1355 - * and padding will, hence forth, be enabled.
1356 - *
1357 - * @see Crypt_Rijndael::_unpad()
880 + * @see Crypt_Base::_setupInlineCrypt()
1358 881 * @access private
1359 882 */
1360 - function _pad($text)
883 + function _setupInlineCrypt()
1361 884 {
1362 - $length = strlen($text);
885 + // Note: _setupInlineCrypt() will be called only if $this->changed === true
886 + // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
887 + // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
1363 888
1364 - if (!$this->padding) {
1365 - if ($length % $this->block_size == 0) {
1366 - return $text;
1367 - } else {
1368 - user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})", E_USER_NOTICE);
1369 - $this->padding = true;
889 + $lambda_functions =& Crypt_Rijndael::_getLambdaFunctions();
890 +
891 + // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
892 + // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
893 + // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
894 + $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
895 +
896 + // Generation of a uniqe hash for our generated code
897 + $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
898 + if ($gen_hi_opt_code) {
899 + $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
900 + }
901 +
902 + if (!isset($lambda_functions[$code_hash])) {
903 + switch (true) {
904 + case $gen_hi_opt_code:
905 + // The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
906 + $w = $this->w;
907 + $dw = $this->dw;
908 + $init_encrypt = '';
909 + $init_decrypt = '';
910 + break;
911 + default:
912 + for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
913 + $w[] = '$w[' . $i . ']';
914 + $dw[] = '$dw[' . $i . ']';
915 + }
916 + $init_encrypt = '$w = $self->w;';
917 + $init_decrypt = '$dw = $self->dw;';
1370 918 }
1371 - }
1372 919
1373 - $pad = $this->block_size - ($length % $this->block_size);
920 + $Nr = $this->Nr;
921 + $Nb = $this->Nb;
922 + $c = $this->c;
1374 923
1375 - return str_pad($text, $length + $pad, chr($pad));
1376 - }
924 + // Generating encrypt code:
925 + $init_encrypt.= '
926 + static $tables;
927 + if (empty($tables)) {
928 + $tables = &$self->_getTables();
929 + }
930 + $t0 = $tables[0];
931 + $t1 = $tables[1];
932 + $t2 = $tables[2];
933 + $t3 = $tables[3];
934 + $sbox = $tables[4];
935 + ';
1377 936
1378 - /**
1379 - * Unpads a string.
1380 - *
1381 - * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
1382 - * and false will be returned.
1383 - *
1384 - * @see Crypt_Rijndael::_pad()
1385 - * @access private
1386 - */
1387 - function _unpad($text)
1388 - {
1389 - if (!$this->padding) {
1390 - return $text;
1391 - }
937 + $s = 'e';
938 + $e = 's';
939 + $wc = $Nb - 1;
1392 940
1393 - $length = ord($text[strlen($text) - 1]);
941 + // Preround: addRoundKey
942 + $encrypt_block = '$in = unpack("N*", $in);'."\n";
943 + for ($i = 0; $i < $Nb; ++$i) {
944 + $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";
945 + }
1394 946
1395 - if (!$length || $length > $this->block_size) {
1396 - return false;
1397 - }
947 + // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
948 + for ($round = 1; $round < $Nr; ++$round) {
949 + list($s, $e) = array($e, $s);
950 + for ($i = 0; $i < $Nb; ++$i) {
951 + $encrypt_block.=
952 + '$'.$e.$i.' =
953 + $t0[($'.$s.$i .' >> 24) & 0xff] ^
954 + $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
955 + $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^
956 + $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^
957 + '.$w[++$wc].";\n";
958 + }
959 + }
1398 960
1399 - return substr($text, 0, -$length);
1400 - }
961 + // Finalround: subWord + shiftRows + addRoundKey
962 + for ($i = 0; $i < $Nb; ++$i) {
963 + $encrypt_block.=
964 + '$'.$e.$i.' =
965 + $sbox[ $'.$e.$i.' & 0xff] |
966 + ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
967 + ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
968 + ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
969 + }
970 + $encrypt_block .= '$in = pack("N*"'."\n";
971 + for ($i = 0; $i < $Nb; ++$i) {
972 + $encrypt_block.= ',
973 + ($'.$e.$i .' & '.((int)0xFF000000).') ^
974 + ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^
975 + ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^
976 + ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^
977 + '.$w[$i]."\n";
978 + }
979 + $encrypt_block .= ');';
1401 980
1402 - /**
1403 - * Treat consecutive "packets" as if they are a continuous buffer.
1404 - *
1405 - * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
1406 - * will yield different outputs:
1407 - *
1408 - * <code>
1409 - * echo $rijndael->encrypt(substr($plaintext, 0, 16));
1410 - * echo $rijndael->encrypt(substr($plaintext, 16, 16));
1411 - * </code>
1412 - * <code>
1413 - * echo $rijndael->encrypt($plaintext);
1414 - * </code>
1415 - *
1416 - * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
1417 - * another, as demonstrated with the following:
1418 - *
1419 - * <code>
1420 - * $rijndael->encrypt(substr($plaintext, 0, 16));
1421 - * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
1422 - * </code>
1423 - * <code>
1424 - * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
1425 - * </code>
1426 - *
1427 - * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
1428 - * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
1429 - * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
1430 - *
1431 - * Put another way, when the continuous buffer is enabled, the state of the Crypt_Rijndael() object changes after each
1432 - * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
1433 - * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
1434 - * however, they are also less intuitive and more likely to cause you problems.
1435 - *
1436 - * @see Crypt_Rijndael::disableContinuousBuffer()
1437 - * @access public
1438 - */
1439 - function enableContinuousBuffer()
1440 - {
1441 - $this->continuousBuffer = true;
1442 - }
981 + // Generating decrypt code:
982 + $init_decrypt.= '
983 + static $invtables;
984 + if (empty($invtables)) {
985 + $invtables = &$self->_getInvTables();
986 + }
987 + $dt0 = $invtables[0];
988 + $dt1 = $invtables[1];
989 + $dt2 = $invtables[2];
990 + $dt3 = $invtables[3];
991 + $isbox = $invtables[4];
992 + ';
1443 993
1444 - /**
1445 - * Treat consecutive packets as if they are a discontinuous buffer.
1446 - *
1447 - * The default behavior.
1448 - *
1449 - * @see Crypt_Rijndael::enableContinuousBuffer()
1450 - * @access public
1451 - */
1452 - function disableContinuousBuffer()
1453 - {
1454 - $this->continuousBuffer = false;
1455 - $this->encryptIV = $this->iv;
1456 - $this->decryptIV = $this->iv;
1457 - }
994 + $s = 'e';
995 + $e = 's';
996 + $wc = $Nb - 1;
1458 997
1459 - /**
1460 - * String Shift
1461 - *
1462 - * Inspired by array_shift
1463 - *
1464 - * @param String $string
1465 - * @param optional Integer $index
1466 - * @return String
1467 - * @access private
1468 - */
1469 - function _string_shift(&$string, $index = 1)
1470 - {
1471 - $substr = substr($string, 0, $index);
1472 - $string = substr($string, $index);
1473 - return $substr;
998 + // Preround: addRoundKey
999 + $decrypt_block = '$in = unpack("N*", $in);'."\n";
1000 + for ($i = 0; $i < $Nb; ++$i) {
1001 + $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";
1002 + }
1003 +
1004 + // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
1005 + for ($round = 1; $round < $Nr; ++$round) {
1006 + list($s, $e) = array($e, $s);
1007 + for ($i = 0; $i < $Nb; ++$i) {
1008 + $decrypt_block.=
1009 + '$'.$e.$i.' =
1010 + $dt0[($'.$s.$i .' >> 24) & 0xff] ^
1011 + $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
1012 + $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^
1013 + $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^
1014 + '.$dw[++$wc].";\n";
1015 + }
1016 + }
1017 +
1018 + // Finalround: subWord + shiftRows + addRoundKey
1019 + for ($i = 0; $i < $Nb; ++$i) {
1020 + $decrypt_block.=
1021 + '$'.$e.$i.' =
1022 + $isbox[ $'.$e.$i.' & 0xff] |
1023 + ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
1024 + ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
1025 + ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
1026 + }
1027 + $decrypt_block .= '$in = pack("N*"'."\n";
1028 + for ($i = 0; $i < $Nb; ++$i) {
1029 + $decrypt_block.= ',
1030 + ($'.$e.$i. ' & '.((int)0xFF000000).') ^
1031 + ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^
1032 + ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^
1033 + ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^
1034 + '.$dw[$i]."\n";
1035 + }
1036 + $decrypt_block .= ');';
1037 +
1038 + $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
1039 + array(
1040 + 'init_crypt' => '',
1041 + 'init_encrypt' => $init_encrypt,
1042 + 'init_decrypt' => $init_decrypt,
1043 + 'encrypt_block' => $encrypt_block,
1044 + 'decrypt_block' => $decrypt_block
1045 + )
1046 + );
1047 + }
1048 + $this->inline_crypt = $lambda_functions[$code_hash];
1474 1049 }
1475 1050 }
1476 -
1477 -// vim: ts=4:sw=4:et:
1478 -// vim6: fdl=1: