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