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