PluginProbe
ManageWP Worker / 4.9.25
ManageWP Worker v4.9.25
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 / src / PHPSecLib / Crypt / Base.php

Base.php in ManageWP Worker 4.9.25, at src/PHPSecLib/Crypt/Base.php

2,039 lines 76.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Base Class for all Crypt_* cipher classes
5 *
6 * PHP versions 4 and 5
7 *
8 * Internally for phpseclib developers:
9 * If you plan to add a new cipher class, please note following rules:
10 *
11 * - The new Crypt_* cipher class should extend Crypt_Base
12 *
13 * - Following methods are then required to be overridden/overloaded:
14 *
15 * - _encryptBlock()
16 *
17 * - _decryptBlock()
18 *
19 * - _setupKey()
20 *
21 * - All other methods are optional to be overridden/overloaded
22 *
23 * - Look at the source code of the current ciphers how they extend Crypt_Base
24 * and take one of them as a start up for the new cipher class.
25 *
26 * - Please read all the other comments/notes/hints here also for each class var/method
27 *
28 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
29 * of this software and associated documentation files (the "Software"), to deal
30 * in the Software without restriction, including without limitation the rights
31 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32 * copies of the Software, and to permit persons to whom the Software is
33 * furnished to do so, subject to the following conditions:
34 *
35 * The above copyright notice and this permission notice shall be included in
36 * all copies or substantial portions of the Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44 * THE SOFTWARE.
45 *
46 * @category Crypt
47 * @package Crypt_Base
48 * @author Jim Wigginton <terrafrost@php.net>
49 * @author Hans-Juergen Petrich <petrich@tronic-media.com>
50 * @copyright MMVII Jim Wigginton
51 * @license http://www.opensource.org/licenses/mit-license.html MIT License
52 * @link http://phpseclib.sourceforge.net
53 */
54
55 /**#@+
56 * @access public
57 * @see Crypt_Base::encrypt()
58 * @see Crypt_Base::decrypt()
59 */
60 /**
61 * Encrypt / decrypt using the Counter mode.
62 *
63 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
64 *
65 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
66 */
67 define('CRYPT_MODE_CTR', -1);
68 /**
69 * Encrypt / decrypt using the Electronic Code Book mode.
70 *
71 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
72 */
73 define('CRYPT_MODE_ECB', 1);
74 /**
75 * Encrypt / decrypt using the Code Book Chaining mode.
76 *
77 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
78 */
79 define('CRYPT_MODE_CBC', 2);
80 /**
81 * Encrypt / decrypt using the Cipher Feedback mode.
82 *
83 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
84 */
85 define('CRYPT_MODE_CFB', 3);
86 /**
87 * Encrypt / decrypt using the Output Feedback mode.
88 *
89 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
90 */
91 define('CRYPT_MODE_OFB', 4);
92 /**
93 * Encrypt / decrypt using streaming mode.
94 *
95 */
96 define('CRYPT_MODE_STREAM', 5);
97 /**#@-*/
98
99 /**#@+
100 * @access private
101 * @see Crypt_Base::Crypt_Base()
102 */
103 /**
104 * Base value for the internal implementation $engine switch
105 */
106 define('CRYPT_MODE_INTERNAL', 1);
107 /**
108 * Base value for the mcrypt implementation $engine switch
109 */
110 define('CRYPT_MODE_MCRYPT', 2);
111 /**#@-*/
112
113 /**
114 * Base Class for all Crypt_* cipher classes
115 *
116 * @package Crypt_Base
117 * @author Jim Wigginton <terrafrost@php.net>
118 * @author Hans-Juergen Petrich <petrich@tronic-media.com>
119 * @access public
120 */
121 class Crypt_Base
122 {
123 /**
124 * The Encryption Mode
125 *
126 * @see Crypt_Base::Crypt_Base()
127 * @var Integer
128 * @access private
129 */
130 public $mode;
131
132 /**
133 * The Block Length of the block cipher
134 *
135 * @var Integer
136 * @access private
137 */
138 public $block_size = 16;
139
140 /**
141 * The Key
142 *
143 * @see Crypt_Base::setKey()
144 * @var String
145 * @access private
146 */
147 public $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
148
149 /**
150 * The Initialization Vector
151 *
152 * @see Crypt_Base::setIV()
153 * @var String
154 * @access private
155 */
156 public $iv;
157
158 /**
159 * A "sliding" Initialization Vector
160 *
161 * @see Crypt_Base::enableContinuousBuffer()
162 * @see Crypt_Base::_clearBuffers()
163 * @var String
164 * @access private
165 */
166 public $encryptIV;
167
168 /**
169 * A "sliding" Initialization Vector
170 *
171 * @see Crypt_Base::enableContinuousBuffer()
172 * @see Crypt_Base::_clearBuffers()
173 * @var String
174 * @access private
175 */
176 public $decryptIV;
177
178 /**
179 * Continuous Buffer status
180 *
181 * @see Crypt_Base::enableContinuousBuffer()
182 * @var Boolean
183 * @access private
184 */
185 public $continuousBuffer = false;
186
187 /**
188 * Encryption buffer for CTR, OFB and CFB modes
189 *
190 * @see Crypt_Base::encrypt()
191 * @see Crypt_Base::_clearBuffers()
192 * @var Array
193 * @access private
194 */
195 public $enbuffer;
196
197 /**
198 * Decryption buffer for CTR, OFB and CFB modes
199 *
200 * @see Crypt_Base::decrypt()
201 * @see Crypt_Base::_clearBuffers()
202 * @var Array
203 * @access private
204 */
205 public $debuffer;
206
207 /**
208 * mcrypt resource for encryption
209 *
210 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
211 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
212 *
213 * @see Crypt_Base::encrypt()
214 * @var Resource
215 * @access private
216 */
217 public $enmcrypt;
218
219 /**
220 * mcrypt resource for decryption
221 *
222 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
223 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
224 *
225 * @see Crypt_Base::decrypt()
226 * @var Resource
227 * @access private
228 */
229 public $demcrypt;
230
231 /**
232 * Does the enmcrypt resource need to be (re)initialized?
233 *
234 * @see Crypt_Twofish::setKey()
235 * @see Crypt_Twofish::setIV()
236 * @var Boolean
237 * @access private
238 */
239 public $enchanged = true;
240
241 /**
242 * Does the demcrypt resource need to be (re)initialized?
243 *
244 * @see Crypt_Twofish::setKey()
245 * @see Crypt_Twofish::setIV()
246 * @var Boolean
247 * @access private
248 */
249 public $dechanged = true;
250
251 /**
252 * mcrypt resource for CFB mode
253 *
254 * mcrypt's CFB mode, in (and only in) buffered context,
255 * is broken, so phpseclib implements the CFB mode by it self,
256 * even when the mcrypt php extension is available.
257 *
258 * In order to do the CFB-mode work (fast) phpseclib
259 * use a separate ECB-mode mcrypt resource.
260 *
261 * @link http://phpseclib.sourceforge.net/cfb-demo.phps
262 * @see Crypt_Base::encrypt()
263 * @see Crypt_Base::decrypt()
264 * @see Crypt_Base::_setupMcrypt()
265 * @var Resource
266 * @access private
267 */
268 public $ecb;
269
270 /**
271 * Optimizing value while CFB-encrypting
272 *
273 * Only relevant if $continuousBuffer enabled
274 * and $engine == CRYPT_MODE_MCRYPT
275 *
276 * It's faster to re-init $enmcrypt if
277 * $buffer bytes > $cfb_init_len than
278 * using the $ecb resource furthermore.
279 *
280 * This value depends of the chosen cipher
281 * and the time it would be needed for it's
282 * initialization [by mcrypt_generic_init()]
283 * which, typically, depends on the complexity
284 * on its internaly Key-expanding algorithm.
285 *
286 * @see Crypt_Base::encrypt()
287 * @var Integer
288 * @access private
289 */
290 public $cfb_init_len = 600;
291
292 /**
293 * Does internal cipher state need to be (re)initialized?
294 *
295 * @see setKey()
296 * @see setIV()
297 * @see disableContinuousBuffer()
298 * @var Boolean
299 * @access private
300 */
301 public $changed = true;
302
303 /**
304 * Padding status
305 *
306 * @see Crypt_Base::enablePadding()
307 * @var Boolean
308 * @access private
309 */
310 public $padding = true;
311
312 /**
313 * Is the mode one that is paddable?
314 *
315 * @see Crypt_Base::Crypt_Base()
316 * @var Boolean
317 * @access private
318 */
319 public $paddable = false;
320
321 /**
322 * Holds which crypt engine internaly should be use,
323 * which will be determined automatically on __construct()
324 *
325 * Currently available $engines are:
326 * - CRYPT_MODE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
327 * - CRYPT_MODE_INTERNAL (slower, pure php-engine, no php-extension required)
328 *
329 * In the pipeline... maybe. But currently not available:
330 * - CRYPT_MODE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
331 *
332 * If possible, CRYPT_MODE_MCRYPT will be used for each cipher.
333 * Otherwise CRYPT_MODE_INTERNAL
334 *
335 * @see Crypt_Base::encrypt()
336 * @see Crypt_Base::decrypt()
337 * @var Integer
338 * @access private
339 */
340 public $engine;
341
342 /**
343 * The mcrypt specific name of the cipher
344 *
345 * Only used if $engine == CRYPT_MODE_MCRYPT
346 *
347 * @link http://www.php.net/mcrypt_module_open
348 * @link http://www.php.net/mcrypt_list_algorithms
349 * @see Crypt_Base::_setupMcrypt()
350 * @var String
351 * @access private
352 */
353 public $cipher_name_mcrypt;
354
355 /**
356 * The default password key_size used by setPassword()
357 *
358 * @see Crypt_Base::setPassword()
359 * @var Integer
360 * @access private
361 */
362 public $password_key_size = 32;
363
364 /**
365 * The default salt used by setPassword()
366 *
367 * @see Crypt_Base::setPassword()
368 * @var String
369 * @access private
370 */
371 public $password_default_salt = 'phpseclib/salt';
372
373 /**
374 * The namespace used by the cipher for its constants.
375 *
376 * ie: AES.php is using CRYPT_AES_MODE_* for its constants
377 * so $const_namespace is AES
378 *
379 * DES.php is using CRYPT_DES_MODE_* for its constants
380 * so $const_namespace is DES... and so on
381 *
382 * All CRYPT_<$const_namespace>_MODE_* are aliases of
383 * the generic CRYPT_MODE_* constants, so both could be used
384 * for each cipher.
385 *
386 * Example:
387 * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
388 * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
389 *
390 * @see Crypt_Base::Crypt_Base()
391 * @var String
392 * @access private
393 */
394 public $const_namespace;
395
396 /**
397 * The name of the performance-optimized callback function
398 *
399 * Used by encrypt() / decrypt()
400 * only if $engine == CRYPT_MODE_INTERNAL
401 *
402 * @see Crypt_Base::encrypt()
403 * @see Crypt_Base::decrypt()
404 * @see Crypt_Base::_setupInlineCrypt()
405 * @see Crypt_Base::$use_inline_crypt
406 * @var Callback
407 * @access private
408 */
409 public $inline_crypt;
410
411 /**
412 * Holds whether performance-optimized $inline_crypt() can/should be used.
413 *
414 * @see Crypt_Base::encrypt()
415 * @see Crypt_Base::decrypt()
416 * @see Crypt_Base::inline_crypt
417 * @var mixed
418 * @access private
419 */
420 public $use_inline_crypt;
421
422 /**
423 * Default Constructor.
424 *
425 * Determines whether or not the mcrypt extension should be used.
426 *
427 * $mode could be:
428 *
429 * - CRYPT_MODE_ECB
430 *
431 * - CRYPT_MODE_CBC
432 *
433 * - CRYPT_MODE_CTR
434 *
435 * - CRYPT_MODE_CFB
436 *
437 * - CRYPT_MODE_OFB
438 *
439 * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
440 *
441 * If not explicitly set, CRYPT_MODE_CBC will be used.
442 *
443 * @param optional Integer $mode
444 *
445 * @access public
446 */
447 public function __construct($mode = CRYPT_MODE_CBC)
448 {
449 $const_crypt_mode = 'CRYPT_'.$this->const_namespace.'_MODE';
450
451 // Determining the availibility of mcrypt support for the cipher
452 if (!defined($const_crypt_mode)) {
453 switch (true) {
454 case extension_loaded('mcrypt') && in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms()):
455 define($const_crypt_mode, CRYPT_MODE_MCRYPT);
456 break;
457 default:
458 define($const_crypt_mode, CRYPT_MODE_INTERNAL);
459 }
460 }
461
462 // Determining which internal $engine should be used.
463 // The fastes possible first.
464 switch (true) {
465 case empty($this->cipher_name_mcrypt): // The cipher module has no mcrypt-engine support at all so we force CRYPT_MODE_INTERNAL
466 $this->engine = CRYPT_MODE_INTERNAL;
467 break;
468 case constant($const_crypt_mode) == CRYPT_MODE_MCRYPT:
469 $this->engine = CRYPT_MODE_MCRYPT;
470 break;
471 default:
472 $this->engine = CRYPT_MODE_INTERNAL;
473 }
474
475 // $mode dependent settings
476 switch ($mode) {
477 case CRYPT_MODE_ECB:
478 $this->paddable = true;
479 $this->mode = $mode;
480 break;
481 case CRYPT_MODE_CTR:
482 case CRYPT_MODE_CFB:
483 case CRYPT_MODE_OFB:
484 case CRYPT_MODE_STREAM:
485 $this->mode = $mode;
486 break;
487 case CRYPT_MODE_CBC:
488 default:
489 $this->paddable = true;
490 $this->mode = CRYPT_MODE_CBC;
491 }
492
493 // Determining whether inline crypting can be used by the cipher
494 if ($this->use_inline_crypt !== false && function_exists('create_function')) {
495 $this->use_inline_crypt = true;
496 }
497 }
498
499 /**
500 * Sets the initialization vector. (optional)
501 *
502 * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed
503 * to be all zero's.
504 *
505 * Note: Could, but not must, extend by the child Crypt_* class
506 *
507 * @access public
508 *
509 * @param String $iv
510 */
511 public function setIV($iv)
512 {
513 if ($this->mode == CRYPT_MODE_ECB) {
514 return;
515 }
516
517 $this->iv = $iv;
518 $this->changed = true;
519 }
520
521 /**
522 * Sets the key.
523 *
524 * The min/max length(s) of the key depends on the cipher which is used.
525 * If the key not fits the length(s) of the cipher it will paded with null bytes
526 * up to the closest valid key length. If the key is more than max length,
527 * we trim the excess bits.
528 *
529 * If the key is not explicitly set, it'll be assumed to be all null bytes.
530 *
531 * Note: Could, but not must, extend by the child Crypt_* class
532 *
533 * @access public
534 *
535 * @param String $key
536 */
537 public function setKey($key)
538 {
539 $this->key = $key;
540 $this->changed = true;
541 }
542
543 /**
544 * Sets the password.
545 *
546 * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
547 * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
548 * $hash, $salt, $count, $dkLen
549 *
550 * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
551 *
552 * Note: Could, but not must, extend by the child Crypt_* class
553 *
554 * @see Crypt/Hash.php
555 *
556 * @param String $password
557 * @param optional String $method
558 *
559 * @return Boolean
560 * @access public
561 */
562 public function setPassword($password, $method = 'pbkdf2')
563 {
564 $key = '';
565
566 switch ($method) {
567 default: // 'pbkdf2' or 'pbkdf1'
568 $func_args = func_get_args();
569
570 // Hash function
571 $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
572
573 // WPA and WPA2 use the SSID as the salt
574 $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
575
576 // RFC2898#section-4.2 uses 1,000 iterations by default
577 // WPA and WPA2 use 4,096.
578 $count = isset($func_args[4]) ? $func_args[4] : 1000;
579
580 // Keylength
581 if (isset($func_args[5])) {
582 $dkLen = $func_args[5];
583 } else {
584 $dkLen = $method == 'pbkdf1' ? 2 * $this->password_key_size : $this->password_key_size;
585 }
586
587 switch (true) {
588 case $method == 'pbkdf1':
589 if (!class_exists('Crypt_Hash')) {
590 require_once dirname(__FILE__).'/Hash.php';
591 }
592 $hashObj = new Crypt_Hash();
593 $hashObj->setHash($hash);
594 if ($dkLen > $hashObj->getLength()) {
595 user_error('Derived key too long');
596
597 return false;
598 }
599 $t = $password.$salt;
600 for ($i = 0; $i < $count; ++$i) {
601 $t = $hashObj->hash($t);
602 }
603 $key = substr($t, 0, $dkLen);
604
605 $this->setKey(substr($key, 0, $dkLen >> 1));
606 $this->setIV(substr($key, $dkLen >> 1));
607
608 return true;
609 // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
610 case !function_exists('hash_pbkdf2'):
611 case !function_exists('hash_algos'):
612 case !in_array($hash, hash_algos()):
613 if (!class_exists('Crypt_Hash')) {
614 require_once dirname(__FILE__).'/Hash.php';
615 }
616 $i = 1;
617 while (strlen($key) < $dkLen) {
618 $hmac = new Crypt_Hash();
619 $hmac->setHash($hash);
620 $hmac->setKey($password);
621 $f = $u = $hmac->hash($salt.pack('N', $i++));
622 for ($j = 2; $j <= $count; ++$j) {
623 $u = $hmac->hash($u);
624 $f ^= $u;
625 }
626 $key .= $f;
627 }
628 $key = substr($key, 0, $dkLen);
629 break;
630 default:
631 $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
632 }
633 }
634
635 $this->setKey($key);
636
637 return true;
638 }
639
640 /**
641 * Encrypts a message.
642 *
643 * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
644 * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
645 * necessary are discussed in the following
646 * URL:
647 *
648 * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
649 *
650 * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
651 * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
652 * length.
653 *
654 * Note: Could, but not must, extend by the child Crypt_* class
655 *
656 * @see Crypt_Base::decrypt()
657 * @access public
658 *
659 * @param String $plaintext
660 *
661 * @return String $cipertext
662 */
663 public function encrypt($plaintext)
664 {
665 if ($this->engine == CRYPT_MODE_MCRYPT) {
666 if ($this->changed) {
667 $this->_setupMcrypt();
668 $this->changed = false;
669 }
670 if ($this->enchanged) {
671 mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
672 $this->enchanged = false;
673 }
674
675 // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
676 // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
677 // rewritten CFB implementation the above outputs the same thing twice.
678 if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
679 $block_size = $this->block_size;
680 $iv = &$this->encryptIV;
681 $pos = &$this->enbuffer['pos'];
682 $len = strlen($plaintext);
683 $ciphertext = '';
684 $i = 0;
685 if ($pos) {
686 $orig_pos = $pos;
687 $max = $block_size - $pos;
688 if ($len >= $max) {
689 $i = $max;
690 $len -= $max;
691 $pos = 0;
692 } else {
693 $i = $len;
694 $pos += $len;
695 $len = 0;
696 }
697 $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
698 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
699 $this->enbuffer['enmcrypt_init'] = true;
700 }
701 if ($len >= $block_size) {
702 if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
703 if ($this->enbuffer['enmcrypt_init'] === true) {
704 mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
705 $this->enbuffer['enmcrypt_init'] = false;
706 }
707 $ciphertext .= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
708 $iv = substr($ciphertext, -$block_size);
709 $len %= $block_size;
710 } else {
711 while ($len >= $block_size) {
712 $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
713 $ciphertext .= $iv;
714 $len -= $block_size;
715 $i += $block_size;
716 }
717 }
718 }
719
720 if ($len) {
721 $iv = mcrypt_generic($this->ecb, $iv);
722 $block = $iv ^ substr($plaintext, -$len);
723 $iv = substr_replace($iv, $block, 0, $len);
724 $ciphertext .= $block;
725 $pos = $len;
726 }
727
728 return $ciphertext;
729 }
730
731 if ($this->paddable) {
732 $plaintext = $this->_pad($plaintext);
733 }
734
735 $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
736
737 if (!$this->continuousBuffer) {
738 mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
739 }
740
741 return $ciphertext;
742 }
743
744 if ($this->changed) {
745 $this->_setup();
746 $this->changed = false;
747 }
748 if ($this->use_inline_crypt) {
749 $inline = $this->inline_crypt;
750
751 return $inline('encrypt', $this, $plaintext);
752 }
753 if ($this->paddable) {
754 $plaintext = $this->_pad($plaintext);
755 }
756
757 $buffer = &$this->enbuffer;
758 $block_size = $this->block_size;
759 $ciphertext = '';
760 switch ($this->mode) {
761 case CRYPT_MODE_ECB:
762 for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
763 $ciphertext .= $this->_encryptBlock(substr($plaintext, $i, $block_size));
764 }
765 break;
766 case CRYPT_MODE_CBC:
767 $xor = $this->encryptIV;
768 for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
769 $block = substr($plaintext, $i, $block_size);
770 $block = $this->_encryptBlock($block ^ $xor);
771 $xor = $block;
772 $ciphertext .= $block;
773 }
774 if ($this->continuousBuffer) {
775 $this->encryptIV = $xor;
776 }
777 break;
778 case CRYPT_MODE_CTR:
779 $xor = $this->encryptIV;
780 if (strlen($buffer['encrypted'])) {
781 for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
782 $block = substr($plaintext, $i, $block_size);
783 if (strlen($block) > strlen($buffer['encrypted'])) {
784 $buffer['encrypted'] .= $this->_encryptBlock($this->_generateXor($xor, $block_size));
785 }
786 $key = $this->_stringShift($buffer['encrypted'], $block_size);
787 $ciphertext .= $block ^ $key;
788 }
789 } else {
790 for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
791 $block = substr($plaintext, $i, $block_size);
792 $key = $this->_encryptBlock($this->_generateXor($xor, $block_size));
793 $ciphertext .= $block ^ $key;
794 }
795 }
796 if ($this->continuousBuffer) {
797 $this->encryptIV = $xor;
798 if ($start = strlen($plaintext) % $block_size) {
799 $buffer['encrypted'] = substr($key, $start).$buffer['encrypted'];
800 }
801 }
802 break;
803 case CRYPT_MODE_CFB:
804 // cfb loosely routines inspired by openssl's:
805 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
806 if ($this->continuousBuffer) {
807 $iv = &$this->encryptIV;
808 $pos = &$buffer['pos'];
809 } else {
810 $iv = $this->encryptIV;
811 $pos = 0;
812 }
813 $len = strlen($plaintext);
814 $i = 0;
815 if ($pos) {
816 $orig_pos = $pos;
817 $max = $block_size - $pos;
818 if ($len >= $max) {
819 $i = $max;
820 $len -= $max;
821 $pos = 0;
822 } else {
823 $i = $len;
824 $pos += $len;
825 $len = 0;
826 }
827 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
828 $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
829 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
830 }
831 while ($len >= $block_size) {
832 $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
833 $ciphertext .= $iv;
834 $len -= $block_size;
835 $i += $block_size;
836 }
837 if ($len) {
838 $iv = $this->_encryptBlock($iv);
839 $block = $iv ^ substr($plaintext, $i);
840 $iv = substr_replace($iv, $block, 0, $len);
841 $ciphertext .= $block;
842 $pos = $len;
843 }
844 break;
845 case CRYPT_MODE_OFB:
846 $xor = $this->encryptIV;
847 if (strlen($buffer['xor'])) {
848 for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
849 $block = substr($plaintext, $i, $block_size);
850 if (strlen($block) > strlen($buffer['xor'])) {
851 $xor = $this->_encryptBlock($xor);
852 $buffer['xor'] .= $xor;
853 }
854 $key = $this->_stringShift($buffer['xor'], $block_size);
855 $ciphertext .= $block ^ $key;
856 }
857 } else {
858 for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
859 $xor = $this->_encryptBlock($xor);
860 $ciphertext .= substr($plaintext, $i, $block_size) ^ $xor;
861 }
862 $key = $xor;
863 }
864 if ($this->continuousBuffer) {
865 $this->encryptIV = $xor;
866 if ($start = strlen($plaintext) % $block_size) {
867 $buffer['xor'] = substr($key, $start).$buffer['xor'];
868 }
869 }
870 break;
871 case CRYPT_MODE_STREAM:
872 $ciphertext = $this->_encryptBlock($plaintext);
873 break;
874 }
875
876 return $ciphertext;
877 }
878
879 /**
880 * Decrypts a message.
881 *
882 * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
883 * it is.
884 *
885 * Note: Could, but not must, extend by the child Crypt_* class
886 *
887 * @see Crypt_Base::encrypt()
888 * @access public
889 *
890 * @param String $ciphertext
891 *
892 * @return String $plaintext
893 */
894 public function decrypt($ciphertext)
895 {
896 if ($this->engine == CRYPT_MODE_MCRYPT) {
897 $block_size = $this->block_size;
898 if ($this->changed) {
899 $this->_setupMcrypt();
900 $this->changed = false;
901 }
902 if ($this->dechanged) {
903 mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
904 $this->dechanged = false;
905 }
906
907 if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
908 $iv = &$this->decryptIV;
909 $pos = &$this->debuffer['pos'];
910 $len = strlen($ciphertext);
911 $plaintext = '';
912 $i = 0;
913 if ($pos) {
914 $orig_pos = $pos;
915 $max = $block_size - $pos;
916 if ($len >= $max) {
917 $i = $max;
918 $len -= $max;
919 $pos = 0;
920 } else {
921 $i = $len;
922 $pos += $len;
923 $len = 0;
924 }
925 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
926 $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
927 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
928 }
929 if ($len >= $block_size) {
930 $cb = substr($ciphertext, $i, $len - $len % $block_size);
931 $plaintext .= mcrypt_generic($this->ecb, $iv.$cb) ^ $cb;
932 $iv = substr($cb, -$block_size);
933 $len %= $block_size;
934 }
935 if ($len) {
936 $iv = mcrypt_generic($this->ecb, $iv);
937 $plaintext .= $iv ^ substr($ciphertext, -$len);
938 $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
939 $pos = $len;
940 }
941
942 return $plaintext;
943 }
944
945 if ($this->paddable) {
946 // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
947 // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
948 $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0));
949 }
950
951 $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
952
953 if (!$this->continuousBuffer) {
954 mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
955 }
956
957 return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
958 }
959
960 if ($this->changed) {
961 $this->_setup();
962 $this->changed = false;
963 }
964 if ($this->use_inline_crypt) {
965 $inline = $this->inline_crypt;
966
967 return $inline('decrypt', $this, $ciphertext);
968 }
969
970 $block_size = $this->block_size;
971 if ($this->paddable) {
972 // we pad with chr(0) since that's what mcrypt_generic does [...]
973 $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0));
974 }
975
976 $buffer = &$this->debuffer;
977 $plaintext = '';
978 switch ($this->mode) {
979 case CRYPT_MODE_ECB:
980 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
981 $plaintext .= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
982 }
983 break;
984 case CRYPT_MODE_CBC:
985 $xor = $this->decryptIV;
986 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
987 $block = substr($ciphertext, $i, $block_size);
988 $plaintext .= $this->_decryptBlock($block) ^ $xor;
989 $xor = $block;
990 }
991 if ($this->continuousBuffer) {
992 $this->decryptIV = $xor;
993 }
994 break;
995 case CRYPT_MODE_CTR:
996 $xor = $this->decryptIV;
997 if (strlen($buffer['ciphertext'])) {
998 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
999 $block = substr($ciphertext, $i, $block_size);
1000 if (strlen($block) > strlen($buffer['ciphertext'])) {
1001 $buffer['ciphertext'] .= $this->_encryptBlock($this->_generateXor($xor, $block_size));
1002 }
1003 $key = $this->_stringShift($buffer['ciphertext'], $block_size);
1004 $plaintext .= $block ^ $key;
1005 }
1006 } else {
1007 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1008 $block = substr($ciphertext, $i, $block_size);
1009 $key = $this->_encryptBlock($this->_generateXor($xor, $block_size));
1010 $plaintext .= $block ^ $key;
1011 }
1012 }
1013 if ($this->continuousBuffer) {
1014 $this->decryptIV = $xor;
1015 if ($start = strlen($ciphertext) % $block_size) {
1016 $buffer['ciphertext'] = substr($key, $start).$buffer['ciphertext'];
1017 }
1018 }
1019 break;
1020 case CRYPT_MODE_CFB:
1021 if ($this->continuousBuffer) {
1022 $iv = &$this->decryptIV;
1023 $pos = &$buffer['pos'];
1024 } else {
1025 $iv = $this->decryptIV;
1026 $pos = 0;
1027 }
1028 $len = strlen($ciphertext);
1029 $i = 0;
1030 if ($pos) {
1031 $orig_pos = $pos;
1032 $max = $block_size - $pos;
1033 if ($len >= $max) {
1034 $i = $max;
1035 $len -= $max;
1036 $pos = 0;
1037 } else {
1038 $i = $len;
1039 $pos += $len;
1040 $len = 0;
1041 }
1042 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1043 $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1044 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1045 }
1046 while ($len >= $block_size) {
1047 $iv = $this->_encryptBlock($iv);
1048 $cb = substr($ciphertext, $i, $block_size);
1049 $plaintext .= $iv ^ $cb;
1050 $iv = $cb;
1051 $len -= $block_size;
1052 $i += $block_size;
1053 }
1054 if ($len) {
1055 $iv = $this->_encryptBlock($iv);
1056 $plaintext .= $iv ^ substr($ciphertext, $i);
1057 $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
1058 $pos = $len;
1059 }
1060 break;
1061 case CRYPT_MODE_OFB:
1062 $xor = $this->decryptIV;
1063 if (strlen($buffer['xor'])) {
1064 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1065 $block = substr($ciphertext, $i, $block_size);
1066 if (strlen($block) > strlen($buffer['xor'])) {
1067 $xor = $this->_encryptBlock($xor);
1068 $buffer['xor'] .= $xor;
1069 }
1070 $key = $this->_stringShift($buffer['xor'], $block_size);
1071 $plaintext .= $block ^ $key;
1072 }
1073 } else {
1074 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1075 $xor = $this->_encryptBlock($xor);
1076 $plaintext .= substr($ciphertext, $i, $block_size) ^ $xor;
1077 }
1078 $key = $xor;
1079 }
1080 if ($this->continuousBuffer) {
1081 $this->decryptIV = $xor;
1082 if ($start = strlen($ciphertext) % $block_size) {
1083 $buffer['xor'] = substr($key, $start).$buffer['xor'];
1084 }
1085 }
1086 break;
1087 case CRYPT_MODE_STREAM:
1088 $plaintext = $this->_decryptBlock($ciphertext);
1089 break;
1090 }
1091
1092 return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1093 }
1094
1095 /**
1096 * Pad "packets".
1097 *
1098 * Block ciphers working by encrypting between their specified [$this->]block_size at a time
1099 * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
1100 * pad the input so that it is of the proper length.
1101 *
1102 * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
1103 * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
1104 * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
1105 * transmitted separately)
1106 *
1107 * @see Crypt_Base::disablePadding()
1108 * @access public
1109 */
1110 public function enablePadding()
1111 {
1112 $this->padding = true;
1113 }
1114
1115 /**
1116 * Do not pad packets.
1117 *
1118 * @see Crypt_Base::enablePadding()
1119 * @access public
1120 */
1121 public function disablePadding()
1122 {
1123 $this->padding = false;
1124 }
1125
1126 /**
1127 * Treat consecutive "packets" as if they are a continuous buffer.
1128 *
1129 * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
1130 * will yield different outputs:
1131 *
1132 * <code>
1133 * echo $rijndael->encrypt(substr($plaintext, 0, 16));
1134 * echo $rijndael->encrypt(substr($plaintext, 16, 16));
1135 * </code>
1136 * <code>
1137 * echo $rijndael->encrypt($plaintext);
1138 * </code>
1139 *
1140 * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
1141 * another, as demonstrated with the following:
1142 *
1143 * <code>
1144 * $rijndael->encrypt(substr($plaintext, 0, 16));
1145 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1146 * </code>
1147 * <code>
1148 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1149 * </code>
1150 *
1151 * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
1152 * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
1153 * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
1154 *
1155 * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
1156 * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
1157 * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
1158 * however, they are also less intuitive and more likely to cause you problems.
1159 *
1160 * Note: Could, but not must, extend by the child Crypt_* class
1161 *
1162 * @see Crypt_Base::disableContinuousBuffer()
1163 * @access public
1164 */
1165 public function enableContinuousBuffer()
1166 {
1167 if ($this->mode == CRYPT_MODE_ECB) {
1168 return;
1169 }
1170
1171 $this->continuousBuffer = true;
1172 }
1173
1174 /**
1175 * Treat consecutive packets as if they are a discontinuous buffer.
1176 *
1177 * The default behavior.
1178 *
1179 * Note: Could, but not must, extend by the child Crypt_* class
1180 *
1181 * @see Crypt_Base::enableContinuousBuffer()
1182 * @access public
1183 */
1184 public function disableContinuousBuffer()
1185 {
1186 if ($this->mode == CRYPT_MODE_ECB) {
1187 return;
1188 }
1189 if (!$this->continuousBuffer) {
1190 return;
1191 }
1192
1193 $this->continuousBuffer = false;
1194 $this->changed = true;
1195 }
1196
1197 /**
1198 * Encrypts a block
1199 *
1200 * Note: Must extend by the child Crypt_* class
1201 *
1202 * @access private
1203 *
1204 * @param String $in
1205 *
1206 * @return String
1207 */
1208 public function _encryptBlock($in)
1209 {
1210 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__).'() must extend by class '.get_class($this), E_USER_ERROR);
1211 }
1212
1213 /**
1214 * Decrypts a block
1215 *
1216 * Note: Must extend by the child Crypt_* class
1217 *
1218 * @access private
1219 *
1220 * @param String $in
1221 *
1222 * @return String
1223 */
1224 public function _decryptBlock($in)
1225 {
1226 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__).'() must extend by class '.get_class($this), E_USER_ERROR);
1227 }
1228
1229 /**
1230 * Setup the key (expansion)
1231 *
1232 * Only used if $engine == CRYPT_MODE_INTERNAL
1233 *
1234 * Note: Must extend by the child Crypt_* class
1235 *
1236 * @see Crypt_Base::_setup()
1237 * @access private
1238 */
1239 public function _setupKey()
1240 {
1241 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__).'() must extend by class '.get_class($this), E_USER_ERROR);
1242 }
1243
1244 /**
1245 * Setup the CRYPT_MODE_INTERNAL $engine
1246 *
1247 * (re)init, if necessary, the internal cipher $engine and flush all $buffers
1248 * Used (only) if $engine == CRYPT_MODE_INTERNAL
1249 *
1250 * _setup() will be called each time if $changed === true
1251 * typically this happens when using one or more of following public methods:
1252 *
1253 * - setKey()
1254 *
1255 * - setIV()
1256 *
1257 * - disableContinuousBuffer()
1258 *
1259 * - First run of encrypt() / decrypt() with no init-settings
1260 *
1261 * Internally: _setup() is called always before(!) en/decryption.
1262 *
1263 * Note: Could, but not must, extend by the child Crypt_* class
1264 *
1265 * @see setKey()
1266 * @see setIV()
1267 * @see disableContinuousBuffer()
1268 * @access private
1269 */
1270 public function _setup()
1271 {
1272 $this->_clearBuffers();
1273 $this->_setupKey();
1274
1275 if ($this->use_inline_crypt) {
1276 $this->_setupInlineCrypt();
1277 }
1278 }
1279
1280 /**
1281 * Setup the CRYPT_MODE_MCRYPT $engine
1282 *
1283 * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
1284 * Used (only) if $engine = CRYPT_MODE_MCRYPT
1285 *
1286 * _setupMcrypt() will be called each time if $changed === true
1287 * typically this happens when using one or more of following public methods:
1288 *
1289 * - setKey()
1290 *
1291 * - setIV()
1292 *
1293 * - disableContinuousBuffer()
1294 *
1295 * - First run of encrypt() / decrypt()
1296 *
1297 *
1298 * Note: Could, but not must, extend by the child Crypt_* class
1299 *
1300 * @see setKey()
1301 * @see setIV()
1302 * @see disableContinuousBuffer()
1303 * @access private
1304 */
1305 public function _setupMcrypt()
1306 {
1307 $this->_clearBuffers();
1308 $this->enchanged = $this->dechanged = true;
1309
1310 if (!isset($this->enmcrypt)) {
1311 static $mcrypt_modes = array(
1312 CRYPT_MODE_CTR => 'ctr',
1313 CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
1314 CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
1315 CRYPT_MODE_CFB => 'ncfb',
1316 CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
1317 CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
1318 );
1319
1320 $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1321 $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1322
1323 // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
1324 // to workaround mcrypt's broken ncfb implementation in buffered mode
1325 // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
1326 if ($this->mode == CRYPT_MODE_CFB) {
1327 $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
1328 }
1329 } // else should mcrypt_generic_deinit be called?
1330
1331 if ($this->mode == CRYPT_MODE_CFB) {
1332 mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
1333 }
1334 }
1335
1336 /**
1337 * Pads a string
1338 *
1339 * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
1340 * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
1341 * chr($this->block_size - (strlen($text) % $this->block_size)
1342 *
1343 * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
1344 * and padding will, hence forth, be enabled.
1345 *
1346 * @see Crypt_Base::_unpad()
1347 *
1348 * @param String $text
1349 *
1350 * @access private
1351 * @return String
1352 */
1353 public function _pad($text)
1354 {
1355 $length = strlen($text);
1356
1357 if (!$this->padding) {
1358 if ($length % $this->block_size == 0) {
1359 return $text;
1360 } else {
1361 user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
1362 $this->padding = true;
1363 }
1364 }
1365
1366 $pad = $this->block_size - ($length % $this->block_size);
1367
1368 return str_pad($text, $length + $pad, chr($pad));
1369 }
1370
1371 /**
1372 * Unpads a string.
1373 *
1374 * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
1375 * and false will be returned.
1376 *
1377 * @see Crypt_Base::_pad()
1378 *
1379 * @param String $text
1380 *
1381 * @access private
1382 * @return String
1383 */
1384 public function _unpad($text)
1385 {
1386 if (!$this->padding) {
1387 return $text;
1388 }
1389
1390 $length = ord($text[strlen($text) - 1]);
1391
1392 if (!$length || $length > $this->block_size) {
1393 return false;
1394 }
1395
1396 return substr($text, 0, -$length);
1397 }
1398
1399 /**
1400 * Clears internal buffers
1401 *
1402 * Clearing/resetting the internal buffers is done everytime
1403 * after disableContinuousBuffer() or on cipher $engine (re)init
1404 * ie after setKey() or setIV()
1405 *
1406 * Note: Could, but not must, extend by the child Crypt_* class
1407 *
1408 * @access public
1409 */
1410 public function _clearBuffers()
1411 {
1412 $this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
1413 $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
1414
1415 // mcrypt's handling of invalid's $iv:
1416 // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
1417 $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
1418 }
1419
1420 /**
1421 * String Shift
1422 *
1423 * Inspired by array_shift
1424 *
1425 * @param String $string
1426 * @param optional Integer $index
1427 *
1428 * @access private
1429 * @return String
1430 */
1431 public function _stringShift(&$string, $index = 1)
1432 {
1433 $substr = substr($string, 0, $index);
1434 $string = substr($string, $index);
1435
1436 return $substr;
1437 }
1438
1439 /**
1440 * Generate CTR XOR encryption key
1441 *
1442 * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
1443 * plaintext / ciphertext in CTR mode.
1444 *
1445 * @see Crypt_Base::decrypt()
1446 * @see Crypt_Base::encrypt()
1447 *
1448 * @param String $iv
1449 * @param Integer $length
1450 *
1451 * @access private
1452 * @return String $xor
1453 */
1454 public function _generateXor(&$iv, $length)
1455 {
1456 $xor = '';
1457 $block_size = $this->block_size;
1458 $num_blocks = floor(($length + ($block_size - 1)) / $block_size);
1459 for ($i = 0; $i < $num_blocks; $i++) {
1460 $xor .= $iv;
1461 for ($j = 4; $j <= $block_size; $j += 4) {
1462 $temp = substr($iv, -$j, 4);
1463 switch ($temp) {
1464 case "\xFF\xFF\xFF\xFF":
1465 $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
1466 break;
1467 case "\x7F\xFF\xFF\xFF":
1468 $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
1469 break 2;
1470 default:
1471 extract(unpack('Ncount', $temp));
1472 $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
1473 break 2;
1474 }
1475 }
1476 }
1477
1478 return $xor;
1479 }
1480
1481 /**
1482 * Setup the performance-optimized function for de/encrypt()
1483 *
1484 * Stores the created (or existing) callback function-name
1485 * in $this->inline_crypt
1486 *
1487 * Internally for phpseclib developers:
1488 *
1489 * _setupInlineCrypt() would be called only if:
1490 *
1491 * - $engine == CRYPT_MODE_INTERNAL and
1492 *
1493 * - $use_inline_crypt === true
1494 *
1495 * - each time on _setup(), after(!) _setupKey()
1496 *
1497 *
1498 * This ensures that _setupInlineCrypt() has always a
1499 * full ready2go initializated internal cipher $engine state
1500 * where, for example, the keys allready expanded,
1501 * keys/block_size calculated and such.
1502 *
1503 * It is, each time if called, the responsibility of _setupInlineCrypt():
1504 *
1505 * - to set $this->inline_crypt to a valid and fully working callback function
1506 * as a (faster) replacement for encrypt() / decrypt()
1507 *
1508 * - NOT to create unlimited callback functions (for memory reasons!)
1509 * no matter how often _setupInlineCrypt() would be called. At some
1510 * point of amount they must be generic re-useable.
1511 *
1512 * - the code of _setupInlineCrypt() it self,
1513 * and the generated callback code,
1514 * must be, in following order:
1515 * - 100% safe
1516 * - 100% compatible to encrypt()/decrypt()
1517 * - using only php5+ features/lang-constructs/php-extensions if
1518 * compatibility (down to php4) or fallback is provided
1519 * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
1520 * - >= 10% faster than encrypt()/decrypt() [which is, by the way,
1521 * the reason for the existence of _setupInlineCrypt() :-)]
1522 * - memory-nice
1523 * - short (as good as possible)
1524 *
1525 * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
1526 * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
1527 * - The following variable names are reserved:
1528 * - $_* (all variable names prefixed with an underscore)
1529 * - $self (object reference to it self. Do not use $this, but $self instead)
1530 * - $in (the content of $in has to en/decrypt by the generated code)
1531 * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
1532 *
1533 *
1534 * @see Crypt_Base::_setup()
1535 * @see Crypt_Base::_createInlineCryptFunction()
1536 * @see Crypt_Base::encrypt()
1537 * @see Crypt_Base::decrypt()
1538 * @access private
1539 */
1540 public function _setupInlineCrypt()
1541 {
1542 // If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
1543
1544 // If, for any reason, an extending Crypt_Base() Crypt_* class
1545 // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
1546 // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
1547 // in the constructor at object instance-time
1548 // or, if it's runtime-specific, at runtime
1549
1550 $this->use_inline_crypt = false;
1551 }
1552
1553 /**
1554 * Creates the performance-optimized function for en/decrypt()
1555 *
1556 * Internally for phpseclib developers:
1557 *
1558 * _createInlineCryptFunction():
1559 *
1560 * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
1561 * with the current [$this->]mode of operation code
1562 *
1563 * - create the $inline function, which called by encrypt() / decrypt()
1564 * as its replacement to speed up the en/decryption operations.
1565 *
1566 * - return the name of the created $inline callback function
1567 *
1568 * - used to speed up en/decryption
1569 *
1570 *
1571 *
1572 * The main reason why can speed up things [up to 50%] this way are:
1573 *
1574 * - using variables more effective then regular.
1575 * (ie no use of expensive arrays but integers $k_0, $k_1 ...
1576 * or even, for example, the pure $key[] values hardcoded)
1577 *
1578 * - avoiding 1000's of function calls of ie _encryptBlock()
1579 * but inlining the crypt operations.
1580 * in the mode of operation for() loop.
1581 *
1582 * - full loop unroll the (sometimes key-dependent) rounds
1583 * avoiding this way ++$i counters and runtime-if's etc...
1584 *
1585 * The basic code architectur of the generated $inline en/decrypt()
1586 * lambda function, in pseudo php, is:
1587 *
1588 * <code>
1589 * +----------------------------------------------------------------------------------------------+
1590 * | callback $inline = create_function: |
1591 * | lambda_function_0001_crypt_ECB($action, $text) |
1592 * | { |
1593 * | INSERT PHP CODE OF: |
1594 * | $cipher_code['init_crypt']; // general init code. |
1595 * | // ie: $sbox'es declarations used for |
1596 * | // encrypt and decrypt'ing. |
1597 * | |
1598 * | switch ($action) { |
1599 * | case 'encrypt': |
1600 * | INSERT PHP CODE OF: |
1601 * | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
1602 * | ie: specified $key or $box |
1603 * | declarations for encrypt'ing. |
1604 * | |
1605 * | foreach ($ciphertext) { |
1606 * | $in = $block_size of $ciphertext; |
1607 * | |
1608 * | INSERT PHP CODE OF: |
1609 * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
1610 * | // strlen($in) == $this->block_size |
1611 * | // here comes the cipher algorithm in action |
1612 * | // for encryption. |
1613 * | // $cipher_code['encrypt_block'] has to |
1614 * | // encrypt the content of the $in variable |
1615 * | |
1616 * | $plaintext .= $in; |
1617 * | } |
1618 * | return $plaintext; |
1619 * | |
1620 * | case 'decrypt': |
1621 * | INSERT PHP CODE OF: |
1622 * | $cipher_code['init_decrypt']; // decrypt sepcific init code |
1623 * | ie: specified $key or $box |
1624 * | declarations for decrypt'ing. |
1625 * | foreach ($plaintext) { |
1626 * | $in = $block_size of $plaintext; |
1627 * | |
1628 * | INSERT PHP CODE OF: |
1629 * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
1630 * | // strlen($in) == $this->block_size |
1631 * | // here comes the cipher algorithm in action |
1632 * | // for decryption. |
1633 * | // $cipher_code['decrypt_block'] has to |
1634 * | // decrypt the content of the $in variable |
1635 * | $ciphertext .= $in; |
1636 * | } |
1637 * | return $ciphertext; |
1638 * | } |
1639 * | } |
1640 * +----------------------------------------------------------------------------------------------+
1641 * </code>
1642 *
1643 * See also the Crypt_*::_setupInlineCrypt()'s for
1644 * productive inline $cipher_code's how they works.
1645 *
1646 * Structure of:
1647 * <code>
1648 * $cipher_code = array(
1649 * 'init_crypt' => (string) '', // optional
1650 * 'init_encrypt' => (string) '', // optional
1651 * 'init_decrypt' => (string) '', // optional
1652 * 'encrypt_block' => (string) '', // required
1653 * 'decrypt_block' => (string) '' // required
1654 * );
1655 * </code>
1656 *
1657 * @see Crypt_Base::_setupInlineCrypt()
1658 * @see Crypt_Base::encrypt()
1659 * @see Crypt_Base::decrypt()
1660 *
1661 * @param Array $cipher_code
1662 *
1663 * @access private
1664 * @return String (the name of the created callback function)
1665 */
1666 public function _createInlineCryptFunction($cipher_code)
1667 {
1668 $block_size = $this->block_size;
1669
1670 // optional
1671 $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
1672 $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
1673 $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
1674 // required
1675 $encrypt_block = $cipher_code['encrypt_block'];
1676 $decrypt_block = $cipher_code['decrypt_block'];
1677
1678 // Generating mode of operation inline code,
1679 // merged with the $cipher_code algorithm
1680 // for encrypt- and decryption.
1681 switch ($this->mode) {
1682 case CRYPT_MODE_ECB:
1683 $encrypt = $init_encrypt.'
1684 $_ciphertext = "";
1685 $_text = $self->_pad($_text);
1686 $_plaintext_len = strlen($_text);
1687
1688 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
1689 $in = substr($_text, $_i, '.$block_size.');
1690 '.$encrypt_block.'
1691 $_ciphertext.= $in;
1692 }
1693
1694 return $_ciphertext;
1695 ';
1696
1697 $decrypt = $init_decrypt.'
1698 $_plaintext = "";
1699 $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
1700 $_ciphertext_len = strlen($_text);
1701
1702 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
1703 $in = substr($_text, $_i, '.$block_size.');
1704 '.$decrypt_block.'
1705 $_plaintext.= $in;
1706 }
1707
1708 return $self->_unpad($_plaintext);
1709 ';
1710 break;
1711 case CRYPT_MODE_CTR:
1712 $encrypt = $init_encrypt.'
1713 $_ciphertext = "";
1714 $_plaintext_len = strlen($_text);
1715 $_xor = $self->encryptIV;
1716 $_buffer = &$self->enbuffer;
1717
1718 if (strlen($_buffer["encrypted"])) {
1719 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
1720 $_block = substr($_text, $_i, '.$block_size.');
1721 if (strlen($_block) > strlen($_buffer["encrypted"])) {
1722 $in = $self->_generateXor($_xor, '.$block_size.');
1723 '.$encrypt_block.'
1724 $_buffer["encrypted"].= $in;
1725 }
1726 $_key = $self->_stringShift($_buffer["encrypted"], '.$block_size.');
1727 $_ciphertext.= $_block ^ $_key;
1728 }
1729 } else {
1730 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
1731 $_block = substr($_text, $_i, '.$block_size.');
1732 $in = $self->_generateXor($_xor, '.$block_size.');
1733 '.$encrypt_block.'
1734 $_key = $in;
1735 $_ciphertext.= $_block ^ $_key;
1736 }
1737 }
1738 if ($self->continuousBuffer) {
1739 $self->encryptIV = $_xor;
1740 if ($_start = $_plaintext_len % '.$block_size.') {
1741 $_buffer["encrypted"] = substr($_key, $_start) . $_buffer["encrypted"];
1742 }
1743 }
1744
1745 return $_ciphertext;
1746 ';
1747
1748 $decrypt = $init_encrypt.'
1749 $_plaintext = "";
1750 $_ciphertext_len = strlen($_text);
1751 $_xor = $self->decryptIV;
1752 $_buffer = &$self->debuffer;
1753
1754 if (strlen($_buffer["ciphertext"])) {
1755 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
1756 $_block = substr($_text, $_i, '.$block_size.');
1757 if (strlen($_block) > strlen($_buffer["ciphertext"])) {
1758 $in = $self->_generateXor($_xor, '.$block_size.');
1759 '.$encrypt_block.'
1760 $_buffer["ciphertext"].= $in;
1761 }
1762 $_key = $self->_stringShift($_buffer["ciphertext"], '.$block_size.');
1763 $_plaintext.= $_block ^ $_key;
1764 }
1765 } else {
1766 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
1767 $_block = substr($_text, $_i, '.$block_size.');
1768 $in = $self->_generateXor($_xor, '.$block_size.');
1769 '.$encrypt_block.'
1770 $_key = $in;
1771 $_plaintext.= $_block ^ $_key;
1772 }
1773 }
1774 if ($self->continuousBuffer) {
1775 $self->decryptIV = $_xor;
1776 if ($_start = $_ciphertext_len % '.$block_size.') {
1777 $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
1778 }
1779 }
1780
1781 return $_plaintext;
1782 ';
1783 break;
1784 case CRYPT_MODE_CFB:
1785 $encrypt = $init_encrypt.'
1786 $_ciphertext = "";
1787 $_buffer = &$self->enbuffer;
1788
1789 if ($self->continuousBuffer) {
1790 $_iv = &$self->encryptIV;
1791 $_pos = &$_buffer["pos"];
1792 } else {
1793 $_iv = $self->encryptIV;
1794 $_pos = 0;
1795 }
1796 $_len = strlen($_text);
1797 $_i = 0;
1798 if ($_pos) {
1799 $_orig_pos = $_pos;
1800 $_max = '.$block_size.' - $_pos;
1801 if ($_len >= $_max) {
1802 $_i = $_max;
1803 $_len-= $_max;
1804 $_pos = 0;
1805 } else {
1806 $_i = $_len;
1807 $_pos+= $_len;
1808 $_len = 0;
1809 }
1810 $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
1811 $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
1812 }
1813 while ($_len >= '.$block_size.') {
1814 $in = $_iv;
1815 '.$encrypt_block.';
1816 $_iv = $in ^ substr($_text, $_i, '.$block_size.');
1817 $_ciphertext.= $_iv;
1818 $_len-= '.$block_size.';
1819 $_i+= '.$block_size.';
1820 }
1821 if ($_len) {
1822 $in = $_iv;
1823 '.$encrypt_block.'
1824 $_iv = $in;
1825 $_block = $_iv ^ substr($_text, $_i);
1826 $_iv = substr_replace($_iv, $_block, 0, $_len);
1827 $_ciphertext.= $_block;
1828 $_pos = $_len;
1829 }
1830 return $_ciphertext;
1831 ';
1832
1833 $decrypt = $init_encrypt.'
1834 $_plaintext = "";
1835 $_buffer = &$self->debuffer;
1836
1837 if ($self->continuousBuffer) {
1838 $_iv = &$self->decryptIV;
1839 $_pos = &$_buffer["pos"];
1840 } else {
1841 $_iv = $self->decryptIV;
1842 $_pos = 0;
1843 }
1844 $_len = strlen($_text);
1845 $_i = 0;
1846 if ($_pos) {
1847 $_orig_pos = $_pos;
1848 $_max = '.$block_size.' - $_pos;
1849 if ($_len >= $_max) {
1850 $_i = $_max;
1851 $_len-= $_max;
1852 $_pos = 0;
1853 } else {
1854 $_i = $_len;
1855 $_pos+= $_len;
1856 $_len = 0;
1857 }
1858 $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
1859 $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
1860 }
1861 while ($_len >= '.$block_size.') {
1862 $in = $_iv;
1863 '.$encrypt_block.'
1864 $_iv = $in;
1865 $cb = substr($_text, $_i, '.$block_size.');
1866 $_plaintext.= $_iv ^ $cb;
1867 $_iv = $cb;
1868 $_len-= '.$block_size.';
1869 $_i+= '.$block_size.';
1870 }
1871 if ($_len) {
1872 $in = $_iv;
1873 '.$encrypt_block.'
1874 $_iv = $in;
1875 $_plaintext.= $_iv ^ substr($_text, $_i);
1876 $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
1877 $_pos = $_len;
1878 }
1879
1880 return $_plaintext;
1881 ';
1882 break;
1883 case CRYPT_MODE_OFB:
1884 $encrypt = $init_encrypt.'
1885 $_ciphertext = "";
1886 $_plaintext_len = strlen($_text);
1887 $_xor = $self->encryptIV;
1888 $_buffer = &$self->enbuffer;
1889
1890 if (strlen($_buffer["xor"])) {
1891 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
1892 $_block = substr($_text, $_i, '.$block_size.');
1893 if (strlen($_block) > strlen($_buffer["xor"])) {
1894 $in = $_xor;
1895 '.$encrypt_block.'
1896 $_xor = $in;
1897 $_buffer["xor"].= $_xor;
1898 }
1899 $_key = $self->_stringShift($_buffer["xor"], '.$block_size.');
1900 $_ciphertext.= $_block ^ $_key;
1901 }
1902 } else {
1903 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
1904 $in = $_xor;
1905 '.$encrypt_block.'
1906 $_xor = $in;
1907 $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
1908 }
1909 $_key = $_xor;
1910 }
1911 if ($self->continuousBuffer) {
1912 $self->encryptIV = $_xor;
1913 if ($_start = $_plaintext_len % '.$block_size.') {
1914 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
1915 }
1916 }
1917 return $_ciphertext;
1918 ';
1919
1920 $decrypt = $init_encrypt.'
1921 $_plaintext = "";
1922 $_ciphertext_len = strlen($_text);
1923 $_xor = $self->decryptIV;
1924 $_buffer = &$self->debuffer;
1925
1926 if (strlen($_buffer["xor"])) {
1927 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
1928 $_block = substr($_text, $_i, '.$block_size.');
1929 if (strlen($_block) > strlen($_buffer["xor"])) {
1930 $in = $_xor;
1931 '.$encrypt_block.'
1932 $_xor = $in;
1933 $_buffer["xor"].= $_xor;
1934 }
1935 $_key = $self->_stringShift($_buffer["xor"], '.$block_size.');
1936 $_plaintext.= $_block ^ $_key;
1937 }
1938 } else {
1939 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
1940 $in = $_xor;
1941 '.$encrypt_block.'
1942 $_xor = $in;
1943 $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
1944 }
1945 $_key = $_xor;
1946 }
1947 if ($self->continuousBuffer) {
1948 $self->decryptIV = $_xor;
1949 if ($_start = $_ciphertext_len % '.$block_size.') {
1950 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
1951 }
1952 }
1953 return $_plaintext;
1954 ';
1955 break;
1956 case CRYPT_MODE_STREAM:
1957 $encrypt = $init_encrypt.'
1958 $_ciphertext = "";
1959 '.$encrypt_block.'
1960 return $_ciphertext;
1961 ';
1962 $decrypt = $init_decrypt.'
1963 $_plaintext = "";
1964 '.$decrypt_block.'
1965 return $_plaintext;
1966 ';
1967 break;
1968 // case CRYPT_MODE_CBC:
1969 default:
1970 $encrypt = $init_encrypt.'
1971 $_ciphertext = "";
1972 $_text = $self->_pad($_text);
1973 $_plaintext_len = strlen($_text);
1974
1975 $in = $self->encryptIV;
1976
1977 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
1978 $in = substr($_text, $_i, '.$block_size.') ^ $in;
1979 '.$encrypt_block.'
1980 $_ciphertext.= $in;
1981 }
1982
1983 if ($self->continuousBuffer) {
1984 $self->encryptIV = $in;
1985 }
1986
1987 return $_ciphertext;
1988 ';
1989
1990 $decrypt = $init_decrypt.'
1991 $_plaintext = "";
1992 $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
1993 $_ciphertext_len = strlen($_text);
1994
1995 $_iv = $self->decryptIV;
1996
1997 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
1998 $in = $_block = substr($_text, $_i, '.$block_size.');
1999 '.$decrypt_block.'
2000 $_plaintext.= $in ^ $_iv;
2001 $_iv = $_block;
2002 }
2003
2004 if ($self->continuousBuffer) {
2005 $self->decryptIV = $_iv;
2006 }
2007
2008 return $self->_unpad($_plaintext);
2009 ';
2010 break;
2011 }
2012
2013 // Create the $inline function and return its name as string. Ready to run!
2014 return create_function('$_action, &$self, $_text', $init_crypt.'if ($_action == "encrypt") { '.$encrypt.' } else { '.$decrypt.' }');
2015 }
2016
2017 /**
2018 * Holds the lambda_functions table (classwide)
2019 *
2020 * Each name of the lambda function, created from
2021 * _setupInlineCrypt() && _createInlineCryptFunction()
2022 * is stored, classwide (!), here for reusing.
2023 *
2024 * The string-based index of $function is a classwide
2025 * uniqe value representing, at least, the $mode of
2026 * operation (or more... depends of the optimizing level)
2027 * for which $mode the lambda function was created.
2028 *
2029 * @access private
2030 * @return &Array
2031 */
2032 public static function &_getLambdaFunctions()
2033 {
2034 static $functions = array();
2035
2036 return $functions;
2037 }
2038 }
2039