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