PluginProbe
ManageWP Worker / 3.9.28
ManageWP Worker v3.9.28
4.9.38 4.9.37 4.9.36 4.9.35 4.9.34 3.8.7 3.8.8 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.18 3.9.19 3.9.2 3.9.20 3.9.21 3.9.22 3.9.23 3.9.24 All 73 releases
worker / lib / PHPSecLib / Crypt / AES.php

AES.php in ManageWP Worker 3.9.28, at lib/PHPSecLib/Crypt/AES.php

541 lines 18.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4 /**
5 * Pure-PHP implementation of AES.
6 *
7 * Uses mcrypt, if available, and an internal implementation, otherwise.
8 *
9 * PHP versions 4 and 5
10 *
11 * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12 * {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
13 * it'll be null-padded to 160-bits and 160 bits will be the key length until {@link Crypt_Rijndael::setKey() setKey()}
14 * is called, again, at which point, it'll be recalculated.
15 *
16 * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
17 * make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
18 * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
19 *
20 * Here's a short example of how to use this library:
21 * <code>
22 * <?php
23 * include('Crypt/AES.php');
24 *
25 * $aes = new Crypt_AES();
26 *
27 * $aes->setKey('abcdefghijklmnop');
28 *
29 * $size = 10 * 1024;
30 * $plaintext = '';
31 * for ($i = 0; $i < $size; $i++) {
32 * $plaintext.= 'a';
33 * }
34 *
35 * echo $aes->decrypt($aes->encrypt($plaintext));
36 * ?>
37 * </code>
38 *
39 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
40 * of this software and associated documentation files (the "Software"), to deal
41 * in the Software without restriction, including without limitation the rights
42 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43 * copies of the Software, and to permit persons to whom the Software is
44 * furnished to do so, subject to the following conditions:
45 *
46 * The above copyright notice and this permission notice shall be included in
47 * all copies or substantial portions of the Software.
48 *
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55 * THE SOFTWARE.
56 *
57 * @category Crypt
58 * @package Crypt_AES
59 * @author Jim Wigginton <terrafrost@php.net>
60 * @copyright MMVIII Jim Wigginton
61 * @license http://www.opensource.org/licenses/mit-license.html MIT License
62 * @link http://phpseclib.sourceforge.net
63 */
64
65 /**
66 * Include Crypt_Rijndael
67 */
68 if (!class_exists('Crypt_Rijndael')) {
69 require_once 'Rijndael.php';
70 }
71
72 /**#@+
73 * @access public
74 * @see Crypt_AES::encrypt()
75 * @see Crypt_AES::decrypt()
76 */
77 /**
78 * Encrypt / decrypt using the Counter mode.
79 *
80 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
81 *
82 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
83 */
84 define('CRYPT_AES_MODE_CTR', -1);
85 /**
86 * Encrypt / decrypt using the Electronic Code Book mode.
87 *
88 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
89 */
90 define('CRYPT_AES_MODE_ECB', 1);
91 /**
92 * Encrypt / decrypt using the Code Book Chaining mode.
93 *
94 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
95 */
96 define('CRYPT_AES_MODE_CBC', 2);
97 /**
98 * Encrypt / decrypt using the Cipher Feedback mode.
99 *
100 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
101 */
102 define('CRYPT_AES_MODE_CFB', 3);
103 /**
104 * Encrypt / decrypt using the Cipher Feedback mode.
105 *
106 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
107 */
108 define('CRYPT_AES_MODE_OFB', 4);
109 /**#@-*/
110
111 /**#@+
112 * @access private
113 * @see Crypt_AES::Crypt_AES()
114 */
115 /**
116 * Toggles the internal implementation
117 */
118 define('CRYPT_AES_MODE_INTERNAL', 1);
119 /**
120 * Toggles the mcrypt implementation
121 */
122 define('CRYPT_AES_MODE_MCRYPT', 2);
123 /**#@-*/
124
125 /**
126 * Pure-PHP implementation of AES.
127 *
128 * @author Jim Wigginton <terrafrost@php.net>
129 * @version 0.1.0
130 * @access public
131 * @package Crypt_AES
132 */
133 class Crypt_AES extends Crypt_Rijndael {
134 /**
135 * mcrypt resource for encryption
136 *
137 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
138 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
139 *
140 * @see Crypt_AES::encrypt()
141 * @var String
142 * @access private
143 */
144 var $enmcrypt;
145
146 /**
147 * mcrypt resource for decryption
148 *
149 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
150 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
151 *
152 * @see Crypt_AES::decrypt()
153 * @var String
154 * @access private
155 */
156 var $demcrypt;
157
158 /**
159 * mcrypt resource for CFB mode
160 *
161 * @see Crypt_AES::encrypt()
162 * @see Crypt_AES::decrypt()
163 * @var String
164 * @access private
165 */
166 var $ecb;
167
168 /**
169 * Default Constructor.
170 *
171 * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
172 * CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
173 *
174 * @param optional Integer $mode
175 * @return Crypt_AES
176 * @access public
177 */
178 function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
179 {
180 if ( !defined('CRYPT_AES_MODE') ) {
181 switch (true) {
182 case extension_loaded('mcrypt') && in_array('rijndael-128', mcrypt_list_algorithms()):
183 define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
184 break;
185 default:
186 define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
187 }
188 }
189
190 switch ( CRYPT_AES_MODE ) {
191 case CRYPT_AES_MODE_MCRYPT:
192 switch ($mode) {
193 case CRYPT_AES_MODE_ECB:
194 $this->paddable = true;
195 $this->mode = MCRYPT_MODE_ECB;
196 break;
197 case CRYPT_AES_MODE_CTR:
198 // ctr doesn't have a constant associated with it even though it appears to be fairly widely
199 // supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to
200 // include a compatibility layer. the layer has been implemented but, for now, is commented out.
201 $this->mode = 'ctr';
202 //$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
203 break;
204 case CRYPT_AES_MODE_CFB:
205 $this->mode = 'ncfb';
206 break;
207 case CRYPT_AES_MODE_OFB:
208 $this->mode = MCRYPT_MODE_NOFB;
209 break;
210 case CRYPT_AES_MODE_CBC:
211 default:
212 $this->paddable = true;
213 $this->mode = MCRYPT_MODE_CBC;
214 }
215
216 break;
217 default:
218 switch ($mode) {
219 case CRYPT_AES_MODE_ECB:
220 $this->paddable = true;
221 $this->mode = CRYPT_RIJNDAEL_MODE_ECB;
222 break;
223 case CRYPT_AES_MODE_CTR:
224 $this->mode = CRYPT_RIJNDAEL_MODE_CTR;
225 break;
226 case CRYPT_AES_MODE_CFB:
227 $this->mode = CRYPT_RIJNDAEL_MODE_CFB;
228 break;
229 case CRYPT_AES_MODE_OFB:
230 $this->mode = CRYPT_RIJNDAEL_MODE_OFB;
231 break;
232 case CRYPT_AES_MODE_CBC:
233 default:
234 $this->paddable = true;
235 $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
236 }
237 }
238
239 if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
240 parent::Crypt_Rijndael($this->mode);
241 }
242
243 }
244
245 /**
246 * Dummy function
247 *
248 * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
249 *
250 * @access public
251 * @param Integer $length
252 */
253 function setBlockLength($length)
254 {
255 return;
256 }
257
258 /**
259 * Sets the initialization vector. (optional)
260 *
261 * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
262 * to be all zero's.
263 *
264 * @access public
265 * @param String $iv
266 */
267 function setIV($iv)
268 {
269 parent::setIV($iv);
270 if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
271 $this->changed = true;
272 }
273 }
274
275 /**
276 * Encrypts a message.
277 *
278 * $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
279 * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
280 * URL:
281 *
282 * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
283 *
284 * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
285 * strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
286 * length.
287 *
288 * @see Crypt_AES::decrypt()
289 * @access public
290 * @param String $plaintext
291 */
292 function encrypt($plaintext)
293 {
294 if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
295 $this->_mcryptSetup();
296
297 // re: http://phpseclib.sourceforge.net/cfb-demo.phps
298 // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
299 // rewritten CFB implementation the above outputs the same thing twice.
300 if ($this->mode == 'ncfb' && $this->continuousBuffer) {
301 $iv = &$this->encryptIV;
302 $pos = &$this->enbuffer['pos'];
303 $len = strlen($plaintext);
304 $ciphertext = '';
305 $i = 0;
306 if ($pos) {
307 $orig_pos = $pos;
308 $max = 16 - $pos;
309 if ($len >= $max) {
310 $i = $max;
311 $len-= $max;
312 $pos = 0;
313 } else {
314 $i = $len;
315 $pos+= $len;
316 $len = 0;
317 }
318 $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
319 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
320 $this->enbuffer['enmcrypt_init'] = true;
321 }
322 if ($len >= 16) {
323 if ($this->enbuffer['enmcrypt_init'] === false || $len > 280) {
324 if ($this->enbuffer['enmcrypt_init'] === true) {
325 mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
326 $this->enbuffer['enmcrypt_init'] = false;
327 }
328 $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 16));
329 $iv = substr($ciphertext, -16);
330 $len%= 16;
331 } else {
332 while ($len >= 16) {
333 $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 16);
334 $ciphertext.= $iv;
335 $len-= 16;
336 $i+= 16;
337 }
338 }
339 }
340
341 if ($len) {
342 $iv = mcrypt_generic($this->ecb, $iv);
343 $block = $iv ^ substr($plaintext, -$len);
344 $iv = substr_replace($iv, $block, 0, $len);
345 $ciphertext.= $block;
346 $pos = $len;
347 }
348
349 return $ciphertext;
350 }
351
352 if ($this->paddable) {
353 $plaintext = $this->_pad($plaintext);
354 }
355
356 $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
357
358 if (!$this->continuousBuffer) {
359 mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
360 }
361
362 return $ciphertext;
363 }
364
365 return parent::encrypt($plaintext);
366 }
367
368 /**
369 * Decrypts a message.
370 *
371 * If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
372 *
373 * @see Crypt_AES::encrypt()
374 * @access public
375 * @param String $ciphertext
376 */
377 function decrypt($ciphertext)
378 {
379 if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
380 $this->_mcryptSetup();
381
382 if ($this->mode == 'ncfb' && $this->continuousBuffer) {
383 $iv = &$this->decryptIV;
384 $pos = &$this->debuffer['pos'];
385 $len = strlen($ciphertext);
386 $plaintext = '';
387 $i = 0;
388 if ($pos) {
389 $orig_pos = $pos;
390 $max = 16 - $pos;
391 if ($len >= $max) {
392 $i = $max;
393 $len-= $max;
394 $pos = 0;
395 } else {
396 $i = $len;
397 $pos+= $len;
398 $len = 0;
399 }
400 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
401 $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
402 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
403 }
404 if ($len >= 16) {
405 $cb = substr($ciphertext, $i, $len - $len % 16);
406 $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
407 $iv = substr($cb, -16);
408 $len%= 16;
409 }
410 if ($len) {
411 $iv = mcrypt_generic($this->ecb, $iv);
412 $plaintext.= $iv ^ substr($ciphertext, -$len);
413 $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
414 $pos = $len;
415 }
416
417 return $plaintext;
418 }
419
420 if ($this->paddable) {
421 // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
422 // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
423 $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
424 }
425
426 $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
427
428 if (!$this->continuousBuffer) {
429 mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
430 }
431
432 return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
433 }
434
435 return parent::decrypt($ciphertext);
436 }
437
438 /**
439 * Setup mcrypt
440 *
441 * Validates all the variables.
442 *
443 * @access private
444 */
445 function _mcryptSetup()
446 {
447 if (!$this->changed) {
448 return;
449 }
450
451 if (!$this->explicit_key_length) {
452 // this just copied from Crypt_Rijndael::_setup()
453 $length = strlen($this->key) >> 2;
454 if ($length > 8) {
455 $length = 8;
456 } else if ($length < 4) {
457 $length = 4;
458 }
459 $this->Nk = $length;
460 $this->key_size = $length << 2;
461 }
462
463 switch ($this->Nk) {
464 case 4: // 128
465 $this->key_size = 16;
466 break;
467 case 5: // 160
468 case 6: // 192
469 $this->key_size = 24;
470 break;
471 case 7: // 224
472 case 8: // 256
473 $this->key_size = 32;
474 }
475
476 $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
477 $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
478
479 if (!isset($this->enmcrypt)) {
480 $mode = $this->mode;
481 //$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
482
483 $this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
484 $this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
485
486 if ($mode == 'ncfb') {
487 $this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
488 }
489
490 } // else should mcrypt_generic_deinit be called?
491
492 mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
493 mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
494
495 if ($this->mode == 'ncfb') {
496 mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
497 }
498
499 $this->changed = false;
500 }
501
502 /**
503 * Treat consecutive "packets" as if they are a continuous buffer.
504 *
505 * The default behavior.
506 *
507 * @see Crypt_Rijndael::disableContinuousBuffer()
508 * @access public
509 */
510 function enableContinuousBuffer()
511 {
512 parent::enableContinuousBuffer();
513
514 if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
515 $this->enbuffer['enmcrypt_init'] = true;
516 $this->debuffer['demcrypt_init'] = true;
517 }
518 }
519
520 /**
521 * Treat consecutive packets as if they are a discontinuous buffer.
522 *
523 * The default behavior.
524 *
525 * @see Crypt_Rijndael::enableContinuousBuffer()
526 * @access public
527 */
528 function disableContinuousBuffer()
529 {
530 parent::disableContinuousBuffer();
531
532 if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
533 mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
534 mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
535 }
536 }
537 }
538
539 // vim: ts=4:sw=4:et:
540 // vim6: fdl=1:
541