PluginProbe
Contact Forms by Cimatti / 2.3.0
Contact Forms by Cimatti v2.3.0
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
contact-forms / phpseclib-crypt / Base.php

Base.php in Contact Forms by Cimatti 2.3.0, at phpseclib-crypt/Base.php

2,669 lines 101.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * phpseclib Crypt_Base - Third-party library
4 * @package phpseclib
5 */
6 if ( ! defined( 'ABSPATH' ) ) exit;
7
8 // phpcs:disable WordPress.Security.EscapeOutput, WordPress.NamingConventions.PrefixAllGlobals, Generic.PHP.ForbiddenFunctions, WordPress.PHP.DevelopmentFunctions, WordPress.WP.AlternativeFunctions -- Third-party cryptographic library
9
10 /**
11 * Base Class for all Crypt_* cipher classes
12 *
13 * PHP versions 4 and 5
14 *
15 * Internally for phpseclib developers:
16 * If you plan to add a new cipher class, please note following rules:
17 *
18 * - The new Crypt_* cipher class should extend Crypt_Base
19 *
20 * - Following methods are then required to be overridden/overloaded:
21 *
22 * - _encryptBlock()
23 *
24 * - _decryptBlock()
25 *
26 * - _setupKey()
27 *
28 * - All other methods are optional to be overridden/overloaded
29 *
30 * - Look at the source code of the current ciphers how they extend Crypt_Base
31 * and take one of them as a start up for the new cipher class.
32 *
33 * - Please read all the other comments/notes/hints here also for each class var/method
34 *
35 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
36 * of this software and associated documentation files (the "Software"), to deal
37 * in the Software without restriction, including without limitation the rights
38 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39 * copies of the Software, and to permit persons to whom the Software is
40 * furnished to do so, subject to the following conditions:
41 *
42 * The above copyright notice and this permission notice shall be included in
43 * all copies or substantial portions of the Software.
44 *
45 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
51 * THE SOFTWARE.
52 *
53 * @category Crypt
54 * @package Crypt_Base
55 * @author Jim Wigginton <terrafrost@php.net>
56 * @author Hans-Juergen Petrich <petrich@tronic-media.com>
57 * @copyright 2007 Jim Wigginton
58 * @license http://www.opensource.org/licenses/mit-license.html MIT License
59 * @link http://phpseclib.sourceforge.net
60 */
61
62 /**#@+
63 * @access public
64 * @see self::encrypt()
65 * @see self::decrypt()
66 */
67 /**
68 * Encrypt / decrypt using the Counter mode.
69 *
70 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
71 *
72 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
73 */
74 define('CRYPT_MODE_CTR', -1);
75 /**
76 * Encrypt / decrypt using the Electronic Code Book mode.
77 *
78 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
79 */
80 define('CRYPT_MODE_ECB', 1);
81 /**
82 * Encrypt / decrypt using the Code Book Chaining mode.
83 *
84 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
85 */
86 define('CRYPT_MODE_CBC', 2);
87 /**
88 * Encrypt / decrypt using the Cipher Feedback mode.
89 *
90 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
91 */
92 define('CRYPT_MODE_CFB', 3);
93 /**
94 * Encrypt / decrypt using the Output Feedback mode.
95 *
96 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
97 */
98 define('CRYPT_MODE_OFB', 4);
99 /**
100 * Encrypt / decrypt using streaming mode.
101 */
102 define('CRYPT_MODE_STREAM', 5);
103 /**#@-*/
104
105 /**#@+
106 * @access private
107 * @see self::Crypt_Base()
108 * @internal These constants are for internal use only
109 */
110 /**
111 * Base value for the internal implementation $engine switch
112 */
113 define('CRYPT_ENGINE_INTERNAL', 1);
114 /**
115 * Base value for the mcrypt implementation $engine switch
116 */
117 define('CRYPT_ENGINE_MCRYPT', 2);
118 /**
119 * Base value for the OpenSSL implementation $engine switch
120 */
121 define('CRYPT_ENGINE_OPENSSL', 3);
122 /**#@-*/
123
124 /**
125 * Base Class for all Crypt_* cipher classes
126 *
127 * @package Crypt_Base
128 * @author Jim Wigginton <terrafrost@php.net>
129 * @author Hans-Juergen Petrich <petrich@tronic-media.com>
130 * @access public
131 */
132 #[AllowDynamicProperties]
133 class Crypt_Base
134 {
135 /**
136 * The Encryption Mode
137 *
138 * @see self::Crypt_Base()
139 * @var int
140 * @access private
141 */
142 var $mode;
143
144 /**
145 * The Block Length of the block cipher
146 *
147 * @var int
148 * @access private
149 */
150 var $block_size = 16;
151
152 /**
153 * The Key
154 *
155 * @see self::setKey()
156 * @var string
157 * @access private
158 */
159 var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
160
161 /**
162 * The Initialization Vector
163 *
164 * @see self::setIV()
165 * @var string
166 * @access private
167 */
168 var $iv;
169
170 /**
171 * A "sliding" Initialization Vector
172 *
173 * @see self::enableContinuousBuffer()
174 * @see self::_clearBuffers()
175 * @var string
176 * @access private
177 */
178 var $encryptIV;
179
180 /**
181 * A "sliding" Initialization Vector
182 *
183 * @see self::enableContinuousBuffer()
184 * @see self::_clearBuffers()
185 * @var string
186 * @access private
187 */
188 var $decryptIV;
189
190 /**
191 * Continuous Buffer status
192 *
193 * @see self::enableContinuousBuffer()
194 * @var bool
195 * @access private
196 */
197 var $continuousBuffer = false;
198
199 /**
200 * Encryption buffer for CTR, OFB and CFB modes
201 *
202 * @see self::encrypt()
203 * @see self::_clearBuffers()
204 * @var array
205 * @access private
206 */
207 var $enbuffer;
208
209 /**
210 * Decryption buffer for CTR, OFB and CFB modes
211 *
212 * @see self::decrypt()
213 * @see self::_clearBuffers()
214 * @var array
215 * @access private
216 */
217 var $debuffer;
218
219 /**
220 * mcrypt resource for encryption
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 self::encrypt()
226 * @var resource
227 * @access private
228 */
229 var $enmcrypt;
230
231 /**
232 * mcrypt resource for decryption
233 *
234 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
235 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
236 *
237 * @see self::decrypt()
238 * @var resource
239 * @access private
240 */
241 var $demcrypt;
242
243 /**
244 * Does the enmcrypt resource need to be (re)initialized?
245 *
246 * @see Crypt_Twofish::setKey()
247 * @see Crypt_Twofish::setIV()
248 * @var bool
249 * @access private
250 */
251 var $enchanged = true;
252
253 /**
254 * Does the demcrypt resource need to be (re)initialized?
255 *
256 * @see Crypt_Twofish::setKey()
257 * @see Crypt_Twofish::setIV()
258 * @var bool
259 * @access private
260 */
261 var $dechanged = true;
262
263 /**
264 * mcrypt resource for CFB mode
265 *
266 * mcrypt's CFB mode, in (and only in) buffered context,
267 * is broken, so phpseclib implements the CFB mode by it self,
268 * even when the mcrypt php extension is available.
269 *
270 * In order to do the CFB-mode work (fast) phpseclib
271 * use a separate ECB-mode mcrypt resource.
272 *
273 * @link http://phpseclib.sourceforge.net/cfb-demo.phps
274 * @see self::encrypt()
275 * @see self::decrypt()
276 * @see self::_setupMcrypt()
277 * @var resource
278 * @access private
279 */
280 var $ecb;
281
282 /**
283 * Optimizing value while CFB-encrypting
284 *
285 * Only relevant if $continuousBuffer enabled
286 * and $engine == CRYPT_ENGINE_MCRYPT
287 *
288 * It's faster to re-init $enmcrypt if
289 * $buffer bytes > $cfb_init_len than
290 * using the $ecb resource furthermore.
291 *
292 * This value depends of the chosen cipher
293 * and the time it would be needed for it's
294 * initialization [by mcrypt_generic_init()]
295 * which, typically, depends on the complexity
296 * on its internaly Key-expanding algorithm.
297 *
298 * @see self::encrypt()
299 * @var int
300 * @access private
301 */
302 var $cfb_init_len = 600;
303
304 /**
305 * Does internal cipher state need to be (re)initialized?
306 *
307 * @see self::setKey()
308 * @see self::setIV()
309 * @see self::disableContinuousBuffer()
310 * @var bool
311 * @access private
312 */
313 var $changed = true;
314
315 /**
316 * Padding status
317 *
318 * @see self::enablePadding()
319 * @var bool
320 * @access private
321 */
322 var $padding = true;
323
324 /**
325 * Is the mode one that is paddable?
326 *
327 * @see self::Crypt_Base()
328 * @var bool
329 * @access private
330 */
331 var $paddable = false;
332
333 /**
334 * Holds which crypt engine internaly should be use,
335 * which will be determined automatically on __construct()
336 *
337 * Currently available $engines are:
338 * - CRYPT_ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
339 * - CRYPT_ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
340 * - CRYPT_ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
341 *
342 * @see self::_setEngine()
343 * @see self::encrypt()
344 * @see self::decrypt()
345 * @var int
346 * @access private
347 */
348 var $engine;
349
350 /**
351 * Holds the preferred crypt engine
352 *
353 * @see self::_setEngine()
354 * @see self::setPreferredEngine()
355 * @var int
356 * @access private
357 */
358 var $preferredEngine;
359
360 /**
361 * The mcrypt specific name of the cipher
362 *
363 * Only used if $engine == CRYPT_ENGINE_MCRYPT
364 *
365 * @link http://www.php.net/mcrypt_module_open
366 * @link http://www.php.net/mcrypt_list_algorithms
367 * @see self::_setupMcrypt()
368 * @var string
369 * @access private
370 */
371 var $cipher_name_mcrypt;
372
373 /**
374 * The openssl specific name of the cipher
375 *
376 * Only used if $engine == CRYPT_ENGINE_OPENSSL
377 *
378 * @link http://www.php.net/openssl-get-cipher-methods
379 * @var string
380 * @access private
381 */
382 var $cipher_name_openssl;
383
384 /**
385 * The openssl specific name of the cipher in ECB mode
386 *
387 * If OpenSSL does not support the mode we're trying to use (CTR)
388 * it can still be emulated with ECB mode.
389 *
390 * @link http://www.php.net/openssl-get-cipher-methods
391 * @var string
392 * @access private
393 */
394 var $cipher_name_openssl_ecb;
395
396 /**
397 * The default salt used by setPassword()
398 *
399 * @see self::setPassword()
400 * @var string
401 * @access private
402 */
403 var $password_default_salt = 'phpseclib/salt';
404
405 /**
406 * The namespace used by the cipher for its constants.
407 *
408 * ie: AES.php is using CRYPT_AES_MODE_* for its constants
409 * so $const_namespace is AES
410 *
411 * DES.php is using CRYPT_DES_MODE_* for its constants
412 * so $const_namespace is DES... and so on
413 *
414 * All CRYPT_<$const_namespace>_MODE_* are aliases of
415 * the generic CRYPT_MODE_* constants, so both could be used
416 * for each cipher.
417 *
418 * Example:
419 * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
420 * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
421 *
422 * @see self::Crypt_Base()
423 * @var string
424 * @access private
425 */
426 var $const_namespace;
427
428 /**
429 * The name of the performance-optimized callback function
430 *
431 * Used by encrypt() / decrypt()
432 * only if $engine == CRYPT_ENGINE_INTERNAL
433 *
434 * @see self::encrypt()
435 * @see self::decrypt()
436 * @see self::_setupInlineCrypt()
437 * @see self::$use_inline_crypt
438 * @var Callback
439 * @access private
440 */
441 var $inline_crypt;
442
443 /**
444 * Holds whether performance-optimized $inline_crypt() can/should be used.
445 *
446 * @see self::encrypt()
447 * @see self::decrypt()
448 * @see self::inline_crypt
449 * @var mixed
450 * @access private
451 */
452 var $use_inline_crypt;
453
454 /**
455 * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
456 *
457 * @see self::_openssl_ctr_process()
458 * @var bool
459 * @access private
460 */
461 var $openssl_emulate_ctr = false;
462
463 /**
464 * Determines what options are passed to openssl_encrypt/decrypt
465 *
466 * @see self::isValidEngine()
467 * @var mixed
468 * @access private
469 */
470 var $openssl_options;
471
472 /**
473 * Has the key length explicitly been set or should it be derived from the key, itself?
474 *
475 * @see self::setKeyLength()
476 * @var bool
477 * @access private
478 */
479 var $explicit_key_length = false;
480
481 /**
482 * Don't truncate / null pad key
483 *
484 * @see self::_clearBuffers()
485 * @var bool
486 * @access private
487 */
488 var $skip_key_adjustment = false;
489
490 /**
491 * Default Constructor.
492 *
493 * Determines whether or not the mcrypt extension should be used.
494 *
495 * $mode could be:
496 *
497 * - CRYPT_MODE_ECB
498 *
499 * - CRYPT_MODE_CBC
500 *
501 * - CRYPT_MODE_CTR
502 *
503 * - CRYPT_MODE_CFB
504 *
505 * - CRYPT_MODE_OFB
506 *
507 * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
508 *
509 * If not explicitly set, CRYPT_MODE_CBC will be used.
510 *
511 * @param int $mode
512 * @access public
513 */
514 function __construct($mode = CRYPT_MODE_CBC)
515 {
516 // $mode dependent settings
517 switch ($mode) {
518 case CRYPT_MODE_ECB:
519 $this->paddable = true;
520 $this->mode = CRYPT_MODE_ECB;
521 break;
522 case CRYPT_MODE_CTR:
523 case CRYPT_MODE_CFB:
524 case CRYPT_MODE_OFB:
525 case CRYPT_MODE_STREAM:
526 $this->mode = $mode;
527 break;
528 case CRYPT_MODE_CBC:
529 default:
530 $this->paddable = true;
531 $this->mode = CRYPT_MODE_CBC;
532 }
533
534 $this->_setEngine();
535
536 // Determining whether inline crypting can be used by the cipher
537 if ($this->use_inline_crypt !== false) {
538 $this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
539 }
540 }
541
542 /**
543 * PHP4 compatible Default Constructor.
544 *
545 * @see self::__construct()
546 * @param int $mode
547 * @access public
548 */
549 function Crypt_Base($mode = CRYPT_MODE_CBC)
550 {
551 $this->__construct($mode);
552 }
553
554 /**
555 * Sets the initialization vector. (optional)
556 *
557 * 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
558 * to be all zero's.
559 *
560 * @access public
561 * @param string $iv
562 * @internal Can be overwritten by a sub class, but does not have to be
563 */
564 function setIV($iv)
565 {
566 if ($this->mode == CRYPT_MODE_ECB) {
567 return;
568 }
569
570 $this->iv = $iv;
571 $this->changed = true;
572 }
573
574 /**
575 * Sets the key length.
576 *
577 * Keys with explicitly set lengths need to be treated accordingly
578 *
579 * @access public
580 * @param int $length
581 */
582 function setKeyLength($length)
583 {
584 $this->explicit_key_length = true;
585 $this->changed = true;
586 $this->_setEngine();
587 }
588
589 /**
590 * Returns the current key length in bits
591 *
592 * @access public
593 * @return int
594 */
595 function getKeyLength()
596 {
597 return $this->key_length << 3;
598 }
599
600 /**
601 * Returns the current block length in bits
602 *
603 * @access public
604 * @return int
605 */
606 function getBlockLength()
607 {
608 return $this->block_size << 3;
609 }
610
611 /**
612 * Sets the key.
613 *
614 * The min/max length(s) of the key depends on the cipher which is used.
615 * If the key not fits the length(s) of the cipher it will paded with null bytes
616 * up to the closest valid key length. If the key is more than max length,
617 * we trim the excess bits.
618 *
619 * If the key is not explicitly set, it'll be assumed to be all null bytes.
620 *
621 * @access public
622 * @param string $key
623 * @internal Could, but not must, extend by the child Crypt_* class
624 */
625 function setKey($key)
626 {
627 if (!$this->explicit_key_length) {
628 $this->setKeyLength(strlen($key) << 3);
629 $this->explicit_key_length = false;
630 }
631
632 $this->key = $key;
633 $this->changed = true;
634 $this->_setEngine();
635 }
636
637 /**
638 * Sets the password.
639 *
640 * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
641 * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
642 * $hash, $salt, $count, $dkLen
643 *
644 * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
645 *
646 * @see Crypt/Hash.php
647 * @param string $password
648 * @param string $method
649 * @return bool
650 * @access public
651 * @internal Could, but not must, extend by the child Crypt_* class
652 */
653 function setPassword($password, $method = 'pbkdf2')
654 {
655 $key = '';
656
657 switch ($method) {
658 default: // 'pbkdf2' or 'pbkdf1'
659 $func_args = func_get_args();
660
661 // Hash function
662 $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
663
664 // WPA and WPA2 use the SSID as the salt
665 $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
666
667 // RFC2898#section-4.2 uses 1,000 iterations by default
668 // WPA and WPA2 use 4,096.
669 $count = isset($func_args[4]) ? $func_args[4] : 1000;
670
671 // Keylength
672 if (isset($func_args[5]) && $func_args[5] > 0) {
673 $dkLen = $func_args[5];
674 } else {
675 $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
676 }
677
678 switch (true) {
679 case $method == 'pbkdf1':
680 if (!class_exists('Crypt_Hash')) {
681 include_once 'Hash.php';
682 }
683 $hashObj = new Crypt_Hash();
684 $hashObj->setHash($hash);
685 if ($dkLen > $hashObj->getLength()) {
686 user_error('Derived key too long');
687 return false;
688 }
689 $t = $password . $salt;
690 for ($i = 0; $i < $count; ++$i) {
691 $t = $hashObj->hash($t);
692 }
693 $key = substr($t, 0, $dkLen);
694
695 $this->setKey(substr($key, 0, $dkLen >> 1));
696 $this->setIV(substr($key, $dkLen >> 1));
697
698 return true;
699 // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
700 case !function_exists('hash_pbkdf2'):
701 case !function_exists('hash_algos'):
702 case !in_array($hash, hash_algos()):
703 if (!class_exists('Crypt_Hash')) {
704 include_once 'Hash.php';
705 }
706 $i = 1;
707 $hmac = new Crypt_Hash();
708 $hmac->setHash($hash);
709 $hmac->setKey($password);
710 while (strlen($key) < $dkLen) {
711 $f = $u = $hmac->hash($salt . pack('N', $i++));
712 for ($j = 2; $j <= $count; ++$j) {
713 $u = $hmac->hash($u);
714 $f^= $u;
715 }
716 $key.= $f;
717 }
718 $key = substr($key, 0, $dkLen);
719 break;
720 default:
721 $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
722 }
723 }
724
725 $this->setKey($key);
726
727 return true;
728 }
729
730 /**
731 * Encrypts a message.
732 *
733 * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
734 * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
735 * necessary are discussed in the following
736 * URL:
737 *
738 * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
739 *
740 * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
741 * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
742 * length.
743 *
744 * @see self::decrypt()
745 * @access public
746 * @param string $plaintext
747 * @return string $ciphertext
748 * @internal Could, but not must, extend by the child Crypt_* class
749 */
750 function encrypt($plaintext)
751 {
752 if ($this->paddable) {
753 $plaintext = $this->_pad($plaintext);
754 }
755
756 if ($this->engine === CRYPT_ENGINE_OPENSSL) {
757 if ($this->changed) {
758 $this->_clearBuffers();
759 $this->changed = false;
760 }
761 switch ($this->mode) {
762 case CRYPT_MODE_STREAM:
763 return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
764 case CRYPT_MODE_ECB:
765 $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
766 return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
767 case CRYPT_MODE_CBC:
768 $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
769 if (!defined('OPENSSL_RAW_DATA')) {
770 $result = substr($result, 0, -$this->block_size);
771 }
772 if ($this->continuousBuffer) {
773 $this->encryptIV = substr($result, -$this->block_size);
774 }
775 return $result;
776 case CRYPT_MODE_CTR:
777 return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
778 case CRYPT_MODE_CFB:
779 // cfb loosely routines inspired by openssl's:
780 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
781 $ciphertext = '';
782 if ($this->continuousBuffer) {
783 $iv = &$this->encryptIV;
784 $pos = &$this->enbuffer['pos'];
785 } else {
786 $iv = $this->encryptIV;
787 $pos = 0;
788 }
789 $len = strlen($plaintext);
790 $i = 0;
791 if ($pos) {
792 $orig_pos = $pos;
793 $max = $this->block_size - $pos;
794 if ($len >= $max) {
795 $i = $max;
796 $len-= $max;
797 $pos = 0;
798 } else {
799 $i = $len;
800 $pos+= $len;
801 $len = 0;
802 }
803 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
804 $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
805 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
806 $plaintext = substr($plaintext, $i);
807 }
808
809 $overflow = $len % $this->block_size;
810
811 if ($overflow) {
812 $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
813 $iv = $this->_string_pop($ciphertext, $this->block_size);
814
815 $size = $len - $overflow;
816 $block = $iv ^ substr($plaintext, -$overflow);
817 $iv = substr_replace($iv, $block, 0, $overflow);
818 $ciphertext.= $block;
819 $pos = $overflow;
820 } elseif ($len) {
821 $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
822 $iv = substr($ciphertext, -$this->block_size);
823 }
824
825 return $ciphertext;
826 case CRYPT_MODE_OFB:
827 return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
828 }
829 }
830
831 if ($this->engine === CRYPT_ENGINE_MCRYPT) {
832 if ($this->changed) {
833 $this->_setupMcrypt();
834 $this->changed = false;
835 }
836 if ($this->enchanged) {
837 @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
838 $this->enchanged = false;
839 }
840
841 // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
842 // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
843 // rewritten CFB implementation the above outputs the same thing twice.
844 if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
845 $block_size = $this->block_size;
846 $iv = &$this->encryptIV;
847 $pos = &$this->enbuffer['pos'];
848 $len = strlen($plaintext);
849 $ciphertext = '';
850 $i = 0;
851 if ($pos) {
852 $orig_pos = $pos;
853 $max = $block_size - $pos;
854 if ($len >= $max) {
855 $i = $max;
856 $len-= $max;
857 $pos = 0;
858 } else {
859 $i = $len;
860 $pos+= $len;
861 $len = 0;
862 }
863 $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
864 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
865 $this->enbuffer['enmcrypt_init'] = true;
866 }
867 if ($len >= $block_size) {
868 if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
869 if ($this->enbuffer['enmcrypt_init'] === true) {
870 @mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
871 $this->enbuffer['enmcrypt_init'] = false;
872 }
873 $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
874 $iv = substr($ciphertext, -$block_size);
875 $len%= $block_size;
876 } else {
877 while ($len >= $block_size) {
878 $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
879 $ciphertext.= $iv;
880 $len-= $block_size;
881 $i+= $block_size;
882 }
883 }
884 }
885
886 if ($len) {
887 $iv = @mcrypt_generic($this->ecb, $iv);
888 $block = $iv ^ substr($plaintext, -$len);
889 $iv = substr_replace($iv, $block, 0, $len);
890 $ciphertext.= $block;
891 $pos = $len;
892 }
893
894 return $ciphertext;
895 }
896
897 $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
898
899 if (!$this->continuousBuffer) {
900 @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
901 }
902
903 return $ciphertext;
904 }
905
906 if ($this->changed) {
907 $this->_setup();
908 $this->changed = false;
909 }
910 if ($this->use_inline_crypt) {
911 $inline = $this->inline_crypt;
912 return $inline('encrypt', $this, $plaintext);
913 }
914
915 $buffer = &$this->enbuffer;
916 $block_size = $this->block_size;
917 $ciphertext = '';
918 switch ($this->mode) {
919 case CRYPT_MODE_ECB:
920 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
921 $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
922 }
923 break;
924 case CRYPT_MODE_CBC:
925 $xor = $this->encryptIV;
926 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
927 $block = substr($plaintext, $i, $block_size);
928 $block = $this->_encryptBlock($block ^ $xor);
929 $xor = $block;
930 $ciphertext.= $block;
931 }
932 if ($this->continuousBuffer) {
933 $this->encryptIV = $xor;
934 }
935 break;
936 case CRYPT_MODE_CTR:
937 $xor = $this->encryptIV;
938 if (strlen($buffer['ciphertext'])) {
939 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
940 $block = substr($plaintext, $i, $block_size);
941 if (strlen($block) > strlen($buffer['ciphertext'])) {
942 $buffer['ciphertext'].= $this->_encryptBlock($xor);
943 }
944 $this->_increment_str($xor);
945 $key = $this->_string_shift($buffer['ciphertext'], $block_size);
946 $ciphertext.= $block ^ $key;
947 }
948 } else {
949 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
950 $block = substr($plaintext, $i, $block_size);
951 $key = $this->_encryptBlock($xor);
952 $this->_increment_str($xor);
953 $ciphertext.= $block ^ $key;
954 }
955 }
956 if ($this->continuousBuffer) {
957 $this->encryptIV = $xor;
958 if ($start = strlen($plaintext) % $block_size) {
959 $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
960 }
961 }
962 break;
963 case CRYPT_MODE_CFB:
964 // cfb loosely routines inspired by openssl's:
965 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
966 if ($this->continuousBuffer) {
967 $iv = &$this->encryptIV;
968 $pos = &$buffer['pos'];
969 } else {
970 $iv = $this->encryptIV;
971 $pos = 0;
972 }
973 $len = strlen($plaintext);
974 $i = 0;
975 if ($pos) {
976 $orig_pos = $pos;
977 $max = $block_size - $pos;
978 if ($len >= $max) {
979 $i = $max;
980 $len-= $max;
981 $pos = 0;
982 } else {
983 $i = $len;
984 $pos+= $len;
985 $len = 0;
986 }
987 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
988 $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
989 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
990 }
991 while ($len >= $block_size) {
992 $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
993 $ciphertext.= $iv;
994 $len-= $block_size;
995 $i+= $block_size;
996 }
997 if ($len) {
998 $iv = $this->_encryptBlock($iv);
999 $block = $iv ^ substr($plaintext, $i);
1000 $iv = substr_replace($iv, $block, 0, $len);
1001 $ciphertext.= $block;
1002 $pos = $len;
1003 }
1004 break;
1005 case CRYPT_MODE_OFB:
1006 $xor = $this->encryptIV;
1007 if (strlen($buffer['xor'])) {
1008 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1009 $block = substr($plaintext, $i, $block_size);
1010 if (strlen($block) > strlen($buffer['xor'])) {
1011 $xor = $this->_encryptBlock($xor);
1012 $buffer['xor'].= $xor;
1013 }
1014 $key = $this->_string_shift($buffer['xor'], $block_size);
1015 $ciphertext.= $block ^ $key;
1016 }
1017 } else {
1018 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1019 $xor = $this->_encryptBlock($xor);
1020 $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
1021 }
1022 $key = $xor;
1023 }
1024 if ($this->continuousBuffer) {
1025 $this->encryptIV = $xor;
1026 if ($start = strlen($plaintext) % $block_size) {
1027 $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1028 }
1029 }
1030 break;
1031 case CRYPT_MODE_STREAM:
1032 $ciphertext = $this->_encryptBlock($plaintext);
1033 break;
1034 }
1035
1036 return $ciphertext;
1037 }
1038
1039 /**
1040 * Decrypts a message.
1041 *
1042 * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
1043 * it is.
1044 *
1045 * @see self::encrypt()
1046 * @access public
1047 * @param string $ciphertext
1048 * @return string $plaintext
1049 * @internal Could, but not must, extend by the child Crypt_* class
1050 */
1051 function decrypt($ciphertext)
1052 {
1053 if ($this->paddable) {
1054 // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
1055 // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
1056 $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
1057 }
1058
1059 if ($this->engine === CRYPT_ENGINE_OPENSSL) {
1060 if ($this->changed) {
1061 $this->_clearBuffers();
1062 $this->changed = false;
1063 }
1064 switch ($this->mode) {
1065 case CRYPT_MODE_STREAM:
1066 $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1067 break;
1068 case CRYPT_MODE_ECB:
1069 if (!defined('OPENSSL_RAW_DATA')) {
1070 $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
1071 }
1072 $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1073 break;
1074 case CRYPT_MODE_CBC:
1075 if (!defined('OPENSSL_RAW_DATA')) {
1076 $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
1077 $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
1078 $offset = 2 * $this->block_size;
1079 } else {
1080 $offset = $this->block_size;
1081 }
1082 $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
1083 if ($this->continuousBuffer) {
1084 $this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
1085 }
1086 break;
1087 case CRYPT_MODE_CTR:
1088 $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
1089 break;
1090 case CRYPT_MODE_CFB:
1091 // cfb loosely routines inspired by openssl's:
1092 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1093 $plaintext = '';
1094 if ($this->continuousBuffer) {
1095 $iv = &$this->decryptIV;
1096 $pos = &$this->buffer['pos'];
1097 } else {
1098 $iv = $this->decryptIV;
1099 $pos = 0;
1100 }
1101 $len = strlen($ciphertext);
1102 $i = 0;
1103 if ($pos) {
1104 $orig_pos = $pos;
1105 $max = $this->block_size - $pos;
1106 if ($len >= $max) {
1107 $i = $max;
1108 $len-= $max;
1109 $pos = 0;
1110 } else {
1111 $i = $len;
1112 $pos+= $len;
1113 $len = 0;
1114 }
1115 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
1116 $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1117 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1118 $ciphertext = substr($ciphertext, $i);
1119 }
1120 $overflow = $len % $this->block_size;
1121 if ($overflow) {
1122 $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1123 if ($len - $overflow) {
1124 $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
1125 }
1126 $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1127 $plaintext.= $iv ^ substr($ciphertext, -$overflow);
1128 $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
1129 $pos = $overflow;
1130 } elseif ($len) {
1131 $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1132 $iv = substr($ciphertext, -$this->block_size);
1133 }
1134 break;
1135 case CRYPT_MODE_OFB:
1136 $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
1137 }
1138
1139 return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1140 }
1141
1142 if ($this->engine === CRYPT_ENGINE_MCRYPT) {
1143 $block_size = $this->block_size;
1144 if ($this->changed) {
1145 $this->_setupMcrypt();
1146 $this->changed = false;
1147 }
1148 if ($this->dechanged) {
1149 @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1150 $this->dechanged = false;
1151 }
1152
1153 if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
1154 $iv = &$this->decryptIV;
1155 $pos = &$this->debuffer['pos'];
1156 $len = strlen($ciphertext);
1157 $plaintext = '';
1158 $i = 0;
1159 if ($pos) {
1160 $orig_pos = $pos;
1161 $max = $block_size - $pos;
1162 if ($len >= $max) {
1163 $i = $max;
1164 $len-= $max;
1165 $pos = 0;
1166 } else {
1167 $i = $len;
1168 $pos+= $len;
1169 $len = 0;
1170 }
1171 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1172 $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1173 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1174 }
1175 if ($len >= $block_size) {
1176 $cb = substr($ciphertext, $i, $len - $len % $block_size);
1177 $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
1178 $iv = substr($cb, -$block_size);
1179 $len%= $block_size;
1180 }
1181 if ($len) {
1182 $iv = @mcrypt_generic($this->ecb, $iv);
1183 $plaintext.= $iv ^ substr($ciphertext, -$len);
1184 $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
1185 $pos = $len;
1186 }
1187
1188 return $plaintext;
1189 }
1190
1191 $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
1192
1193 if (!$this->continuousBuffer) {
1194 @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1195 }
1196
1197 return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1198 }
1199
1200 if ($this->changed) {
1201 $this->_setup();
1202 $this->changed = false;
1203 }
1204 if ($this->use_inline_crypt) {
1205 $inline = $this->inline_crypt;
1206 return $inline('decrypt', $this, $ciphertext);
1207 }
1208
1209 $block_size = $this->block_size;
1210
1211 $buffer = &$this->debuffer;
1212 $plaintext = '';
1213 switch ($this->mode) {
1214 case CRYPT_MODE_ECB:
1215 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1216 $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
1217 }
1218 break;
1219 case CRYPT_MODE_CBC:
1220 $xor = $this->decryptIV;
1221 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1222 $block = substr($ciphertext, $i, $block_size);
1223 $plaintext.= $this->_decryptBlock($block) ^ $xor;
1224 $xor = $block;
1225 }
1226 if ($this->continuousBuffer) {
1227 $this->decryptIV = $xor;
1228 }
1229 break;
1230 case CRYPT_MODE_CTR:
1231 $xor = $this->decryptIV;
1232 if (strlen($buffer['ciphertext'])) {
1233 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1234 $block = substr($ciphertext, $i, $block_size);
1235 if (strlen($block) > strlen($buffer['ciphertext'])) {
1236 $buffer['ciphertext'].= $this->_encryptBlock($xor);
1237 $this->_increment_str($xor);
1238 }
1239 $key = $this->_string_shift($buffer['ciphertext'], $block_size);
1240 $plaintext.= $block ^ $key;
1241 }
1242 } else {
1243 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1244 $block = substr($ciphertext, $i, $block_size);
1245 $key = $this->_encryptBlock($xor);
1246 $this->_increment_str($xor);
1247 $plaintext.= $block ^ $key;
1248 }
1249 }
1250 if ($this->continuousBuffer) {
1251 $this->decryptIV = $xor;
1252 if ($start = strlen($ciphertext) % $block_size) {
1253 $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1254 }
1255 }
1256 break;
1257 case CRYPT_MODE_CFB:
1258 if ($this->continuousBuffer) {
1259 $iv = &$this->decryptIV;
1260 $pos = &$buffer['pos'];
1261 } else {
1262 $iv = $this->decryptIV;
1263 $pos = 0;
1264 }
1265 $len = strlen($ciphertext);
1266 $i = 0;
1267 if ($pos) {
1268 $orig_pos = $pos;
1269 $max = $block_size - $pos;
1270 if ($len >= $max) {
1271 $i = $max;
1272 $len-= $max;
1273 $pos = 0;
1274 } else {
1275 $i = $len;
1276 $pos+= $len;
1277 $len = 0;
1278 }
1279 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1280 $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1281 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1282 }
1283 while ($len >= $block_size) {
1284 $iv = $this->_encryptBlock($iv);
1285 $cb = substr($ciphertext, $i, $block_size);
1286 $plaintext.= $iv ^ $cb;
1287 $iv = $cb;
1288 $len-= $block_size;
1289 $i+= $block_size;
1290 }
1291 if ($len) {
1292 $iv = $this->_encryptBlock($iv);
1293 $plaintext.= $iv ^ substr($ciphertext, $i);
1294 $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
1295 $pos = $len;
1296 }
1297 break;
1298 case CRYPT_MODE_OFB:
1299 $xor = $this->decryptIV;
1300 if (strlen($buffer['xor'])) {
1301 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1302 $block = substr($ciphertext, $i, $block_size);
1303 if (strlen($block) > strlen($buffer['xor'])) {
1304 $xor = $this->_encryptBlock($xor);
1305 $buffer['xor'].= $xor;
1306 }
1307 $key = $this->_string_shift($buffer['xor'], $block_size);
1308 $plaintext.= $block ^ $key;
1309 }
1310 } else {
1311 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1312 $xor = $this->_encryptBlock($xor);
1313 $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
1314 }
1315 $key = $xor;
1316 }
1317 if ($this->continuousBuffer) {
1318 $this->decryptIV = $xor;
1319 if ($start = strlen($ciphertext) % $block_size) {
1320 $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1321 }
1322 }
1323 break;
1324 case CRYPT_MODE_STREAM:
1325 $plaintext = $this->_decryptBlock($ciphertext);
1326 break;
1327 }
1328 return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1329 }
1330
1331 /**
1332 * OpenSSL CTR Processor
1333 *
1334 * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1335 * for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1336 * and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
1337 * function will emulate CTR with ECB when necessary.
1338 *
1339 * @see self::encrypt()
1340 * @see self::decrypt()
1341 * @param string $plaintext
1342 * @param string $encryptIV
1343 * @param array $buffer
1344 * @return string
1345 * @access private
1346 */
1347 function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
1348 {
1349 $ciphertext = '';
1350
1351 $block_size = $this->block_size;
1352 $key = $this->key;
1353
1354 if ($this->openssl_emulate_ctr) {
1355 $xor = $encryptIV;
1356 if (strlen($buffer['ciphertext'])) {
1357 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1358 $block = substr($plaintext, $i, $block_size);
1359 if (strlen($block) > strlen($buffer['ciphertext'])) {
1360 $result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1361 $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
1362 $buffer['ciphertext'].= $result;
1363 }
1364 $this->_increment_str($xor);
1365 $otp = $this->_string_shift($buffer['ciphertext'], $block_size);
1366 $ciphertext.= $block ^ $otp;
1367 }
1368 } else {
1369 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1370 $block = substr($plaintext, $i, $block_size);
1371 $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1372 $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
1373 $this->_increment_str($xor);
1374 $ciphertext.= $block ^ $otp;
1375 }
1376 }
1377 if ($this->continuousBuffer) {
1378 $encryptIV = $xor;
1379 if ($start = strlen($plaintext) % $block_size) {
1380 $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1381 }
1382 }
1383
1384 return $ciphertext;
1385 }
1386
1387 if (strlen($buffer['ciphertext'])) {
1388 $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
1389 $plaintext = substr($plaintext, strlen($ciphertext));
1390
1391 if (!strlen($plaintext)) {
1392 return $ciphertext;
1393 }
1394 }
1395
1396 $overflow = strlen($plaintext) % $block_size;
1397 if ($overflow) {
1398 $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
1399 $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1400 $temp = $this->_string_pop($encrypted, $block_size);
1401 $ciphertext.= $encrypted . ($plaintext2 ^ $temp);
1402 if ($this->continuousBuffer) {
1403 $buffer['ciphertext'] = substr($temp, $overflow);
1404 $encryptIV = $temp;
1405 }
1406 } elseif (!strlen($buffer['ciphertext'])) {
1407 $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1408 $temp = $this->_string_pop($ciphertext, $block_size);
1409 if ($this->continuousBuffer) {
1410 $encryptIV = $temp;
1411 }
1412 }
1413 if ($this->continuousBuffer) {
1414 if (!defined('OPENSSL_RAW_DATA')) {
1415 $encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1416 }
1417 $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1418 if ($overflow) {
1419 $this->_increment_str($encryptIV);
1420 }
1421 }
1422
1423 return $ciphertext;
1424 }
1425
1426 /**
1427 * OpenSSL OFB Processor
1428 *
1429 * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1430 * for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1431 * and Crypt_Base::decrypt().
1432 *
1433 * @see self::encrypt()
1434 * @see self::decrypt()
1435 * @param string $plaintext
1436 * @param string $encryptIV
1437 * @param array $buffer
1438 * @return string
1439 * @access private
1440 */
1441 function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
1442 {
1443 if (strlen($buffer['xor'])) {
1444 $ciphertext = $plaintext ^ $buffer['xor'];
1445 $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
1446 $plaintext = substr($plaintext, strlen($ciphertext));
1447 } else {
1448 $ciphertext = '';
1449 }
1450
1451 $block_size = $this->block_size;
1452
1453 $len = strlen($plaintext);
1454 $key = $this->key;
1455 $overflow = $len % $block_size;
1456
1457 if (strlen($plaintext)) {
1458 if ($overflow) {
1459 $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1460 $xor = $this->_string_pop($ciphertext, $block_size);
1461 if ($this->continuousBuffer) {
1462 $encryptIV = $xor;
1463 }
1464 $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
1465 if ($this->continuousBuffer) {
1466 $buffer['xor'] = $xor;
1467 }
1468 } else {
1469 $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1470 if ($this->continuousBuffer) {
1471 $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
1472 }
1473 }
1474 }
1475
1476 return $ciphertext;
1477 }
1478
1479 /**
1480 * phpseclib <-> OpenSSL Mode Mapper
1481 *
1482 * May need to be overwritten by classes extending this one in some cases
1483 *
1484 * @return int
1485 * @access private
1486 */
1487 function _openssl_translate_mode()
1488 {
1489 switch ($this->mode) {
1490 case CRYPT_MODE_ECB:
1491 return 'ecb';
1492 case CRYPT_MODE_CBC:
1493 return 'cbc';
1494 case CRYPT_MODE_CTR:
1495 return 'ctr';
1496 case CRYPT_MODE_CFB:
1497 return 'cfb';
1498 case CRYPT_MODE_OFB:
1499 return 'ofb';
1500 }
1501 }
1502
1503 /**
1504 * Pad "packets".
1505 *
1506 * Block ciphers working by encrypting between their specified [$this->]block_size at a time
1507 * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
1508 * pad the input so that it is of the proper length.
1509 *
1510 * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
1511 * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
1512 * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
1513 * transmitted separately)
1514 *
1515 * @see self::disablePadding()
1516 * @access public
1517 */
1518 function enablePadding()
1519 {
1520 $this->padding = true;
1521 }
1522
1523 /**
1524 * Do not pad packets.
1525 *
1526 * @see self::enablePadding()
1527 * @access public
1528 */
1529 function disablePadding()
1530 {
1531 $this->padding = false;
1532 }
1533
1534 /**
1535 * Treat consecutive "packets" as if they are a continuous buffer.
1536 *
1537 * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
1538 * will yield different outputs:
1539 *
1540 * <code>
1541 * echo $rijndael->encrypt(substr($plaintext, 0, 16));
1542 * echo $rijndael->encrypt(substr($plaintext, 16, 16));
1543 * </code>
1544 * <code>
1545 * echo $rijndael->encrypt($plaintext);
1546 * </code>
1547 *
1548 * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
1549 * another, as demonstrated with the following:
1550 *
1551 * <code>
1552 * $rijndael->encrypt(substr($plaintext, 0, 16));
1553 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1554 * </code>
1555 * <code>
1556 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1557 * </code>
1558 *
1559 * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
1560 * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
1561 * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
1562 *
1563 * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
1564 * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
1565 * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
1566 * however, they are also less intuitive and more likely to cause you problems.
1567 *
1568 * @see self::disableContinuousBuffer()
1569 * @access public
1570 * @internal Could, but not must, extend by the child Crypt_* class
1571 */
1572 function enableContinuousBuffer()
1573 {
1574 if ($this->mode == CRYPT_MODE_ECB) {
1575 return;
1576 }
1577
1578 $this->continuousBuffer = true;
1579
1580 $this->_setEngine();
1581 }
1582
1583 /**
1584 * Treat consecutive packets as if they are a discontinuous buffer.
1585 *
1586 * The default behavior.
1587 *
1588 * @see self::enableContinuousBuffer()
1589 * @access public
1590 * @internal Could, but not must, extend by the child Crypt_* class
1591 */
1592 function disableContinuousBuffer()
1593 {
1594 if ($this->mode == CRYPT_MODE_ECB) {
1595 return;
1596 }
1597 if (!$this->continuousBuffer) {
1598 return;
1599 }
1600
1601 $this->continuousBuffer = false;
1602 $this->changed = true;
1603
1604 $this->_setEngine();
1605 }
1606
1607 /**
1608 * Test for engine validity
1609 *
1610 * @see self::Crypt_Base()
1611 * @param int $engine
1612 * @access public
1613 * @return bool
1614 */
1615 function isValidEngine($engine)
1616 {
1617 switch ($engine) {
1618 case CRYPT_ENGINE_OPENSSL:
1619 if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) {
1620 return false;
1621 }
1622 $this->openssl_emulate_ctr = false;
1623 $result = $this->cipher_name_openssl &&
1624 extension_loaded('openssl') &&
1625 // PHP 5.3.0 - 5.3.2 did not let you set IV's
1626 version_compare(PHP_VERSION, '5.3.3', '>=');
1627 if (!$result) {
1628 return false;
1629 }
1630
1631 // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
1632 // $options openssl_encrypt expected a boolean $raw_data.
1633 if (!defined('OPENSSL_RAW_DATA')) {
1634 $this->openssl_options = true;
1635 } else {
1636 $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
1637 }
1638
1639 $methods = openssl_get_cipher_methods();
1640 if (in_array($this->cipher_name_openssl, $methods)) {
1641 return true;
1642 }
1643 // not all of openssl's symmetric cipher's support ctr. for those
1644 // that don't we'll emulate it
1645 switch ($this->mode) {
1646 case CRYPT_MODE_CTR:
1647 if (in_array($this->cipher_name_openssl_ecb, $methods)) {
1648 $this->openssl_emulate_ctr = true;
1649 return true;
1650 }
1651 }
1652 return false;
1653 case CRYPT_ENGINE_MCRYPT:
1654 return $this->cipher_name_mcrypt &&
1655 extension_loaded('mcrypt') &&
1656 in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
1657 case CRYPT_ENGINE_INTERNAL:
1658 return true;
1659 }
1660
1661 return false;
1662 }
1663
1664 /**
1665 * Sets the preferred crypt engine
1666 *
1667 * Currently, $engine could be:
1668 *
1669 * - CRYPT_ENGINE_OPENSSL [very fast]
1670 *
1671 * - CRYPT_ENGINE_MCRYPT [fast]
1672 *
1673 * - CRYPT_ENGINE_INTERNAL [slow]
1674 *
1675 * If the preferred crypt engine is not available the fastest available one will be used
1676 *
1677 * @see self::Crypt_Base()
1678 * @param int $engine
1679 * @access public
1680 */
1681 function setPreferredEngine($engine)
1682 {
1683 switch ($engine) {
1684 //case CRYPT_ENGINE_OPENSSL:
1685 case CRYPT_ENGINE_MCRYPT:
1686 case CRYPT_ENGINE_INTERNAL:
1687 $this->preferredEngine = $engine;
1688 break;
1689 default:
1690 $this->preferredEngine = CRYPT_ENGINE_OPENSSL;
1691 }
1692
1693 $this->_setEngine();
1694 }
1695
1696 /**
1697 * Returns the engine currently being utilized
1698 *
1699 * @see self::_setEngine()
1700 * @access public
1701 */
1702 function getEngine()
1703 {
1704 return $this->engine;
1705 }
1706
1707 /**
1708 * Sets the engine as appropriate
1709 *
1710 * @see self::Crypt_Base()
1711 * @access private
1712 */
1713 function _setEngine()
1714 {
1715 $this->engine = null;
1716
1717 $candidateEngines = array(
1718 $this->preferredEngine,
1719 CRYPT_ENGINE_OPENSSL,
1720 CRYPT_ENGINE_MCRYPT
1721 );
1722 foreach ($candidateEngines as $engine) {
1723 if ($this->isValidEngine($engine)) {
1724 $this->engine = $engine;
1725 break;
1726 }
1727 }
1728 if (!$this->engine) {
1729 $this->engine = CRYPT_ENGINE_INTERNAL;
1730 }
1731
1732 if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) {
1733 // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
1734 // (re)open them with the module named in $this->cipher_name_mcrypt
1735 @mcrypt_module_close($this->enmcrypt);
1736 @mcrypt_module_close($this->demcrypt);
1737 $this->enmcrypt = null;
1738 $this->demcrypt = null;
1739
1740 if ($this->ecb) {
1741 @mcrypt_module_close($this->ecb);
1742 $this->ecb = null;
1743 }
1744 }
1745
1746 $this->changed = true;
1747 }
1748
1749 /**
1750 * Encrypts a block
1751 *
1752 * @access private
1753 * @param string $in
1754 * @return string
1755 * @internal Must be extended by the child Crypt_* class
1756 */
1757 function _encryptBlock($in)
1758 {
1759 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1760 }
1761
1762 /**
1763 * Decrypts a block
1764 *
1765 * @access private
1766 * @param string $in
1767 * @return string
1768 * @internal Must be extended by the child Crypt_* class
1769 */
1770 function _decryptBlock($in)
1771 {
1772 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1773 }
1774
1775 /**
1776 * Setup the key (expansion)
1777 *
1778 * Only used if $engine == CRYPT_ENGINE_INTERNAL
1779 *
1780 * @see self::_setup()
1781 * @access private
1782 * @internal Must be extended by the child Crypt_* class
1783 */
1784 function _setupKey()
1785 {
1786 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1787 }
1788
1789 /**
1790 * Setup the CRYPT_ENGINE_INTERNAL $engine
1791 *
1792 * (re)init, if necessary, the internal cipher $engine and flush all $buffers
1793 * Used (only) if $engine == CRYPT_ENGINE_INTERNAL
1794 *
1795 * _setup() will be called each time if $changed === true
1796 * typically this happens when using one or more of following public methods:
1797 *
1798 * - setKey()
1799 *
1800 * - setIV()
1801 *
1802 * - disableContinuousBuffer()
1803 *
1804 * - First run of encrypt() / decrypt() with no init-settings
1805 *
1806 * @see self::setKey()
1807 * @see self::setIV()
1808 * @see self::disableContinuousBuffer()
1809 * @access private
1810 * @internal _setup() is always called before en/decryption.
1811 * @internal Could, but not must, extend by the child Crypt_* class
1812 */
1813 function _setup()
1814 {
1815 $this->_clearBuffers();
1816 $this->_setupKey();
1817
1818 if ($this->use_inline_crypt) {
1819 $this->_setupInlineCrypt();
1820 }
1821 }
1822
1823 /**
1824 * Setup the CRYPT_ENGINE_MCRYPT $engine
1825 *
1826 * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
1827 * Used (only) if $engine = CRYPT_ENGINE_MCRYPT
1828 *
1829 * _setupMcrypt() will be called each time if $changed === true
1830 * typically this happens when using one or more of following public methods:
1831 *
1832 * - setKey()
1833 *
1834 * - setIV()
1835 *
1836 * - disableContinuousBuffer()
1837 *
1838 * - First run of encrypt() / decrypt()
1839 *
1840 * @see self::setKey()
1841 * @see self::setIV()
1842 * @see self::disableContinuousBuffer()
1843 * @access private
1844 * @internal Could, but not must, extend by the child Crypt_* class
1845 */
1846 function _setupMcrypt()
1847 {
1848 $this->_clearBuffers();
1849 $this->enchanged = $this->dechanged = true;
1850
1851 if (!isset($this->enmcrypt)) {
1852 static $mcrypt_modes = array(
1853 CRYPT_MODE_CTR => 'ctr',
1854 CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
1855 CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
1856 CRYPT_MODE_CFB => 'ncfb',
1857 CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
1858 CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
1859 );
1860
1861 $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1862 $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1863
1864 // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
1865 // to workaround mcrypt's broken ncfb implementation in buffered mode
1866 // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
1867 if ($this->mode == CRYPT_MODE_CFB) {
1868 $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
1869 }
1870 } // else should mcrypt_generic_deinit be called?
1871
1872 if ($this->mode == CRYPT_MODE_CFB) {
1873 @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
1874 }
1875 }
1876
1877 /**
1878 * Pads a string
1879 *
1880 * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
1881 * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
1882 * chr($this->block_size - (strlen($text) % $this->block_size)
1883 *
1884 * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
1885 * and padding will, hence forth, be enabled.
1886 *
1887 * @see self::_unpad()
1888 * @param string $text
1889 * @access private
1890 * @return string
1891 */
1892 function _pad($text)
1893 {
1894 $length = strlen($text);
1895
1896 if (!$this->padding) {
1897 if ($length % $this->block_size == 0) {
1898 return $text;
1899 } else {
1900 user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
1901 $this->padding = true;
1902 }
1903 }
1904
1905 $pad = $this->block_size - ($length % $this->block_size);
1906
1907 return str_pad($text, $length + $pad, chr($pad));
1908 }
1909
1910 /**
1911 * Unpads a string.
1912 *
1913 * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
1914 * and false will be returned.
1915 *
1916 * @see self::_pad()
1917 * @param string $text
1918 * @access private
1919 * @return string
1920 */
1921 function _unpad($text)
1922 {
1923 if (!$this->padding) {
1924 return $text;
1925 }
1926
1927 $length = ord($text[strlen($text) - 1]);
1928
1929 if (!$length || $length > $this->block_size) {
1930 return false;
1931 }
1932
1933 return substr($text, 0, -$length);
1934 }
1935
1936 /**
1937 * Clears internal buffers
1938 *
1939 * Clearing/resetting the internal buffers is done everytime
1940 * after disableContinuousBuffer() or on cipher $engine (re)init
1941 * ie after setKey() or setIV()
1942 *
1943 * @access public
1944 * @internal Could, but not must, extend by the child Crypt_* class
1945 */
1946 function _clearBuffers()
1947 {
1948 $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
1949
1950 // mcrypt's handling of invalid's $iv:
1951 // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
1952 $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
1953
1954 if (!$this->skip_key_adjustment) {
1955 $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
1956 }
1957 }
1958
1959 /**
1960 * String Shift
1961 *
1962 * Inspired by array_shift
1963 *
1964 * @param string $string
1965 * @param int $index
1966 * @access private
1967 * @return string
1968 */
1969 function _string_shift(&$string, $index = 1)
1970 {
1971 $substr = substr($string, 0, $index);
1972 $string = substr($string, $index);
1973 return $substr;
1974 }
1975
1976 /**
1977 * String Pop
1978 *
1979 * Inspired by array_pop
1980 *
1981 * @param string $string
1982 * @param int $index
1983 * @access private
1984 * @return string
1985 */
1986 function _string_pop(&$string, $index = 1)
1987 {
1988 $substr = substr($string, -$index);
1989 $string = substr($string, 0, -$index);
1990 return $substr;
1991 }
1992
1993 /**
1994 * Increment the current string
1995 *
1996 * @see self::decrypt()
1997 * @see self::encrypt()
1998 * @param string $var
1999 * @access private
2000 */
2001 function _increment_str(&$var)
2002 {
2003 for ($i = 4; $i <= strlen($var); $i+= 4) {
2004 $temp = substr($var, -$i, 4);
2005 switch ($temp) {
2006 case "\xFF\xFF\xFF\xFF":
2007 $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
2008 break;
2009 case "\x7F\xFF\xFF\xFF":
2010 $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
2011 return;
2012 default:
2013 $temp = unpack('Nnum', $temp);
2014 $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
2015 return;
2016 }
2017 }
2018
2019 $remainder = strlen($var) % 4;
2020
2021 if ($remainder == 0) {
2022 return;
2023 }
2024
2025 $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
2026 $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
2027 $var = substr_replace($var, $temp, 0, $remainder);
2028 }
2029
2030 /**
2031 * Setup the performance-optimized function for de/encrypt()
2032 *
2033 * Stores the created (or existing) callback function-name
2034 * in $this->inline_crypt
2035 *
2036 * Internally for phpseclib developers:
2037 *
2038 * _setupInlineCrypt() would be called only if:
2039 *
2040 * - $engine == CRYPT_ENGINE_INTERNAL and
2041 *
2042 * - $use_inline_crypt === true
2043 *
2044 * - each time on _setup(), after(!) _setupKey()
2045 *
2046 *
2047 * This ensures that _setupInlineCrypt() has always a
2048 * full ready2go initializated internal cipher $engine state
2049 * where, for example, the keys allready expanded,
2050 * keys/block_size calculated and such.
2051 *
2052 * It is, each time if called, the responsibility of _setupInlineCrypt():
2053 *
2054 * - to set $this->inline_crypt to a valid and fully working callback function
2055 * as a (faster) replacement for encrypt() / decrypt()
2056 *
2057 * - NOT to create unlimited callback functions (for memory reasons!)
2058 * no matter how often _setupInlineCrypt() would be called. At some
2059 * point of amount they must be generic re-useable.
2060 *
2061 * - the code of _setupInlineCrypt() it self,
2062 * and the generated callback code,
2063 * must be, in following order:
2064 * - 100% safe
2065 * - 100% compatible to encrypt()/decrypt()
2066 * - using only php5+ features/lang-constructs/php-extensions if
2067 * compatibility (down to php4) or fallback is provided
2068 * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
2069 * - >= 10% faster than encrypt()/decrypt() [which is, by the way,
2070 * the reason for the existence of _setupInlineCrypt() :-)]
2071 * - memory-nice
2072 * - short (as good as possible)
2073 *
2074 * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
2075 * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
2076 * - The following variable names are reserved:
2077 * - $_* (all variable names prefixed with an underscore)
2078 * - $self (object reference to it self. Do not use $this, but $self instead)
2079 * - $in (the content of $in has to en/decrypt by the generated code)
2080 * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
2081 *
2082 *
2083 * @see self::_setup()
2084 * @see self::_createInlineCryptFunction()
2085 * @see self::encrypt()
2086 * @see self::decrypt()
2087 * @access private
2088 * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
2089 */
2090 function _setupInlineCrypt()
2091 {
2092 // If, for any reason, an extending Crypt_Base() Crypt_* class
2093 // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
2094 // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
2095 // in the constructor at object instance-time
2096 // or, if it's runtime-specific, at runtime
2097
2098 $this->use_inline_crypt = false;
2099 }
2100
2101 /**
2102 * Creates the performance-optimized function for en/decrypt()
2103 *
2104 * Internally for phpseclib developers:
2105 *
2106 * _createInlineCryptFunction():
2107 *
2108 * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
2109 * with the current [$this->]mode of operation code
2110 *
2111 * - create the $inline function, which called by encrypt() / decrypt()
2112 * as its replacement to speed up the en/decryption operations.
2113 *
2114 * - return the name of the created $inline callback function
2115 *
2116 * - used to speed up en/decryption
2117 *
2118 *
2119 *
2120 * The main reason why can speed up things [up to 50%] this way are:
2121 *
2122 * - using variables more effective then regular.
2123 * (ie no use of expensive arrays but integers $k_0, $k_1 ...
2124 * or even, for example, the pure $key[] values hardcoded)
2125 *
2126 * - avoiding 1000's of function calls of ie _encryptBlock()
2127 * but inlining the crypt operations.
2128 * in the mode of operation for() loop.
2129 *
2130 * - full loop unroll the (sometimes key-dependent) rounds
2131 * avoiding this way ++$i counters and runtime-if's etc...
2132 *
2133 * The basic code architectur of the generated $inline en/decrypt()
2134 * lambda function, in pseudo php, is:
2135 *
2136 * <code>
2137 * +----------------------------------------------------------------------------------------------+
2138 * | callback $inline = create_function: |
2139 * | lambda_function_0001_crypt_ECB($action, $text) |
2140 * | { |
2141 * | INSERT PHP CODE OF: |
2142 * | $cipher_code['init_crypt']; // general init code. |
2143 * | // ie: $sbox'es declarations used for |
2144 * | // encrypt and decrypt'ing. |
2145 * | |
2146 * | switch ($action) { |
2147 * | case 'encrypt': |
2148 * | INSERT PHP CODE OF: |
2149 * | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
2150 * | ie: specified $key or $box |
2151 * | declarations for encrypt'ing. |
2152 * | |
2153 * | foreach ($ciphertext) { |
2154 * | $in = $block_size of $ciphertext; |
2155 * | |
2156 * | INSERT PHP CODE OF: |
2157 * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
2158 * | // strlen($in) == $this->block_size |
2159 * | // here comes the cipher algorithm in action |
2160 * | // for encryption. |
2161 * | // $cipher_code['encrypt_block'] has to |
2162 * | // encrypt the content of the $in variable |
2163 * | |
2164 * | $plaintext .= $in; |
2165 * | } |
2166 * | return $plaintext; |
2167 * | |
2168 * | case 'decrypt': |
2169 * | INSERT PHP CODE OF: |
2170 * | $cipher_code['init_decrypt']; // decrypt sepcific init code |
2171 * | ie: specified $key or $box |
2172 * | declarations for decrypt'ing. |
2173 * | foreach ($plaintext) { |
2174 * | $in = $block_size of $plaintext; |
2175 * | |
2176 * | INSERT PHP CODE OF: |
2177 * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
2178 * | // strlen($in) == $this->block_size |
2179 * | // here comes the cipher algorithm in action |
2180 * | // for decryption. |
2181 * | // $cipher_code['decrypt_block'] has to |
2182 * | // decrypt the content of the $in variable |
2183 * | $ciphertext .= $in; |
2184 * | } |
2185 * | return $ciphertext; |
2186 * | } |
2187 * | } |
2188 * +----------------------------------------------------------------------------------------------+
2189 * </code>
2190 *
2191 * See also the Crypt_*::_setupInlineCrypt()'s for
2192 * productive inline $cipher_code's how they works.
2193 *
2194 * Structure of:
2195 * <code>
2196 * $cipher_code = array(
2197 * 'init_crypt' => (string) '', // optional
2198 * 'init_encrypt' => (string) '', // optional
2199 * 'init_decrypt' => (string) '', // optional
2200 * 'encrypt_block' => (string) '', // required
2201 * 'decrypt_block' => (string) '' // required
2202 * );
2203 * </code>
2204 *
2205 * @see self::_setupInlineCrypt()
2206 * @see self::encrypt()
2207 * @see self::decrypt()
2208 * @param array $cipher_code
2209 * @access private
2210 * @return string (the name of the created callback function)
2211 */
2212 function _createInlineCryptFunction($cipher_code)
2213 {
2214 $block_size = $this->block_size;
2215
2216 // optional
2217 $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
2218 $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
2219 $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
2220 // required
2221 $encrypt_block = $cipher_code['encrypt_block'];
2222 $decrypt_block = $cipher_code['decrypt_block'];
2223
2224 // Generating mode of operation inline code,
2225 // merged with the $cipher_code algorithm
2226 // for encrypt- and decryption.
2227 switch ($this->mode) {
2228 case CRYPT_MODE_ECB:
2229 $encrypt = $init_encrypt . '
2230 $_ciphertext = "";
2231 $_plaintext_len = strlen($_text);
2232
2233 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2234 $in = substr($_text, $_i, '.$block_size.');
2235 '.$encrypt_block.'
2236 $_ciphertext.= $in;
2237 }
2238
2239 return $_ciphertext;
2240 ';
2241
2242 $decrypt = $init_decrypt . '
2243 $_plaintext = "";
2244 $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2245 $_ciphertext_len = strlen($_text);
2246
2247 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2248 $in = substr($_text, $_i, '.$block_size.');
2249 '.$decrypt_block.'
2250 $_plaintext.= $in;
2251 }
2252
2253 return $self->_unpad($_plaintext);
2254 ';
2255 break;
2256 case CRYPT_MODE_CTR:
2257 $encrypt = $init_encrypt . '
2258 $_ciphertext = "";
2259 $_plaintext_len = strlen($_text);
2260 $_xor = $self->encryptIV;
2261 $_buffer = &$self->enbuffer;
2262 if (strlen($_buffer["ciphertext"])) {
2263 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2264 $_block = substr($_text, $_i, '.$block_size.');
2265 if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2266 $in = $_xor;
2267 '.$encrypt_block.'
2268 $self->_increment_str($_xor);
2269 $_buffer["ciphertext"].= $in;
2270 }
2271 $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2272 $_ciphertext.= $_block ^ $_key;
2273 }
2274 } else {
2275 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2276 $_block = substr($_text, $_i, '.$block_size.');
2277 $in = $_xor;
2278 '.$encrypt_block.'
2279 $self->_increment_str($_xor);
2280 $_key = $in;
2281 $_ciphertext.= $_block ^ $_key;
2282 }
2283 }
2284 if ($self->continuousBuffer) {
2285 $self->encryptIV = $_xor;
2286 if ($_start = $_plaintext_len % '.$block_size.') {
2287 $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2288 }
2289 }
2290
2291 return $_ciphertext;
2292 ';
2293
2294 $decrypt = $init_encrypt . '
2295 $_plaintext = "";
2296 $_ciphertext_len = strlen($_text);
2297 $_xor = $self->decryptIV;
2298 $_buffer = &$self->debuffer;
2299
2300 if (strlen($_buffer["ciphertext"])) {
2301 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2302 $_block = substr($_text, $_i, '.$block_size.');
2303 if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2304 $in = $_xor;
2305 '.$encrypt_block.'
2306 $self->_increment_str($_xor);
2307 $_buffer["ciphertext"].= $in;
2308 }
2309 $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2310 $_plaintext.= $_block ^ $_key;
2311 }
2312 } else {
2313 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2314 $_block = substr($_text, $_i, '.$block_size.');
2315 $in = $_xor;
2316 '.$encrypt_block.'
2317 $self->_increment_str($_xor);
2318 $_key = $in;
2319 $_plaintext.= $_block ^ $_key;
2320 }
2321 }
2322 if ($self->continuousBuffer) {
2323 $self->decryptIV = $_xor;
2324 if ($_start = $_ciphertext_len % '.$block_size.') {
2325 $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2326 }
2327 }
2328
2329 return $_plaintext;
2330 ';
2331 break;
2332 case CRYPT_MODE_CFB:
2333 $encrypt = $init_encrypt . '
2334 $_ciphertext = "";
2335 $_buffer = &$self->enbuffer;
2336
2337 if ($self->continuousBuffer) {
2338 $_iv = &$self->encryptIV;
2339 $_pos = &$_buffer["pos"];
2340 } else {
2341 $_iv = $self->encryptIV;
2342 $_pos = 0;
2343 }
2344 $_len = strlen($_text);
2345 $_i = 0;
2346 if ($_pos) {
2347 $_orig_pos = $_pos;
2348 $_max = '.$block_size.' - $_pos;
2349 if ($_len >= $_max) {
2350 $_i = $_max;
2351 $_len-= $_max;
2352 $_pos = 0;
2353 } else {
2354 $_i = $_len;
2355 $_pos+= $_len;
2356 $_len = 0;
2357 }
2358 $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
2359 $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
2360 }
2361 while ($_len >= '.$block_size.') {
2362 $in = $_iv;
2363 '.$encrypt_block.';
2364 $_iv = $in ^ substr($_text, $_i, '.$block_size.');
2365 $_ciphertext.= $_iv;
2366 $_len-= '.$block_size.';
2367 $_i+= '.$block_size.';
2368 }
2369 if ($_len) {
2370 $in = $_iv;
2371 '.$encrypt_block.'
2372 $_iv = $in;
2373 $_block = $_iv ^ substr($_text, $_i);
2374 $_iv = substr_replace($_iv, $_block, 0, $_len);
2375 $_ciphertext.= $_block;
2376 $_pos = $_len;
2377 }
2378 return $_ciphertext;
2379 ';
2380
2381 $decrypt = $init_encrypt . '
2382 $_plaintext = "";
2383 $_buffer = &$self->debuffer;
2384
2385 if ($self->continuousBuffer) {
2386 $_iv = &$self->decryptIV;
2387 $_pos = &$_buffer["pos"];
2388 } else {
2389 $_iv = $self->decryptIV;
2390 $_pos = 0;
2391 }
2392 $_len = strlen($_text);
2393 $_i = 0;
2394 if ($_pos) {
2395 $_orig_pos = $_pos;
2396 $_max = '.$block_size.' - $_pos;
2397 if ($_len >= $_max) {
2398 $_i = $_max;
2399 $_len-= $_max;
2400 $_pos = 0;
2401 } else {
2402 $_i = $_len;
2403 $_pos+= $_len;
2404 $_len = 0;
2405 }
2406 $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
2407 $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
2408 }
2409 while ($_len >= '.$block_size.') {
2410 $in = $_iv;
2411 '.$encrypt_block.'
2412 $_iv = $in;
2413 $cb = substr($_text, $_i, '.$block_size.');
2414 $_plaintext.= $_iv ^ $cb;
2415 $_iv = $cb;
2416 $_len-= '.$block_size.';
2417 $_i+= '.$block_size.';
2418 }
2419 if ($_len) {
2420 $in = $_iv;
2421 '.$encrypt_block.'
2422 $_iv = $in;
2423 $_plaintext.= $_iv ^ substr($_text, $_i);
2424 $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
2425 $_pos = $_len;
2426 }
2427
2428 return $_plaintext;
2429 ';
2430 break;
2431 case CRYPT_MODE_OFB:
2432 $encrypt = $init_encrypt . '
2433 $_ciphertext = "";
2434 $_plaintext_len = strlen($_text);
2435 $_xor = $self->encryptIV;
2436 $_buffer = &$self->enbuffer;
2437
2438 if (strlen($_buffer["xor"])) {
2439 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2440 $_block = substr($_text, $_i, '.$block_size.');
2441 if (strlen($_block) > strlen($_buffer["xor"])) {
2442 $in = $_xor;
2443 '.$encrypt_block.'
2444 $_xor = $in;
2445 $_buffer["xor"].= $_xor;
2446 }
2447 $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2448 $_ciphertext.= $_block ^ $_key;
2449 }
2450 } else {
2451 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2452 $in = $_xor;
2453 '.$encrypt_block.'
2454 $_xor = $in;
2455 $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2456 }
2457 $_key = $_xor;
2458 }
2459 if ($self->continuousBuffer) {
2460 $self->encryptIV = $_xor;
2461 if ($_start = $_plaintext_len % '.$block_size.') {
2462 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2463 }
2464 }
2465 return $_ciphertext;
2466 ';
2467
2468 $decrypt = $init_encrypt . '
2469 $_plaintext = "";
2470 $_ciphertext_len = strlen($_text);
2471 $_xor = $self->decryptIV;
2472 $_buffer = &$self->debuffer;
2473
2474 if (strlen($_buffer["xor"])) {
2475 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2476 $_block = substr($_text, $_i, '.$block_size.');
2477 if (strlen($_block) > strlen($_buffer["xor"])) {
2478 $in = $_xor;
2479 '.$encrypt_block.'
2480 $_xor = $in;
2481 $_buffer["xor"].= $_xor;
2482 }
2483 $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2484 $_plaintext.= $_block ^ $_key;
2485 }
2486 } else {
2487 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2488 $in = $_xor;
2489 '.$encrypt_block.'
2490 $_xor = $in;
2491 $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2492 }
2493 $_key = $_xor;
2494 }
2495 if ($self->continuousBuffer) {
2496 $self->decryptIV = $_xor;
2497 if ($_start = $_ciphertext_len % '.$block_size.') {
2498 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2499 }
2500 }
2501 return $_plaintext;
2502 ';
2503 break;
2504 case CRYPT_MODE_STREAM:
2505 $encrypt = $init_encrypt . '
2506 $_ciphertext = "";
2507 '.$encrypt_block.'
2508 return $_ciphertext;
2509 ';
2510 $decrypt = $init_decrypt . '
2511 $_plaintext = "";
2512 '.$decrypt_block.'
2513 return $_plaintext;
2514 ';
2515 break;
2516 // case CRYPT_MODE_CBC:
2517 default:
2518 $encrypt = $init_encrypt . '
2519 $_ciphertext = "";
2520 $_plaintext_len = strlen($_text);
2521
2522 $in = $self->encryptIV;
2523
2524 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2525 $in = substr($_text, $_i, '.$block_size.') ^ $in;
2526 '.$encrypt_block.'
2527 $_ciphertext.= $in;
2528 }
2529
2530 if ($self->continuousBuffer) {
2531 $self->encryptIV = $in;
2532 }
2533
2534 return $_ciphertext;
2535 ';
2536
2537 $decrypt = $init_decrypt . '
2538 $_plaintext = "";
2539 $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2540 $_ciphertext_len = strlen($_text);
2541
2542 $_iv = $self->decryptIV;
2543
2544 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2545 $in = $_block = substr($_text, $_i, '.$block_size.');
2546 '.$decrypt_block.'
2547 $_plaintext.= $in ^ $_iv;
2548 $_iv = $_block;
2549 }
2550
2551 if ($self->continuousBuffer) {
2552 $self->decryptIV = $_iv;
2553 }
2554
2555 return $self->_unpad($_plaintext);
2556 ';
2557 break;
2558 }
2559
2560 // Create the $inline function and return its name as string. Ready to run!
2561 if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
2562 eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
2563 return $func;
2564 }
2565
2566 return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
2567 }
2568
2569 /**
2570 * Holds the lambda_functions table (classwide)
2571 *
2572 * Each name of the lambda function, created from
2573 * _setupInlineCrypt() && _createInlineCryptFunction()
2574 * is stored, classwide (!), here for reusing.
2575 *
2576 * The string-based index of $function is a classwide
2577 * unique value representing, at least, the $mode of
2578 * operation (or more... depends of the optimizing level)
2579 * for which $mode the lambda function was created.
2580 *
2581 * @access private
2582 * @return array &$functions
2583 */
2584 function &_getLambdaFunctions()
2585 {
2586 static $functions = array();
2587 return $functions;
2588 }
2589
2590 /**
2591 * Generates a digest from $bytes
2592 *
2593 * @see self::_setupInlineCrypt()
2594 * @access private
2595 * @param $bytes
2596 * @return string
2597 */
2598 function _hashInlineCryptFunction($bytes)
2599 {
2600 if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) {
2601 define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool', hash_algos())));
2602 }
2603
2604 $result = '';
2605 $hash = $bytes;
2606
2607 switch (true) {
2608 case CRYPT_BASE_WHIRLPOOL_AVAILABLE:
2609 foreach (str_split($bytes, 64) as $t) {
2610 $hash = hash('whirlpool', $hash, true);
2611 $result .= $t ^ $hash;
2612 }
2613 return $result . hash('whirlpool', $hash, true);
2614 default:
2615 $len = strlen($bytes);
2616 for ($i = 0; $i < $len; $i+=20) {
2617 $t = substr($bytes, $i, 20);
2618 $hash = pack('H*', sha1($hash));
2619 $result .= $t ^ $hash;
2620 }
2621 return $result . pack('H*', sha1($hash));
2622 }
2623 }
2624
2625 /**
2626 * Convert float to int
2627 *
2628 * On 32-bit Linux installs running PHP < 5.3 converting floats to ints doesn't always work
2629 *
2630 * @access private
2631 * @param string $x
2632 * @return int
2633 */
2634 function safe_intval($x)
2635 {
2636 switch (true) {
2637 case is_int($x):
2638 // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
2639 case version_compare(PHP_VERSION, '5.3.0') >= 0 && (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
2640 // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
2641 case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
2642 return $x;
2643 }
2644 return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
2645 ((fmod(floor($x / 0x80000000), 2) & 1) << 31);
2646 }
2647
2648 /**
2649 * eval()'able string for in-line float to int
2650 *
2651 * @access private
2652 * @return string
2653 */
2654 function safe_intval_inline()
2655 {
2656 // on 32-bit linux systems with PHP < 5.3 float to integer conversion is bad
2657 switch (true) {
2658 case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
2659 case version_compare(PHP_VERSION, '5.3.0') >= 0 && (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
2660 case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
2661 return '%s';
2662 break;
2663 default:
2664 $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
2665 return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
2666 }
2667 }
2668 }
2669