1<?php
2
3/**
4 * Base Class for all \phpseclib3\Crypt\* cipher classes
5 *
6 * PHP version 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 \phpseclib3\Crypt\* cipher class should extend \phpseclib3\Crypt\Common\SymmetricKey
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 \phpseclib3\Crypt\Common\SymmetricKey
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 * @author    Jim Wigginton <terrafrost@php.net>
29 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
30 * @copyright 2007 Jim Wigginton
31 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
32 * @link      http://phpseclib.sourceforge.net
33 */
34
35namespace phpseclib3\Crypt\Common;
36
37use phpseclib3\Common\Functions\Strings;
38use phpseclib3\Crypt\Blowfish;
39use phpseclib3\Crypt\Hash;
40use phpseclib3\Exception\BadDecryptionException;
41use phpseclib3\Exception\BadModeException;
42use phpseclib3\Exception\InconsistentSetupException;
43use phpseclib3\Exception\InsufficientSetupException;
44use phpseclib3\Exception\UnsupportedAlgorithmException;
45use phpseclib3\Math\BigInteger;
46use phpseclib3\Math\BinaryField;
47use phpseclib3\Math\PrimeField;
48
49/**
50 * Base Class for all \phpseclib3\Crypt\* cipher classes
51 *
52 * @author  Jim Wigginton <terrafrost@php.net>
53 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
54 */
55abstract class SymmetricKey
56{
57    /**
58     * Encrypt / decrypt using the Counter mode.
59     *
60     * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
61     *
62     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
63     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
64     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
65     */
66    const MODE_CTR = -1;
67    /**
68     * Encrypt / decrypt using the Electronic Code Book mode.
69     *
70     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
71     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
72     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
73     */
74    const MODE_ECB = 1;
75    /**
76     * Encrypt / decrypt using the Code Book Chaining mode.
77     *
78     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
79     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
80     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
81     */
82    const MODE_CBC = 2;
83    /**
84     * Encrypt / decrypt using the Cipher Feedback mode.
85     *
86     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
87     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
88     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
89     */
90    const MODE_CFB = 3;
91    /**
92     * Encrypt / decrypt using the Cipher Feedback mode (8bit)
93     *
94     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
95     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
96     */
97    const MODE_CFB8 = 7;
98    /**
99     * Encrypt / decrypt using the Output Feedback mode (8bit)
100     *
101     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
102     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
103     */
104    const MODE_OFB8 = 8;
105    /**
106     * Encrypt / decrypt using the Output Feedback mode.
107     *
108     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
109     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
110     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
111     */
112    const MODE_OFB = 4;
113    /**
114     * Encrypt / decrypt using Galois/Counter mode.
115     *
116     * @link https://en.wikipedia.org/wiki/Galois/Counter_Mode
117     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
118     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
119     */
120    const MODE_GCM = 5;
121    /**
122     * Encrypt / decrypt using streaming mode.
123     *
124     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
125     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
126     */
127    const MODE_STREAM = 6;
128
129    /**
130     * Mode Map
131     *
132     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
133     */
134    const MODE_MAP = [
135        'ctr'    => self::MODE_CTR,
136        'ecb'    => self::MODE_ECB,
137        'cbc'    => self::MODE_CBC,
138        'cfb'    => self::MODE_CFB,
139        'cfb8'   => self::MODE_CFB8,
140        'ofb'    => self::MODE_OFB,
141        'ofb8'   => self::MODE_OFB8,
142        'gcm'    => self::MODE_GCM,
143        'stream' => self::MODE_STREAM
144    ];
145
146    /**
147     * Base value for the internal implementation $engine switch
148     *
149     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
150     */
151    const ENGINE_INTERNAL = 1;
152    /**
153     * Base value for the eval() implementation $engine switch
154     *
155     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
156     */
157    const ENGINE_EVAL = 2;
158    /**
159     * Base value for the mcrypt implementation $engine switch
160     *
161     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
162     */
163    const ENGINE_MCRYPT = 3;
164    /**
165     * Base value for the openssl implementation $engine switch
166     *
167     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
168     */
169    const ENGINE_OPENSSL = 4;
170    /**
171     * Base value for the libsodium implementation $engine switch
172     *
173     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
174     */
175    const ENGINE_LIBSODIUM = 5;
176    /**
177     * Base value for the openssl / gcm implementation $engine switch
178     *
179     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
180     */
181    const ENGINE_OPENSSL_GCM = 6;
182
183    /**
184     * Engine Reverse Map
185     *
186     * @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine()
187     */
188    const ENGINE_MAP = [
189        self::ENGINE_INTERNAL    => 'PHP',
190        self::ENGINE_EVAL        => 'Eval',
191        self::ENGINE_MCRYPT      => 'mcrypt',
192        self::ENGINE_OPENSSL     => 'OpenSSL',
193        self::ENGINE_LIBSODIUM   => 'libsodium',
194        self::ENGINE_OPENSSL_GCM => 'OpenSSL (GCM)'
195    ];
196
197    /**
198     * The Encryption Mode
199     *
200     * @see self::__construct()
201     * @var int
202     */
203    protected $mode;
204
205    /**
206     * The Block Length of the block cipher
207     *
208     * @var int
209     */
210    protected $block_size = 16;
211
212    /**
213     * The Key
214     *
215     * @see self::setKey()
216     * @var string
217     */
218    protected $key = false;
219
220    /**
221     * HMAC Key
222     *
223     * @see self::setupGCM()
224     * @var ?string
225     */
226    protected $hKey = false;
227
228    /**
229     * The Initialization Vector
230     *
231     * @see self::setIV()
232     * @var string
233     */
234    protected $iv = false;
235
236    /**
237     * A "sliding" Initialization Vector
238     *
239     * @see self::enableContinuousBuffer()
240     * @see self::clearBuffers()
241     * @var string
242     */
243    protected $encryptIV;
244
245    /**
246     * A "sliding" Initialization Vector
247     *
248     * @see self::enableContinuousBuffer()
249     * @see self::clearBuffers()
250     * @var string
251     */
252    protected $decryptIV;
253
254    /**
255     * Continuous Buffer status
256     *
257     * @see self::enableContinuousBuffer()
258     * @var bool
259     */
260    protected $continuousBuffer = false;
261
262    /**
263     * Encryption buffer for CTR, OFB and CFB modes
264     *
265     * @see self::encrypt()
266     * @see self::clearBuffers()
267     * @var array
268     */
269    protected $enbuffer;
270
271    /**
272     * Decryption buffer for CTR, OFB and CFB modes
273     *
274     * @see self::decrypt()
275     * @see self::clearBuffers()
276     * @var array
277     */
278    protected $debuffer;
279
280    /**
281     * mcrypt resource for encryption
282     *
283     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
284     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
285     *
286     * @see self::encrypt()
287     * @var resource
288     */
289    private $enmcrypt;
290
291    /**
292     * mcrypt resource for decryption
293     *
294     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
295     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
296     *
297     * @see self::decrypt()
298     * @var resource
299     */
300    private $demcrypt;
301
302    /**
303     * Does the enmcrypt resource need to be (re)initialized?
304     *
305     * @see \phpseclib3\Crypt\Twofish::setKey()
306     * @see \phpseclib3\Crypt\Twofish::setIV()
307     * @var bool
308     */
309    private $enchanged = true;
310
311    /**
312     * Does the demcrypt resource need to be (re)initialized?
313     *
314     * @see \phpseclib3\Crypt\Twofish::setKey()
315     * @see \phpseclib3\Crypt\Twofish::setIV()
316     * @var bool
317     */
318    private $dechanged = true;
319
320    /**
321     * mcrypt resource for CFB mode
322     *
323     * mcrypt's CFB mode, in (and only in) buffered context,
324     * is broken, so phpseclib implements the CFB mode by it self,
325     * even when the mcrypt php extension is available.
326     *
327     * In order to do the CFB-mode work (fast) phpseclib
328     * use a separate ECB-mode mcrypt resource.
329     *
330     * @link http://phpseclib.sourceforge.net/cfb-demo.phps
331     * @see self::encrypt()
332     * @see self::decrypt()
333     * @see self::setupMcrypt()
334     * @var resource
335     */
336    private $ecb;
337
338    /**
339     * Optimizing value while CFB-encrypting
340     *
341     * Only relevant if $continuousBuffer enabled
342     * and $engine == self::ENGINE_MCRYPT
343     *
344     * It's faster to re-init $enmcrypt if
345     * $buffer bytes > $cfb_init_len than
346     * using the $ecb resource furthermore.
347     *
348     * This value depends of the chosen cipher
349     * and the time it would be needed for it's
350     * initialization [by mcrypt_generic_init()]
351     * which, typically, depends on the complexity
352     * on its internaly Key-expanding algorithm.
353     *
354     * @see self::encrypt()
355     * @var int
356     */
357    protected $cfb_init_len = 600;
358
359    /**
360     * Does internal cipher state need to be (re)initialized?
361     *
362     * @see self::setKey()
363     * @see self::setIV()
364     * @see self::disableContinuousBuffer()
365     * @var bool
366     */
367    protected $changed = true;
368
369    /**
370     * Does Eval engie need to be (re)initialized?
371     *
372     * @see self::setup()
373     * @var bool
374     */
375    protected $nonIVChanged = true;
376
377    /**
378     * Padding status
379     *
380     * @see self::enablePadding()
381     * @var bool
382     */
383    private $padding = true;
384
385    /**
386     * Is the mode one that is paddable?
387     *
388     * @see self::__construct()
389     * @var bool
390     */
391    private $paddable = false;
392
393    /**
394     * Holds which crypt engine internaly should be use,
395     * which will be determined automatically on __construct()
396     *
397     * Currently available $engines are:
398     * - self::ENGINE_LIBSODIUM   (very fast, php-extension: libsodium, extension_loaded('libsodium') required)
399     * - self::ENGINE_OPENSSL_GCM (very fast, php-extension: openssl, extension_loaded('openssl') required)
400     * - self::ENGINE_OPENSSL     (very fast, php-extension: openssl, extension_loaded('openssl') required)
401     * - self::ENGINE_MCRYPT      (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
402     * - self::ENGINE_EVAL        (medium, pure php-engine, no php-extension required)
403     * - self::ENGINE_INTERNAL    (slower, pure php-engine, no php-extension required)
404     *
405     * @see self::setEngine()
406     * @see self::encrypt()
407     * @see self::decrypt()
408     * @var int
409     */
410    protected $engine;
411
412    /**
413     * Holds the preferred crypt engine
414     *
415     * @see self::setEngine()
416     * @see self::setPreferredEngine()
417     * @var int
418     */
419    private $preferredEngine;
420
421    /**
422     * The mcrypt specific name of the cipher
423     *
424     * Only used if $engine == self::ENGINE_MCRYPT
425     *
426     * @link http://www.php.net/mcrypt_module_open
427     * @link http://www.php.net/mcrypt_list_algorithms
428     * @see self::setupMcrypt()
429     * @var string
430     */
431    protected $cipher_name_mcrypt;
432
433    /**
434     * The openssl specific name of the cipher
435     *
436     * Only used if $engine == self::ENGINE_OPENSSL
437     *
438     * @link http://www.php.net/openssl-get-cipher-methods
439     * @var string
440     */
441    protected $cipher_name_openssl;
442
443    /**
444     * The openssl specific name of the cipher in ECB mode
445     *
446     * If OpenSSL does not support the mode we're trying to use (CTR)
447     * it can still be emulated with ECB mode.
448     *
449     * @link http://www.php.net/openssl-get-cipher-methods
450     * @var string
451     */
452    protected $cipher_name_openssl_ecb;
453
454    /**
455     * The default salt used by setPassword()
456     *
457     * @see self::setPassword()
458     * @var string
459     */
460    private $password_default_salt = 'phpseclib/salt';
461
462    /**
463     * The name of the performance-optimized callback function
464     *
465     * Used by encrypt() / decrypt()
466     * only if $engine == self::ENGINE_INTERNAL
467     *
468     * @see self::encrypt()
469     * @see self::decrypt()
470     * @see self::setupInlineCrypt()
471     * @var Callback
472     */
473    protected $inline_crypt;
474
475    /**
476     * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
477     *
478     * @see self::openssl_ctr_process()
479     * @var bool
480     */
481    private $openssl_emulate_ctr = false;
482
483    /**
484     * Don't truncate / null pad key
485     *
486     * @see self::clearBuffers()
487     * @var bool
488     */
489    private $skip_key_adjustment = false;
490
491    /**
492     * Has the key length explicitly been set or should it be derived from the key, itself?
493     *
494     * @see self::setKeyLength()
495     * @var bool
496     */
497    protected $explicit_key_length = false;
498
499    /**
500     * Hash subkey for GHASH
501     *
502     * @see self::setupGCM()
503     * @see self::ghash()
504     * @var BinaryField\Integer
505     */
506    private $h;
507
508    /**
509     * Additional authenticated data
510     *
511     * @var string
512     */
513    protected $aad = '';
514
515    /**
516     * Authentication Tag produced after a round of encryption
517     *
518     * @var string
519     */
520    protected $newtag = false;
521
522    /**
523     * Authentication Tag to be verified during decryption
524     *
525     * @var string
526     */
527    protected $oldtag = false;
528
529    /**
530     * GCM Binary Field
531     *
532     * @see self::__construct()
533     * @see self::ghash()
534     * @var BinaryField
535     */
536    private static $gcmField;
537
538    /**
539     * Poly1305 Prime Field
540     *
541     * @see self::enablePoly1305()
542     * @see self::poly1305()
543     * @var PrimeField
544     */
545    private static $poly1305Field;
546
547    /**
548     * Flag for using regular vs "safe" intval
549     *
550     * @see self::initialize_static_variables()
551     * @var boolean
552     */
553    protected static $use_reg_intval;
554
555    /**
556     * Poly1305 Key
557     *
558     * @see self::setPoly1305Key()
559     * @see self::poly1305()
560     * @var string
561     */
562    protected $poly1305Key;
563
564    /**
565     * Poly1305 Flag
566     *
567     * @see self::setPoly1305Key()
568     * @see self::enablePoly1305()
569     * @var boolean
570     */
571    protected $usePoly1305 = false;
572
573    /**
574     * The Original Initialization Vector
575     *
576     * GCM uses the nonce to build the IV but we want to be able to distinguish between nonce-derived
577     * IV's and user-set IV's
578     *
579     * @see self::setIV()
580     * @var string
581     */
582    private $origIV = false;
583
584    /**
585     * Nonce
586     *
587     * Only used with GCM. We could re-use setIV() but nonce's can be of a different length and
588     * toggling between GCM and other modes could be more complicated if we re-used setIV()
589     *
590     * @see self::setNonce()
591     * @var string
592     */
593    protected $nonce = false;
594
595    /**
596     * Default Constructor.
597     *
598     * $mode could be:
599     *
600     * - ecb
601     *
602     * - cbc
603     *
604     * - ctr
605     *
606     * - cfb
607     *
608     * - cfb8
609     *
610     * - ofb
611     *
612     * - ofb8
613     *
614     * - gcm
615     *
616     * @param string $mode
617     * @throws BadModeException if an invalid / unsupported mode is provided
618     */
619    public function __construct($mode)
620    {
621        $mode = strtolower($mode);
622        // necessary because of 5.6 compatibility; we can't do isset(self::MODE_MAP[$mode]) in 5.6
623        $map = self::MODE_MAP;
624        if (!isset($map[$mode])) {
625            throw new BadModeException('No valid mode has been specified');
626        }
627
628        $mode = self::MODE_MAP[$mode];
629
630        // $mode dependent settings
631        switch ($mode) {
632            case self::MODE_ECB:
633            case self::MODE_CBC:
634                $this->paddable = true;
635                break;
636            case self::MODE_CTR:
637            case self::MODE_CFB:
638            case self::MODE_CFB8:
639            case self::MODE_OFB:
640            case self::MODE_OFB8:
641            case self::MODE_STREAM:
642                $this->paddable = false;
643                break;
644            case self::MODE_GCM:
645                if ($this->block_size != 16) {
646                    throw new BadModeException('GCM is only valid for block ciphers with a block size of 128 bits');
647                }
648                if (!isset(self::$gcmField)) {
649                    self::$gcmField = new BinaryField(128, 7, 2, 1, 0);
650                }
651                $this->paddable = false;
652                break;
653            default:
654                throw new BadModeException('No valid mode has been specified');
655        }
656
657        $this->mode = $mode;
658
659        static::initialize_static_variables();
660    }
661
662    /**
663     * Initialize static variables
664     */
665    protected static function initialize_static_variables()
666    {
667        if (!isset(self::$use_reg_intval)) {
668            switch (true) {
669                // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
670                case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
671                case !function_exists('php_uname'):
672                case !is_string(php_uname('m')):
673                case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
674                case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
675                    self::$use_reg_intval = true;
676                    break;
677                case (php_uname('m') & "\xDF\xDF\xDF") == 'ARM':
678                    switch (true) {
679                        /* PHP 7.0.0 introduced a bug that affected 32-bit ARM processors:
680
681                           https://github.com/php/php-src/commit/716da71446ebbd40fa6cf2cea8a4b70f504cc3cd
682
683                           altho the changelogs make no mention of it, this bug was fixed with this commit:
684
685                           https://github.com/php/php-src/commit/c1729272b17a1fe893d1a54e423d3b71470f3ee8
686
687                           affected versions of PHP are: 7.0.x, 7.1.0 - 7.1.23 and 7.2.0 - 7.2.11 */
688                        case PHP_VERSION_ID >= 70000 && PHP_VERSION_ID <= 70123:
689                        case PHP_VERSION_ID >= 70200 && PHP_VERSION_ID <= 70211:
690                            self::$use_reg_intval = false;
691                            break;
692                        default:
693                            self::$use_reg_intval = true;
694                    }
695            }
696        }
697    }
698
699    /**
700     * Sets the initialization vector.
701     *
702     * setIV() is not required when ecb or gcm modes are being used.
703     *
704     * {@internal Can be overwritten by a sub class, but does not have to be}
705     *
706     * @param string $iv
707     * @throws \LengthException if the IV length isn't equal to the block size
708     * @throws \BadMethodCallException if an IV is provided when one shouldn't be
709     */
710    public function setIV($iv)
711    {
712        if ($this->mode == self::MODE_ECB) {
713            throw new \BadMethodCallException('This mode does not require an IV.');
714        }
715
716        if ($this->mode == self::MODE_GCM) {
717            throw new \BadMethodCallException('Use setNonce instead');
718        }
719
720        if (!$this->usesIV()) {
721            throw new \BadMethodCallException('This algorithm does not use an IV.');
722        }
723
724        if (strlen($iv) != $this->block_size) {
725            throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required');
726        }
727
728        $this->iv = $this->origIV = $iv;
729        $this->changed = true;
730    }
731
732    /**
733     * Enables Poly1305 mode.
734     *
735     * Once enabled Poly1305 cannot be disabled.
736     *
737     * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode
738     */
739    public function enablePoly1305()
740    {
741        if ($this->mode == self::MODE_GCM) {
742            throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode');
743        }
744
745        $this->usePoly1305 = true;
746    }
747
748    /**
749     * Enables Poly1305 mode.
750     *
751     * Once enabled Poly1305 cannot be disabled. If $key is not passed then an attempt to call createPoly1305Key
752     * will be made.
753     *
754     * @param string $key optional
755     * @throws \LengthException if the key isn't long enough
756     * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode
757     */
758    public function setPoly1305Key($key = null)
759    {
760        if ($this->mode == self::MODE_GCM) {
761            throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode');
762        }
763
764        if (!is_string($key) || strlen($key) != 32) {
765            throw new \LengthException('The Poly1305 key must be 32 bytes long (256 bits)');
766        }
767
768        if (!isset(self::$poly1305Field)) {
769            // 2^130-5
770            self::$poly1305Field = new PrimeField(new BigInteger('3fffffffffffffffffffffffffffffffb', 16));
771        }
772
773        $this->poly1305Key = $key;
774        $this->usePoly1305 = true;
775    }
776
777    /**
778     * Sets the nonce.
779     *
780     * setNonce() is only required when gcm is used
781     *
782     * @param string $nonce
783     * @throws \BadMethodCallException if an nonce is provided when one shouldn't be
784     */
785    public function setNonce($nonce)
786    {
787        if ($this->mode != self::MODE_GCM) {
788            throw new \BadMethodCallException('Nonces are only used in GCM mode.');
789        }
790
791        $this->nonce = $nonce;
792        $this->setEngine();
793    }
794
795    /**
796     * Sets additional authenticated data
797     *
798     * setAAD() is only used by gcm or in poly1305 mode
799     *
800     * @param string $aad
801     * @throws \BadMethodCallException if mode isn't GCM or if poly1305 isn't being utilized
802     */
803    public function setAAD($aad)
804    {
805        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
806            throw new \BadMethodCallException('Additional authenticated data is only utilized in GCM mode or with Poly1305');
807        }
808
809        $this->aad = $aad;
810    }
811
812    /**
813     * Returns whether or not the algorithm uses an IV
814     *
815     * @return bool
816     */
817    public function usesIV()
818    {
819        return $this->mode != self::MODE_GCM && $this->mode != self::MODE_ECB;
820    }
821
822    /**
823     * Returns whether or not the algorithm uses a nonce
824     *
825     * @return bool
826     */
827    public function usesNonce()
828    {
829        return $this->mode == self::MODE_GCM;
830    }
831
832    /**
833     * Returns the current key length in bits
834     *
835     * @return int
836     */
837    public function getKeyLength()
838    {
839        return $this->key_length << 3;
840    }
841
842    /**
843     * Returns the current block length in bits
844     *
845     * @return int
846     */
847    public function getBlockLength()
848    {
849        return $this->block_size << 3;
850    }
851
852    /**
853     * Returns the current block length in bytes
854     *
855     * @return int
856     */
857    public function getBlockLengthInBytes()
858    {
859        return $this->block_size;
860    }
861
862    /**
863     * Sets the key length.
864     *
865     * Keys with explicitly set lengths need to be treated accordingly
866     *
867     * @param int $length
868     */
869    public function setKeyLength($length)
870    {
871        $this->explicit_key_length = $length >> 3;
872
873        if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) {
874            $this->key = false;
875            throw new InconsistentSetupException('Key has already been set and is not ' . $this->explicit_key_length . ' bytes long');
876        }
877    }
878
879    /**
880     * Sets the key.
881     *
882     * The min/max length(s) of the key depends on the cipher which is used.
883     * If the key not fits the length(s) of the cipher it will paded with null bytes
884     * up to the closest valid key length.  If the key is more than max length,
885     * we trim the excess bits.
886     *
887     * If the key is not explicitly set, it'll be assumed to be all null bytes.
888     *
889     * {@internal Could, but not must, extend by the child Crypt_* class}
890     *
891     * @param string $key
892     */
893    public function setKey($key)
894    {
895        if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
896            throw new InconsistentSetupException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
897        }
898
899        $this->key = $key;
900        $this->key_length = strlen($key);
901        $this->setEngine();
902    }
903
904    /**
905     * Sets the password.
906     *
907     * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
908     *     {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
909     *         $hash, $salt, $count, $dkLen
910     *
911     *         Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
912     *     {@link https://en.wikipedia.org/wiki/Bcrypt bcypt}:
913     *         $salt, $rounds, $keylen
914     *
915     *         This is a modified version of bcrypt used by OpenSSH.
916     *
917     * {@internal Could, but not must, extend by the child Crypt_* class}
918     *
919     * @see Crypt/Hash.php
920     * @param string $password
921     * @param string $method
922     * @param int|string ...$func_args
923     * @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
924     * @throws \RuntimeException if bcrypt is being used and a salt isn't provided
925     * @return bool
926     */
927    public function setPassword($password, $method = 'pbkdf2', ...$func_args)
928    {
929        $key = '';
930
931        $method = strtolower($method);
932        switch ($method) {
933            case 'bcrypt':
934                if (!isset($func_args[2])) {
935                    throw new \RuntimeException('A salt must be provided for bcrypt to work');
936                }
937
938                $salt = $func_args[0];
939
940                $rounds = isset($func_args[1]) ? $func_args[1] : 16;
941                $keylen = isset($func_args[2]) ? $func_args[2] : $this->key_length;
942
943                $key = Blowfish::bcrypt_pbkdf($password, $salt, $keylen + $this->block_size, $rounds);
944
945                $this->setKey(substr($key, 0, $keylen));
946                $this->setIV(substr($key, $keylen));
947
948                return true;
949            case 'pkcs12': // from https://tools.ietf.org/html/rfc7292#appendix-B.2
950            case 'pbkdf1':
951            case 'pbkdf2':
952                // Hash function
953                $hash = isset($func_args[0]) ? strtolower($func_args[0]) : 'sha1';
954                $hashObj = new Hash();
955                $hashObj->setHash($hash);
956
957                // WPA and WPA2 use the SSID as the salt
958                $salt = isset($func_args[1]) ? $func_args[1] : $this->password_default_salt;
959
960                // RFC2898#section-4.2 uses 1,000 iterations by default
961                // WPA and WPA2 use 4,096.
962                $count = isset($func_args[2]) ? $func_args[2] : 1000;
963
964                // Keylength
965                if (isset($func_args[3])) {
966                    if ($func_args[3] <= 0) {
967                        throw new \LengthException('Derived key length cannot be longer 0 or less');
968                    }
969                    $dkLen = $func_args[3];
970                } else {
971                    $key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length;
972                    $dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length;
973                }
974
975                switch (true) {
976                    case $method == 'pkcs12':
977                        /*
978                         In this specification, however, all passwords are created from
979                         BMPStrings with a NULL terminator.  This means that each character in
980                         the original BMPString is encoded in 2 bytes in big-endian format
981                         (most-significant byte first).  There are no Unicode byte order
982                         marks.  The 2 bytes produced from the last character in the BMPString
983                         are followed by 2 additional bytes with the value 0x00.
984
985                         -- https://tools.ietf.org/html/rfc7292#appendix-B.1
986                         */
987                        $password = "\0" . chunk_split($password, 1, "\0") . "\0";
988
989                        /*
990                         This standard specifies 3 different values for the ID byte mentioned
991                         above:
992
993                         1.  If ID=1, then the pseudorandom bits being produced are to be used
994                             as key material for performing encryption or decryption.
995
996                         2.  If ID=2, then the pseudorandom bits being produced are to be used
997                             as an IV (Initial Value) for encryption or decryption.
998
999                         3.  If ID=3, then the pseudorandom bits being produced are to be used
1000                             as an integrity key for MACing.
1001                         */
1002                        // Construct a string, D (the "diversifier"), by concatenating v/8
1003                        // copies of ID.
1004                        $blockLength = $hashObj->getBlockLengthInBytes();
1005                        $d1 = str_repeat(chr(1), $blockLength);
1006                        $d2 = str_repeat(chr(2), $blockLength);
1007                        $s = '';
1008                        if (strlen($salt)) {
1009                            while (strlen($s) < $blockLength) {
1010                                $s .= $salt;
1011                            }
1012                        }
1013                        $s = substr($s, 0, $blockLength);
1014
1015                        $p = '';
1016                        if (strlen($password)) {
1017                            while (strlen($p) < $blockLength) {
1018                                $p .= $password;
1019                            }
1020                        }
1021                        $p = substr($p, 0, $blockLength);
1022
1023                        $i = $s . $p;
1024
1025                        $this->setKey(self::pkcs12helper($dkLen, $hashObj, $i, $d1, $count));
1026                        if ($this->usesIV()) {
1027                            $this->setIV(self::pkcs12helper($this->block_size, $hashObj, $i, $d2, $count));
1028                        }
1029
1030                        return true;
1031                    case $method == 'pbkdf1':
1032                        if ($dkLen > $hashObj->getLengthInBytes()) {
1033                            throw new \LengthException('Derived key length cannot be longer than the hash length');
1034                        }
1035                        $t = $password . $salt;
1036                        for ($i = 0; $i < $count; ++$i) {
1037                            $t = $hashObj->hash($t);
1038                        }
1039                        $key = substr($t, 0, $dkLen);
1040
1041                        $this->setKey(substr($key, 0, $dkLen >> 1));
1042                        if ($this->usesIV()) {
1043                            $this->setIV(substr($key, $dkLen >> 1));
1044                        }
1045
1046                        return true;
1047                    case !in_array($hash, hash_algos()):
1048                        $i = 1;
1049                        $hashObj->setKey($password);
1050                        while (strlen($key) < $dkLen) {
1051                            $f = $u = $hashObj->hash($salt . pack('N', $i++));
1052                            for ($j = 2; $j <= $count; ++$j) {
1053                                $u = $hashObj->hash($u);
1054                                $f ^= $u;
1055                            }
1056                            $key .= $f;
1057                        }
1058                        $key = substr($key, 0, $dkLen);
1059                        break;
1060                    default:
1061                        $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
1062                }
1063                break;
1064            default:
1065                throw new UnsupportedAlgorithmException($method . ' is not a supported password hashing method');
1066        }
1067
1068        $this->setKey($key);
1069
1070        return true;
1071    }
1072
1073    /**
1074     * PKCS#12 KDF Helper Function
1075     *
1076     * As discussed here:
1077     *
1078     * {@link https://tools.ietf.org/html/rfc7292#appendix-B}
1079     *
1080     * @see self::setPassword()
1081     * @param int $n
1082     * @param \phpseclib3\Crypt\Hash $hashObj
1083     * @param string $i
1084     * @param string $d
1085     * @param int $count
1086     * @return string $a
1087     */
1088    private static function pkcs12helper($n, $hashObj, $i, $d, $count)
1089    {
1090        static $one;
1091        if (!isset($one)) {
1092            $one = new BigInteger(1);
1093        }
1094
1095        $blockLength = $hashObj->getBlockLength() >> 3;
1096
1097        $c = ceil($n / $hashObj->getLengthInBytes());
1098        $a = '';
1099        for ($j = 1; $j <= $c; $j++) {
1100            $ai = $d . $i;
1101            for ($k = 0; $k < $count; $k++) {
1102                $ai = $hashObj->hash($ai);
1103            }
1104            $b = '';
1105            while (strlen($b) < $blockLength) {
1106                $b .= $ai;
1107            }
1108            $b = substr($b, 0, $blockLength);
1109            $b = new BigInteger($b, 256);
1110            $newi = '';
1111            for ($k = 0; $k < strlen($i); $k += $blockLength) {
1112                $temp = substr($i, $k, $blockLength);
1113                $temp = new BigInteger($temp, 256);
1114                $temp->setPrecision($blockLength << 3);
1115                $temp = $temp->add($b);
1116                $temp = $temp->add($one);
1117                $newi .= $temp->toBytes(false);
1118            }
1119            $i = $newi;
1120            $a .= $ai;
1121        }
1122
1123        return substr($a, 0, $n);
1124    }
1125
1126    /**
1127     * Encrypts a message.
1128     *
1129     * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
1130     * implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's
1131     * necessary are discussed in the following
1132     * URL:
1133     *
1134     * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
1135     *
1136     * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
1137     * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
1138     * length.
1139     *
1140     * {@internal Could, but not must, extend by the child Crypt_* class}
1141     *
1142     * @see self::decrypt()
1143     * @param string $plaintext
1144     * @return string $ciphertext
1145     */
1146    public function encrypt($plaintext)
1147    {
1148        if ($this->paddable) {
1149            $plaintext = $this->pad($plaintext);
1150        }
1151
1152        $this->setup();
1153
1154        if ($this->mode == self::MODE_GCM) {
1155            $oldIV = $this->iv;
1156            Strings::increment_str($this->iv);
1157            $cipher = new static('ctr');
1158            $cipher->setKey($this->key);
1159            $cipher->setIV($this->iv);
1160            $ciphertext = $cipher->encrypt($plaintext);
1161
1162            $s = $this->ghash(
1163                self::nullPad128($this->aad) .
1164                self::nullPad128($ciphertext) .
1165                self::len64($this->aad) .
1166                self::len64($ciphertext)
1167            );
1168            $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV;
1169            $this->newtag = $cipher->encrypt($s);
1170            return $ciphertext;
1171        }
1172
1173        if (isset($this->poly1305Key)) {
1174            $cipher = clone $this;
1175            unset($cipher->poly1305Key);
1176            $this->usePoly1305 = false;
1177            $ciphertext = $cipher->encrypt($plaintext);
1178            $this->newtag = $this->poly1305($ciphertext);
1179            return $ciphertext;
1180        }
1181
1182        if ($this->engine === self::ENGINE_OPENSSL) {
1183            switch ($this->mode) {
1184                case self::MODE_STREAM:
1185                    return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
1186                case self::MODE_ECB:
1187                    return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
1188                case self::MODE_CBC:
1189                    $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV);
1190                    if ($this->continuousBuffer) {
1191                        $this->encryptIV = substr($result, -$this->block_size);
1192                    }
1193                    return $result;
1194                case self::MODE_CTR:
1195                    return $this->openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
1196                case self::MODE_CFB:
1197                    // cfb loosely routines inspired by openssl's:
1198                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1199                    $ciphertext = '';
1200                    if ($this->continuousBuffer) {
1201                        $iv = &$this->encryptIV;
1202                        $pos = &$this->enbuffer['pos'];
1203                    } else {
1204                        $iv = $this->encryptIV;
1205                        $pos = 0;
1206                    }
1207                    $len = strlen($plaintext);
1208                    $i = 0;
1209                    if ($pos) {
1210                        $orig_pos = $pos;
1211                        $max = $this->block_size - $pos;
1212                        if ($len >= $max) {
1213                            $i = $max;
1214                            $len -= $max;
1215                            $pos = 0;
1216                        } else {
1217                            $i = $len;
1218                            $pos += $len;
1219                            $len = 0;
1220                        }
1221                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1222                        $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
1223                        $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
1224                        $plaintext = substr($plaintext, $i);
1225                    }
1226
1227                    $overflow = $len % $this->block_size;
1228
1229                    if ($overflow) {
1230                        $ciphertext .= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
1231                        $iv = Strings::pop($ciphertext, $this->block_size);
1232
1233                        $size = $len - $overflow;
1234                        $block = $iv ^ substr($plaintext, -$overflow);
1235                        $iv = substr_replace($iv, $block, 0, $overflow);
1236                        $ciphertext .= $block;
1237                        $pos = $overflow;
1238                    } elseif ($len) {
1239                        $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
1240                        $iv = substr($ciphertext, -$this->block_size);
1241                    }
1242
1243                    return $ciphertext;
1244                case self::MODE_CFB8:
1245                    $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV);
1246                    if ($this->continuousBuffer) {
1247                        if (($len = strlen($ciphertext)) >= $this->block_size) {
1248                            $this->encryptIV = substr($ciphertext, -$this->block_size);
1249                        } else {
1250                            $this->encryptIV = substr($this->encryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
1251                        }
1252                    }
1253                    return $ciphertext;
1254                case self::MODE_OFB8:
1255                    $ciphertext = '';
1256                    $len = strlen($plaintext);
1257                    $iv = $this->encryptIV;
1258
1259                    for ($i = 0; $i < $len; ++$i) {
1260                        $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV);
1261                        $ciphertext .= $plaintext[$i] ^ $xor;
1262                        $iv = substr($iv, 1) . $xor[0];
1263                    }
1264
1265                    if ($this->continuousBuffer) {
1266                        $this->encryptIV = $iv;
1267                    }
1268                    break;
1269                case self::MODE_OFB:
1270                    return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
1271            }
1272        }
1273
1274        if ($this->engine === self::ENGINE_MCRYPT) {
1275            set_error_handler(function () {
1276            });
1277            if ($this->enchanged) {
1278                mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV));
1279                $this->enchanged = false;
1280            }
1281
1282            // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
1283            // using mcrypt's default handing of CFB the above would output two different things.  using phpseclib's
1284            // rewritten CFB implementation the above outputs the same thing twice.
1285            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
1286                $block_size = $this->block_size;
1287                $iv = &$this->encryptIV;
1288                $pos = &$this->enbuffer['pos'];
1289                $len = strlen($plaintext);
1290                $ciphertext = '';
1291                $i = 0;
1292                if ($pos) {
1293                    $orig_pos = $pos;
1294                    $max = $block_size - $pos;
1295                    if ($len >= $max) {
1296                        $i = $max;
1297                        $len -= $max;
1298                        $pos = 0;
1299                    } else {
1300                        $i = $len;
1301                        $pos += $len;
1302                        $len = 0;
1303                    }
1304                    $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
1305                    $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
1306                    $this->enbuffer['enmcrypt_init'] = true;
1307                }
1308                if ($len >= $block_size) {
1309                    if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
1310                        if ($this->enbuffer['enmcrypt_init'] === true) {
1311                            mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
1312                            $this->enbuffer['enmcrypt_init'] = false;
1313                        }
1314                        $ciphertext .= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
1315                        $iv = substr($ciphertext, -$block_size);
1316                        $len %= $block_size;
1317                    } else {
1318                        while ($len >= $block_size) {
1319                            $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
1320                            $ciphertext .= $iv;
1321                            $len -= $block_size;
1322                            $i += $block_size;
1323                        }
1324                    }
1325                }
1326
1327                if ($len) {
1328                    $iv = mcrypt_generic($this->ecb, $iv);
1329                    $block = $iv ^ substr($plaintext, -$len);
1330                    $iv = substr_replace($iv, $block, 0, $len);
1331                    $ciphertext .= $block;
1332                    $pos = $len;
1333                }
1334
1335                restore_error_handler();
1336
1337                return $ciphertext;
1338            }
1339
1340            $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
1341
1342            if (!$this->continuousBuffer) {
1343                mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV));
1344            }
1345
1346            restore_error_handler();
1347
1348            return $ciphertext;
1349        }
1350
1351        if ($this->engine === self::ENGINE_EVAL) {
1352            $inline = $this->inline_crypt;
1353            return $inline('encrypt', $plaintext);
1354        }
1355
1356        $buffer = &$this->enbuffer;
1357        $block_size = $this->block_size;
1358        $ciphertext = '';
1359        switch ($this->mode) {
1360            case self::MODE_ECB:
1361                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1362                    $ciphertext .= $this->encryptBlock(substr($plaintext, $i, $block_size));
1363                }
1364                break;
1365            case self::MODE_CBC:
1366                $xor = $this->encryptIV;
1367                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1368                    $block = substr($plaintext, $i, $block_size);
1369                    $block = $this->encryptBlock($block ^ $xor);
1370                    $xor = $block;
1371                    $ciphertext .= $block;
1372                }
1373                if ($this->continuousBuffer) {
1374                    $this->encryptIV = $xor;
1375                }
1376                break;
1377            case self::MODE_CTR:
1378                $xor = $this->encryptIV;
1379                if (strlen($buffer['ciphertext'])) {
1380                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1381                        $block = substr($plaintext, $i, $block_size);
1382                        if (strlen($block) > strlen($buffer['ciphertext'])) {
1383                            $buffer['ciphertext'] .= $this->encryptBlock($xor);
1384                            Strings::increment_str($xor);
1385                        }
1386                        $key = Strings::shift($buffer['ciphertext'], $block_size);
1387                        $ciphertext .= $block ^ $key;
1388                    }
1389                } else {
1390                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1391                        $block = substr($plaintext, $i, $block_size);
1392                        $key = $this->encryptBlock($xor);
1393                        Strings::increment_str($xor);
1394                        $ciphertext .= $block ^ $key;
1395                    }
1396                }
1397                if ($this->continuousBuffer) {
1398                    $this->encryptIV = $xor;
1399                    if ($start = strlen($plaintext) % $block_size) {
1400                        $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1401                    }
1402                }
1403                break;
1404            case self::MODE_CFB:
1405                // cfb loosely routines inspired by openssl's:
1406                // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1407                if ($this->continuousBuffer) {
1408                    $iv = &$this->encryptIV;
1409                    $pos = &$buffer['pos'];
1410                } else {
1411                    $iv = $this->encryptIV;
1412                    $pos = 0;
1413                }
1414                $len = strlen($plaintext);
1415                $i = 0;
1416                if ($pos) {
1417                    $orig_pos = $pos;
1418                    $max = $block_size - $pos;
1419                    if ($len >= $max) {
1420                        $i = $max;
1421                        $len -= $max;
1422                        $pos = 0;
1423                    } else {
1424                        $i = $len;
1425                        $pos += $len;
1426                        $len = 0;
1427                    }
1428                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1429                    $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
1430                    $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
1431                }
1432                while ($len >= $block_size) {
1433                    $iv = $this->encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
1434                    $ciphertext .= $iv;
1435                    $len -= $block_size;
1436                    $i += $block_size;
1437                }
1438                if ($len) {
1439                    $iv = $this->encryptBlock($iv);
1440                    $block = $iv ^ substr($plaintext, $i);
1441                    $iv = substr_replace($iv, $block, 0, $len);
1442                    $ciphertext .= $block;
1443                    $pos = $len;
1444                }
1445                break;
1446            case self::MODE_CFB8:
1447                $ciphertext = '';
1448                $len = strlen($plaintext);
1449                $iv = $this->encryptIV;
1450
1451                for ($i = 0; $i < $len; ++$i) {
1452                    $ciphertext .= ($c = $plaintext[$i] ^ $this->encryptBlock($iv));
1453                    $iv = substr($iv, 1) . $c;
1454                }
1455
1456                if ($this->continuousBuffer) {
1457                    if ($len >= $block_size) {
1458                        $this->encryptIV = substr($ciphertext, -$block_size);
1459                    } else {
1460                        $this->encryptIV = substr($this->encryptIV, $len - $block_size) . substr($ciphertext, -$len);
1461                    }
1462                }
1463                break;
1464            case self::MODE_OFB8:
1465                $ciphertext = '';
1466                $len = strlen($plaintext);
1467                $iv = $this->encryptIV;
1468
1469                for ($i = 0; $i < $len; ++$i) {
1470                    $xor = $this->encryptBlock($iv);
1471                    $ciphertext .= $plaintext[$i] ^ $xor;
1472                    $iv = substr($iv, 1) . $xor[0];
1473                }
1474
1475                if ($this->continuousBuffer) {
1476                    $this->encryptIV = $iv;
1477                }
1478                break;
1479            case self::MODE_OFB:
1480                $xor = $this->encryptIV;
1481                if (strlen($buffer['xor'])) {
1482                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1483                        $block = substr($plaintext, $i, $block_size);
1484                        if (strlen($block) > strlen($buffer['xor'])) {
1485                            $xor = $this->encryptBlock($xor);
1486                            $buffer['xor'] .= $xor;
1487                        }
1488                        $key = Strings::shift($buffer['xor'], $block_size);
1489                        $ciphertext .= $block ^ $key;
1490                    }
1491                } else {
1492                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1493                        $xor = $this->encryptBlock($xor);
1494                        $ciphertext .= substr($plaintext, $i, $block_size) ^ $xor;
1495                    }
1496                    $key = $xor;
1497                }
1498                if ($this->continuousBuffer) {
1499                    $this->encryptIV = $xor;
1500                    if ($start = strlen($plaintext) % $block_size) {
1501                        $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1502                    }
1503                }
1504                break;
1505            case self::MODE_STREAM:
1506                $ciphertext = $this->encryptBlock($plaintext);
1507                break;
1508        }
1509
1510        return $ciphertext;
1511    }
1512
1513    /**
1514     * Decrypts a message.
1515     *
1516     * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
1517     * it is.
1518     *
1519     * {@internal Could, but not must, extend by the child Crypt_* class}
1520     *
1521     * @see self::encrypt()
1522     * @param string $ciphertext
1523     * @return string $plaintext
1524     * @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size
1525     */
1526    public function decrypt($ciphertext)
1527    {
1528        if ($this->paddable && strlen($ciphertext) % $this->block_size) {
1529            throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')');
1530        }
1531        $this->setup();
1532
1533        if ($this->mode == self::MODE_GCM || isset($this->poly1305Key)) {
1534            if ($this->oldtag === false) {
1535                throw new InsufficientSetupException('Authentication Tag has not been set');
1536            }
1537
1538            if (isset($this->poly1305Key)) {
1539                $newtag = $this->poly1305($ciphertext);
1540            } else {
1541                $oldIV = $this->iv;
1542                Strings::increment_str($this->iv);
1543                $cipher = new static('ctr');
1544                $cipher->setKey($this->key);
1545                $cipher->setIV($this->iv);
1546                $plaintext = $cipher->decrypt($ciphertext);
1547
1548                $s = $this->ghash(
1549                    self::nullPad128($this->aad) .
1550                    self::nullPad128($ciphertext) .
1551                    self::len64($this->aad) .
1552                    self::len64($ciphertext)
1553                );
1554                $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV;
1555                $newtag = $cipher->encrypt($s);
1556            }
1557            if ($this->oldtag != substr($newtag, 0, strlen($newtag))) {
1558                $cipher = clone $this;
1559                unset($cipher->poly1305Key);
1560                $this->usePoly1305 = false;
1561                $plaintext = $cipher->decrypt($ciphertext);
1562                $this->oldtag = false;
1563                throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
1564            }
1565            $this->oldtag = false;
1566            return $plaintext;
1567        }
1568
1569        if ($this->engine === self::ENGINE_OPENSSL) {
1570            switch ($this->mode) {
1571                case self::MODE_STREAM:
1572                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
1573                    break;
1574                case self::MODE_ECB:
1575                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
1576                    break;
1577                case self::MODE_CBC:
1578                    $offset = $this->block_size;
1579                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV);
1580                    if ($this->continuousBuffer) {
1581                        $this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
1582                    }
1583                    break;
1584                case self::MODE_CTR:
1585                    $plaintext = $this->openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
1586                    break;
1587                case self::MODE_CFB:
1588                    // cfb loosely routines inspired by openssl's:
1589                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1590                    $plaintext = '';
1591                    if ($this->continuousBuffer) {
1592                        $iv = &$this->decryptIV;
1593                        $pos = &$this->debuffer['pos'];
1594                    } else {
1595                        $iv = $this->decryptIV;
1596                        $pos = 0;
1597                    }
1598                    $len = strlen($ciphertext);
1599                    $i = 0;
1600                    if ($pos) {
1601                        $orig_pos = $pos;
1602                        $max = $this->block_size - $pos;
1603                        if ($len >= $max) {
1604                            $i = $max;
1605                            $len -= $max;
1606                            $pos = 0;
1607                        } else {
1608                            $i = $len;
1609                            $pos += $len;
1610                            $len = 0;
1611                        }
1612                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
1613                        $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1614                        $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1615                        $ciphertext = substr($ciphertext, $i);
1616                    }
1617                    $overflow = $len % $this->block_size;
1618                    if ($overflow) {
1619                        $plaintext .= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
1620                        if ($len - $overflow) {
1621                            $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
1622                        }
1623                        $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
1624                        $plaintext .= $iv ^ substr($ciphertext, -$overflow);
1625                        $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
1626                        $pos = $overflow;
1627                    } elseif ($len) {
1628                        $plaintext .= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
1629                        $iv = substr($ciphertext, -$this->block_size);
1630                    }
1631                    break;
1632                case self::MODE_CFB8:
1633                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV);
1634                    if ($this->continuousBuffer) {
1635                        if (($len = strlen($ciphertext)) >= $this->block_size) {
1636                            $this->decryptIV = substr($ciphertext, -$this->block_size);
1637                        } else {
1638                            $this->decryptIV = substr($this->decryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
1639                        }
1640                    }
1641                    break;
1642                case self::MODE_OFB8:
1643                    $plaintext = '';
1644                    $len = strlen($ciphertext);
1645                    $iv = $this->decryptIV;
1646
1647                    for ($i = 0; $i < $len; ++$i) {
1648                        $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV);
1649                        $plaintext .= $ciphertext[$i] ^ $xor;
1650                        $iv = substr($iv, 1) . $xor[0];
1651                    }
1652
1653                    if ($this->continuousBuffer) {
1654                        $this->decryptIV = $iv;
1655                    }
1656                    break;
1657                case self::MODE_OFB:
1658                    $plaintext = $this->openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
1659            }
1660
1661            return $this->paddable ? $this->unpad($plaintext) : $plaintext;
1662        }
1663
1664        if ($this->engine === self::ENGINE_MCRYPT) {
1665            set_error_handler(function () {
1666            });
1667            $block_size = $this->block_size;
1668            if ($this->dechanged) {
1669                mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV));
1670                $this->dechanged = false;
1671            }
1672
1673            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
1674                $iv = &$this->decryptIV;
1675                $pos = &$this->debuffer['pos'];
1676                $len = strlen($ciphertext);
1677                $plaintext = '';
1678                $i = 0;
1679                if ($pos) {
1680                    $orig_pos = $pos;
1681                    $max = $block_size - $pos;
1682                    if ($len >= $max) {
1683                        $i = $max;
1684                        $len -= $max;
1685                        $pos = 0;
1686                    } else {
1687                        $i = $len;
1688                        $pos += $len;
1689                        $len = 0;
1690                    }
1691                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1692                    $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1693                    $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1694                }
1695                if ($len >= $block_size) {
1696                    $cb = substr($ciphertext, $i, $len - $len % $block_size);
1697                    $plaintext .= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
1698                    $iv = substr($cb, -$block_size);
1699                    $len %= $block_size;
1700                }
1701                if ($len) {
1702                    $iv = mcrypt_generic($this->ecb, $iv);
1703                    $plaintext .= $iv ^ substr($ciphertext, -$len);
1704                    $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
1705                    $pos = $len;
1706                }
1707
1708                restore_error_handler();
1709
1710                return $plaintext;
1711            }
1712
1713            $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
1714
1715            if (!$this->continuousBuffer) {
1716                mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV));
1717            }
1718
1719            restore_error_handler();
1720
1721            return $this->paddable ? $this->unpad($plaintext) : $plaintext;
1722        }
1723
1724        if ($this->engine === self::ENGINE_EVAL) {
1725            $inline = $this->inline_crypt;
1726            return $inline('decrypt', $ciphertext);
1727        }
1728
1729        $block_size = $this->block_size;
1730
1731        $buffer = &$this->debuffer;
1732        $plaintext = '';
1733        switch ($this->mode) {
1734            case self::MODE_ECB:
1735                for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1736                    $plaintext .= $this->decryptBlock(substr($ciphertext, $i, $block_size));
1737                }
1738                break;
1739            case self::MODE_CBC:
1740                $xor = $this->decryptIV;
1741                for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1742                    $block = substr($ciphertext, $i, $block_size);
1743                    $plaintext .= $this->decryptBlock($block) ^ $xor;
1744                    $xor = $block;
1745                }
1746                if ($this->continuousBuffer) {
1747                    $this->decryptIV = $xor;
1748                }
1749                break;
1750            case self::MODE_CTR:
1751                $xor = $this->decryptIV;
1752                if (strlen($buffer['ciphertext'])) {
1753                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1754                        $block = substr($ciphertext, $i, $block_size);
1755                        if (strlen($block) > strlen($buffer['ciphertext'])) {
1756                            $buffer['ciphertext'] .= $this->encryptBlock($xor);
1757                            Strings::increment_str($xor);
1758                        }
1759                        $key = Strings::shift($buffer['ciphertext'], $block_size);
1760                        $plaintext .= $block ^ $key;
1761                    }
1762                } else {
1763                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1764                        $block = substr($ciphertext, $i, $block_size);
1765                        $key = $this->encryptBlock($xor);
1766                        Strings::increment_str($xor);
1767                        $plaintext .= $block ^ $key;
1768                    }
1769                }
1770                if ($this->continuousBuffer) {
1771                    $this->decryptIV = $xor;
1772                    if ($start = strlen($ciphertext) % $block_size) {
1773                        $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1774                    }
1775                }
1776                break;
1777            case self::MODE_CFB:
1778                if ($this->continuousBuffer) {
1779                    $iv = &$this->decryptIV;
1780                    $pos = &$buffer['pos'];
1781                } else {
1782                    $iv = $this->decryptIV;
1783                    $pos = 0;
1784                }
1785                $len = strlen($ciphertext);
1786                $i = 0;
1787                if ($pos) {
1788                    $orig_pos = $pos;
1789                    $max = $block_size - $pos;
1790                    if ($len >= $max) {
1791                        $i = $max;
1792                        $len -= $max;
1793                        $pos = 0;
1794                    } else {
1795                        $i = $len;
1796                        $pos += $len;
1797                        $len = 0;
1798                    }
1799                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1800                    $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1801                    $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1802                }
1803                while ($len >= $block_size) {
1804                    $iv = $this->encryptBlock($iv);
1805                    $cb = substr($ciphertext, $i, $block_size);
1806                    $plaintext .= $iv ^ $cb;
1807                    $iv = $cb;
1808                    $len -= $block_size;
1809                    $i += $block_size;
1810                }
1811                if ($len) {
1812                    $iv = $this->encryptBlock($iv);
1813                    $plaintext .= $iv ^ substr($ciphertext, $i);
1814                    $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
1815                    $pos = $len;
1816                }
1817                break;
1818            case self::MODE_CFB8:
1819                $plaintext = '';
1820                $len = strlen($ciphertext);
1821                $iv = $this->decryptIV;
1822
1823                for ($i = 0; $i < $len; ++$i) {
1824                    $plaintext .= $ciphertext[$i] ^ $this->encryptBlock($iv);
1825                    $iv = substr($iv, 1) . $ciphertext[$i];
1826                }
1827
1828                if ($this->continuousBuffer) {
1829                    if ($len >= $block_size) {
1830                        $this->decryptIV = substr($ciphertext, -$block_size);
1831                    } else {
1832                        $this->decryptIV = substr($this->decryptIV, $len - $block_size) . substr($ciphertext, -$len);
1833                    }
1834                }
1835                break;
1836            case self::MODE_OFB8:
1837                $plaintext = '';
1838                $len = strlen($ciphertext);
1839                $iv = $this->decryptIV;
1840
1841                for ($i = 0; $i < $len; ++$i) {
1842                    $xor = $this->encryptBlock($iv);
1843                    $plaintext .= $ciphertext[$i] ^ $xor;
1844                    $iv = substr($iv, 1) . $xor[0];
1845                }
1846
1847                if ($this->continuousBuffer) {
1848                    $this->decryptIV = $iv;
1849                }
1850                break;
1851            case self::MODE_OFB:
1852                $xor = $this->decryptIV;
1853                if (strlen($buffer['xor'])) {
1854                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1855                        $block = substr($ciphertext, $i, $block_size);
1856                        if (strlen($block) > strlen($buffer['xor'])) {
1857                            $xor = $this->encryptBlock($xor);
1858                            $buffer['xor'] .= $xor;
1859                        }
1860                        $key = Strings::shift($buffer['xor'], $block_size);
1861                        $plaintext .= $block ^ $key;
1862                    }
1863                } else {
1864                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
1865                        $xor = $this->encryptBlock($xor);
1866                        $plaintext .= substr($ciphertext, $i, $block_size) ^ $xor;
1867                    }
1868                    $key = $xor;
1869                }
1870                if ($this->continuousBuffer) {
1871                    $this->decryptIV = $xor;
1872                    if ($start = strlen($ciphertext) % $block_size) {
1873                        $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1874                    }
1875                }
1876                break;
1877            case self::MODE_STREAM:
1878                $plaintext = $this->decryptBlock($ciphertext);
1879                break;
1880        }
1881        return $this->paddable ? $this->unpad($plaintext) : $plaintext;
1882    }
1883
1884    /**
1885     * Get the authentication tag
1886     *
1887     * Only used in GCM or Poly1305 mode
1888     *
1889     * @see self::encrypt()
1890     * @param int $length optional
1891     * @return string
1892     * @throws \LengthException if $length isn't of a sufficient length
1893     * @throws \RuntimeException if GCM mode isn't being used
1894     */
1895    public function getTag($length = 16)
1896    {
1897        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
1898            throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305');
1899        }
1900
1901        if ($this->newtag === false) {
1902            throw new \BadMethodCallException('A tag can only be returned after a round of encryption has been performed');
1903        }
1904
1905        // the tag is 128-bits. it can't be greater than 16 bytes because that's bigger than the tag is. if it
1906        // were 0 you might as well be doing CTR and less than 4 provides minimal security that could be trivially
1907        // easily brute forced.
1908        // see https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=36
1909        // for more info
1910        if ($length < 4 || $length > 16) {
1911            throw new \LengthException('The authentication tag must be between 4 and 16 bytes long');
1912        }
1913
1914        return $length == 16 ?
1915            $this->newtag :
1916            substr($this->newtag, 0, $length);
1917    }
1918
1919    /**
1920     * Sets the authentication tag
1921     *
1922     * Only used in GCM mode
1923     *
1924     * @see self::decrypt()
1925     * @param string $tag
1926     * @throws \LengthException if $length isn't of a sufficient length
1927     * @throws \RuntimeException if GCM mode isn't being used
1928     */
1929    public function setTag($tag)
1930    {
1931        if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) {
1932            $this->createPoly1305Key();
1933        }
1934
1935        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
1936            throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305');
1937        }
1938
1939        $length = strlen($tag);
1940        if ($length < 4 || $length > 16) {
1941            throw new \LengthException('The authentication tag must be between 4 and 16 bytes long');
1942        }
1943        $this->oldtag = $tag;
1944    }
1945
1946    /**
1947     * Get the IV
1948     *
1949     * mcrypt requires an IV even if ECB is used
1950     *
1951     * @see self::encrypt()
1952     * @see self::decrypt()
1953     * @param string $iv
1954     * @return string
1955     */
1956    protected function getIV($iv)
1957    {
1958        return $this->mode == self::MODE_ECB ? str_repeat("\0", $this->block_size) : $iv;
1959    }
1960
1961    /**
1962     * OpenSSL CTR Processor
1963     *
1964     * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1965     * for CTR is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt()
1966     * and SymmetricKey::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
1967     * function will emulate CTR with ECB when necessary.
1968     *
1969     * @see self::encrypt()
1970     * @see self::decrypt()
1971     * @param string $plaintext
1972     * @param string $encryptIV
1973     * @param array $buffer
1974     * @return string
1975     */
1976    private function openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
1977    {
1978        $ciphertext = '';
1979
1980        $block_size = $this->block_size;
1981        $key = $this->key;
1982
1983        if ($this->openssl_emulate_ctr) {
1984            $xor = $encryptIV;
1985            if (strlen($buffer['ciphertext'])) {
1986                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1987                    $block = substr($plaintext, $i, $block_size);
1988                    if (strlen($block) > strlen($buffer['ciphertext'])) {
1989                        $buffer['ciphertext'] .= openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
1990                    }
1991                    Strings::increment_str($xor);
1992                    $otp = Strings::shift($buffer['ciphertext'], $block_size);
1993                    $ciphertext .= $block ^ $otp;
1994                }
1995            } else {
1996                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
1997                    $block = substr($plaintext, $i, $block_size);
1998                    $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
1999                    Strings::increment_str($xor);
2000                    $ciphertext .= $block ^ $otp;
2001                }
2002            }
2003            if ($this->continuousBuffer) {
2004                $encryptIV = $xor;
2005                if ($start = strlen($plaintext) % $block_size) {
2006                    $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
2007                }
2008            }
2009
2010            return $ciphertext;
2011        }
2012
2013        if (strlen($buffer['ciphertext'])) {
2014            $ciphertext = $plaintext ^ Strings::shift($buffer['ciphertext'], strlen($plaintext));
2015            $plaintext = substr($plaintext, strlen($ciphertext));
2016
2017            if (!strlen($plaintext)) {
2018                return $ciphertext;
2019            }
2020        }
2021
2022        $overflow = strlen($plaintext) % $block_size;
2023        if ($overflow) {
2024            $plaintext2 = Strings::pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
2025            $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
2026            $temp = Strings::pop($encrypted, $block_size);
2027            $ciphertext .= $encrypted . ($plaintext2 ^ $temp);
2028            if ($this->continuousBuffer) {
2029                $buffer['ciphertext'] = substr($temp, $overflow);
2030                $encryptIV = $temp;
2031            }
2032        } elseif (!strlen($buffer['ciphertext'])) {
2033            $ciphertext .= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
2034            $temp = Strings::pop($ciphertext, $block_size);
2035            if ($this->continuousBuffer) {
2036                $encryptIV = $temp;
2037            }
2038        }
2039        if ($this->continuousBuffer) {
2040            $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
2041            if ($overflow) {
2042                Strings::increment_str($encryptIV);
2043            }
2044        }
2045
2046        return $ciphertext;
2047    }
2048
2049    /**
2050     * OpenSSL OFB Processor
2051     *
2052     * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
2053     * for OFB is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt()
2054     * and SymmetricKey::decrypt().
2055     *
2056     * @see self::encrypt()
2057     * @see self::decrypt()
2058     * @param string $plaintext
2059     * @param string $encryptIV
2060     * @param array $buffer
2061     * @return string
2062     */
2063    private function openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
2064    {
2065        if (strlen($buffer['xor'])) {
2066            $ciphertext = $plaintext ^ $buffer['xor'];
2067            $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
2068            $plaintext = substr($plaintext, strlen($ciphertext));
2069        } else {
2070            $ciphertext = '';
2071        }
2072
2073        $block_size = $this->block_size;
2074
2075        $len = strlen($plaintext);
2076        $key = $this->key;
2077        $overflow = $len % $block_size;
2078
2079        if (strlen($plaintext)) {
2080            if ($overflow) {
2081                $ciphertext .= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
2082                $xor = Strings::pop($ciphertext, $block_size);
2083                if ($this->continuousBuffer) {
2084                    $encryptIV = $xor;
2085                }
2086                $ciphertext .= Strings::shift($xor, $overflow) ^ substr($plaintext, -$overflow);
2087                if ($this->continuousBuffer) {
2088                    $buffer['xor'] = $xor;
2089                }
2090            } else {
2091                $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
2092                if ($this->continuousBuffer) {
2093                    $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
2094                }
2095            }
2096        }
2097
2098        return $ciphertext;
2099    }
2100
2101    /**
2102     * phpseclib <-> OpenSSL Mode Mapper
2103     *
2104     * May need to be overwritten by classes extending this one in some cases
2105     *
2106     * @return string
2107     */
2108    protected function openssl_translate_mode()
2109    {
2110        switch ($this->mode) {
2111            case self::MODE_ECB:
2112                return 'ecb';
2113            case self::MODE_CBC:
2114                return 'cbc';
2115            case self::MODE_CTR:
2116            case self::MODE_GCM:
2117                return 'ctr';
2118            case self::MODE_CFB:
2119                return 'cfb';
2120            case self::MODE_CFB8:
2121                return 'cfb8';
2122            case self::MODE_OFB:
2123                return 'ofb';
2124        }
2125    }
2126
2127    /**
2128     * Pad "packets".
2129     *
2130     * Block ciphers working by encrypting between their specified [$this->]block_size at a time
2131     * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
2132     * pad the input so that it is of the proper length.
2133     *
2134     * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH,
2135     * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping
2136     * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
2137     * transmitted separately)
2138     *
2139     * @see self::disablePadding()
2140     */
2141    public function enablePadding()
2142    {
2143        $this->padding = true;
2144    }
2145
2146    /**
2147     * Do not pad packets.
2148     *
2149     * @see self::enablePadding()
2150     */
2151    public function disablePadding()
2152    {
2153        $this->padding = false;
2154    }
2155
2156    /**
2157     * Treat consecutive "packets" as if they are a continuous buffer.
2158     *
2159     * Say you have a 32-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
2160     * will yield different outputs:
2161     *
2162     * <code>
2163     *    echo $rijndael->encrypt(substr($plaintext,  0, 16));
2164     *    echo $rijndael->encrypt(substr($plaintext, 16, 16));
2165     * </code>
2166     * <code>
2167     *    echo $rijndael->encrypt($plaintext);
2168     * </code>
2169     *
2170     * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
2171     * another, as demonstrated with the following:
2172     *
2173     * <code>
2174     *    $rijndael->encrypt(substr($plaintext, 0, 16));
2175     *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
2176     * </code>
2177     * <code>
2178     *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
2179     * </code>
2180     *
2181     * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
2182     * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
2183     * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
2184     *
2185     * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\*() object changes after each
2186     * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
2187     * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
2188     * however, they are also less intuitive and more likely to cause you problems.
2189     *
2190     * {@internal Could, but not must, extend by the child Crypt_* class}
2191     *
2192     * @see self::disableContinuousBuffer()
2193     */
2194    public function enableContinuousBuffer()
2195    {
2196        if ($this->mode == self::MODE_ECB) {
2197            return;
2198        }
2199
2200        if ($this->mode == self::MODE_GCM) {
2201            throw new \BadMethodCallException('This mode does not run in continuous mode');
2202        }
2203
2204        $this->continuousBuffer = true;
2205
2206        $this->setEngine();
2207    }
2208
2209    /**
2210     * Treat consecutive packets as if they are a discontinuous buffer.
2211     *
2212     * The default behavior.
2213     *
2214     * {@internal Could, but not must, extend by the child Crypt_* class}
2215     *
2216     * @see self::enableContinuousBuffer()
2217     */
2218    public function disableContinuousBuffer()
2219    {
2220        if ($this->mode == self::MODE_ECB) {
2221            return;
2222        }
2223        if (!$this->continuousBuffer) {
2224            return;
2225        }
2226
2227        $this->continuousBuffer = false;
2228
2229        $this->setEngine();
2230    }
2231
2232    /**
2233     * Test for engine validity
2234     *
2235     * @see self::__construct()
2236     * @param int $engine
2237     * @return bool
2238     */
2239    protected function isValidEngineHelper($engine)
2240    {
2241        switch ($engine) {
2242            case self::ENGINE_OPENSSL:
2243                $this->openssl_emulate_ctr = false;
2244                $result = $this->cipher_name_openssl &&
2245                          extension_loaded('openssl');
2246                if (!$result) {
2247                    return false;
2248                }
2249
2250                $methods = openssl_get_cipher_methods();
2251                if (in_array($this->cipher_name_openssl, $methods)) {
2252                    return true;
2253                }
2254                // not all of openssl's symmetric cipher's support ctr. for those
2255                // that don't we'll emulate it
2256                switch ($this->mode) {
2257                    case self::MODE_CTR:
2258                        if (in_array($this->cipher_name_openssl_ecb, $methods)) {
2259                            $this->openssl_emulate_ctr = true;
2260                            return true;
2261                        }
2262                }
2263                return false;
2264            case self::ENGINE_MCRYPT:
2265                set_error_handler(function () {
2266                });
2267                $result = $this->cipher_name_mcrypt &&
2268                          extension_loaded('mcrypt') &&
2269                          in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
2270                restore_error_handler();
2271                return $result;
2272            case self::ENGINE_EVAL:
2273                return method_exists($this, 'setupInlineCrypt');
2274            case self::ENGINE_INTERNAL:
2275                return true;
2276        }
2277
2278        return false;
2279    }
2280
2281    /**
2282     * Test for engine validity
2283     *
2284     * @see self::__construct()
2285     * @param string $engine
2286     * @return bool
2287     */
2288    public function isValidEngine($engine)
2289    {
2290        static $reverseMap;
2291        if (!isset($reverseMap)) {
2292            $reverseMap = array_map('strtolower', self::ENGINE_MAP);
2293            $reverseMap = array_flip($reverseMap);
2294        }
2295        $engine = strtolower($engine);
2296        if (!isset($reverseMap[$engine])) {
2297            return false;
2298        }
2299
2300        return $this->isValidEngineHelper($reverseMap[$engine]);
2301    }
2302
2303    /**
2304     * Sets the preferred crypt engine
2305     *
2306     * Currently, $engine could be:
2307     *
2308     * - libsodium[very fast]
2309     *
2310     * - OpenSSL  [very fast]
2311     *
2312     * - mcrypt   [fast]
2313     *
2314     * - Eval     [slow]
2315     *
2316     * - PHP      [slowest]
2317     *
2318     * If the preferred crypt engine is not available the fastest available one will be used
2319     *
2320     * @see self::__construct()
2321     * @param string $engine
2322     */
2323    public function setPreferredEngine($engine)
2324    {
2325        static $reverseMap;
2326        if (!isset($reverseMap)) {
2327            $reverseMap = array_map('strtolower', self::ENGINE_MAP);
2328            $reverseMap = array_flip($reverseMap);
2329        }
2330        $engine = is_string($engine) ? strtolower($engine) : '';
2331        $this->preferredEngine = isset($reverseMap[$engine]) ? $reverseMap[$engine] : self::ENGINE_LIBSODIUM;
2332
2333        $this->setEngine();
2334    }
2335
2336    /**
2337     * Returns the engine currently being utilized
2338     *
2339     * @see self::setEngine()
2340     */
2341    public function getEngine()
2342    {
2343        return self::ENGINE_MAP[$this->engine];
2344    }
2345
2346    /**
2347     * Sets the engine as appropriate
2348     *
2349     * @see self::__construct()
2350     */
2351    protected function setEngine()
2352    {
2353        $this->engine = null;
2354
2355        $candidateEngines = [
2356            self::ENGINE_LIBSODIUM,
2357            self::ENGINE_OPENSSL_GCM,
2358            self::ENGINE_OPENSSL,
2359            self::ENGINE_MCRYPT,
2360            self::ENGINE_EVAL
2361        ];
2362        if (isset($this->preferredEngine)) {
2363            $temp = [$this->preferredEngine];
2364            $candidateEngines = array_merge(
2365                $temp,
2366                array_diff($candidateEngines, $temp)
2367            );
2368        }
2369        foreach ($candidateEngines as $engine) {
2370            if ($this->isValidEngineHelper($engine)) {
2371                $this->engine = $engine;
2372                break;
2373            }
2374        }
2375        if (!$this->engine) {
2376            $this->engine = self::ENGINE_INTERNAL;
2377        }
2378
2379        if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
2380            set_error_handler(function () {
2381            });
2382            // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
2383            // (re)open them with the module named in $this->cipher_name_mcrypt
2384            mcrypt_module_close($this->enmcrypt);
2385            mcrypt_module_close($this->demcrypt);
2386            $this->enmcrypt = null;
2387            $this->demcrypt = null;
2388
2389            if ($this->ecb) {
2390                mcrypt_module_close($this->ecb);
2391                $this->ecb = null;
2392            }
2393            restore_error_handler();
2394        }
2395
2396        $this->changed = $this->nonIVChanged = true;
2397    }
2398
2399    /**
2400     * Encrypts a block
2401     *
2402     * Note: Must be extended by the child \phpseclib3\Crypt\* class
2403     *
2404     * @param string $in
2405     * @return string
2406     */
2407    abstract protected function encryptBlock($in);
2408
2409    /**
2410     * Decrypts a block
2411     *
2412     * Note: Must be extended by the child \phpseclib3\Crypt\* class
2413     *
2414     * @param string $in
2415     * @return string
2416     */
2417    abstract protected function decryptBlock($in);
2418
2419    /**
2420     * Setup the key (expansion)
2421     *
2422     * Only used if $engine == self::ENGINE_INTERNAL
2423     *
2424     * Note: Must extend by the child \phpseclib3\Crypt\* class
2425     *
2426     * @see self::setup()
2427     */
2428    abstract protected function setupKey();
2429
2430    /**
2431     * Setup the self::ENGINE_INTERNAL $engine
2432     *
2433     * (re)init, if necessary, the internal cipher $engine and flush all $buffers
2434     * Used (only) if $engine == self::ENGINE_INTERNAL
2435     *
2436     * _setup() will be called each time if $changed === true
2437     * typically this happens when using one or more of following public methods:
2438     *
2439     * - setKey()
2440     *
2441     * - setIV()
2442     *
2443     * - disableContinuousBuffer()
2444     *
2445     * - First run of encrypt() / decrypt() with no init-settings
2446     *
2447     * {@internal setup() is always called before en/decryption.}
2448     *
2449     * {@internal Could, but not must, extend by the child Crypt_* class}
2450     *
2451     * @see self::setKey()
2452     * @see self::setIV()
2453     * @see self::disableContinuousBuffer()
2454     */
2455    protected function setup()
2456    {
2457        if (!$this->changed) {
2458            return;
2459        }
2460
2461        $this->changed = false;
2462
2463        if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) {
2464            $this->createPoly1305Key();
2465        }
2466
2467        $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true];
2468        //$this->newtag = $this->oldtag = false;
2469
2470        if ($this->usesNonce()) {
2471            if ($this->nonce === false) {
2472                throw new InsufficientSetupException('No nonce has been defined');
2473            }
2474            if ($this->mode == self::MODE_GCM && !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) {
2475                $this->setupGCM();
2476            }
2477        } else {
2478            $this->iv = $this->origIV;
2479        }
2480
2481        if ($this->iv === false && !in_array($this->mode, [self::MODE_STREAM, self::MODE_ECB])) {
2482            if ($this->mode != self::MODE_GCM || !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) {
2483                throw new InsufficientSetupException('No IV has been defined');
2484            }
2485        }
2486
2487        if ($this->key === false) {
2488            throw new InsufficientSetupException('No key has been defined');
2489        }
2490
2491        $this->encryptIV = $this->decryptIV = $this->iv;
2492
2493        switch ($this->engine) {
2494            case self::ENGINE_MCRYPT:
2495                $this->enchanged = $this->dechanged = true;
2496
2497                set_error_handler(function () {
2498                });
2499
2500                if (!isset($this->enmcrypt)) {
2501                    static $mcrypt_modes = [
2502                        self::MODE_CTR    => 'ctr',
2503                        self::MODE_ECB    => MCRYPT_MODE_ECB,
2504                        self::MODE_CBC    => MCRYPT_MODE_CBC,
2505                        self::MODE_CFB    => 'ncfb',
2506                        self::MODE_CFB8   => MCRYPT_MODE_CFB,
2507                        self::MODE_OFB    => MCRYPT_MODE_NOFB,
2508                        self::MODE_OFB8   => MCRYPT_MODE_OFB,
2509                        self::MODE_STREAM => MCRYPT_MODE_STREAM,
2510                    ];
2511
2512                    $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
2513                    $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
2514
2515                    // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
2516                    // to workaround mcrypt's broken ncfb implementation in buffered mode
2517                    // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
2518                    if ($this->mode == self::MODE_CFB) {
2519                        $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
2520                    }
2521                } // else should mcrypt_generic_deinit be called?
2522
2523                if ($this->mode == self::MODE_CFB) {
2524                    mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
2525                }
2526
2527                restore_error_handler();
2528
2529                break;
2530            case self::ENGINE_INTERNAL:
2531                $this->setupKey();
2532                break;
2533            case self::ENGINE_EVAL:
2534                if ($this->nonIVChanged) {
2535                    $this->setupKey();
2536                    $this->setupInlineCrypt();
2537                }
2538        }
2539
2540        $this->nonIVChanged = false;
2541    }
2542
2543    /**
2544     * Pads a string
2545     *
2546     * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
2547     * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
2548     * chr($this->block_size - (strlen($text) % $this->block_size)
2549     *
2550     * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
2551     * and padding will, hence forth, be enabled.
2552     *
2553     * @see self::unpad()
2554     * @param string $text
2555     * @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size
2556     * @return string
2557     */
2558    protected function pad($text)
2559    {
2560        $length = strlen($text);
2561
2562        if (!$this->padding) {
2563            if ($length % $this->block_size == 0) {
2564                return $text;
2565            } else {
2566                throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding.");
2567            }
2568        }
2569
2570        $pad = $this->block_size - ($length % $this->block_size);
2571
2572        return str_pad($text, $length + $pad, chr($pad));
2573    }
2574
2575    /**
2576     * Unpads a string.
2577     *
2578     * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
2579     * and false will be returned.
2580     *
2581     * @see self::pad()
2582     * @param string $text
2583     * @throws \LengthException if the ciphertext's length is not a multiple of the block size
2584     * @return string
2585     */
2586    protected function unpad($text)
2587    {
2588        if (!$this->padding) {
2589            return $text;
2590        }
2591
2592        $length = ord($text[strlen($text) - 1]);
2593
2594        if (!$length || $length > $this->block_size) {
2595            throw new BadDecryptionException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})");
2596        }
2597
2598        return substr($text, 0, -$length);
2599    }
2600
2601    /**
2602     * Setup the performance-optimized function for de/encrypt()
2603     *
2604     * Stores the created (or existing) callback function-name
2605     * in $this->inline_crypt
2606     *
2607     * Internally for phpseclib developers:
2608     *
2609     *     _setupInlineCrypt() would be called only if:
2610     *
2611     *     - $this->engine === self::ENGINE_EVAL
2612     *
2613     *     - each time on _setup(), after(!) _setupKey()
2614     *
2615     *
2616     *     This ensures that _setupInlineCrypt() has always a
2617     *     full ready2go initializated internal cipher $engine state
2618     *     where, for example, the keys already expanded,
2619     *     keys/block_size calculated and such.
2620     *
2621     *     It is, each time if called, the responsibility of _setupInlineCrypt():
2622     *
2623     *     - to set $this->inline_crypt to a valid and fully working callback function
2624     *       as a (faster) replacement for encrypt() / decrypt()
2625     *
2626     *     - NOT to create unlimited callback functions (for memory reasons!)
2627     *       no matter how often _setupInlineCrypt() would be called. At some
2628     *       point of amount they must be generic re-useable.
2629     *
2630     *     - the code of _setupInlineCrypt() it self,
2631     *       and the generated callback code,
2632     *       must be, in following order:
2633     *       - 100% safe
2634     *       - 100% compatible to encrypt()/decrypt()
2635     *       - using only php5+ features/lang-constructs/php-extensions if
2636     *         compatibility (down to php4) or fallback is provided
2637     *       - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
2638     *       - >= 10% faster than encrypt()/decrypt() [which is, by the way,
2639     *         the reason for the existence of _setupInlineCrypt() :-)]
2640     *       - memory-nice
2641     *       - short (as good as possible)
2642     *
2643     * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
2644     *       - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib3\Crypt\* class.
2645     *       - The following variable names are reserved:
2646     *         - $_*  (all variable names prefixed with an underscore)
2647     *         - $self (object reference to it self. Do not use $this, but $self instead)
2648     *         - $in (the content of $in has to en/decrypt by the generated code)
2649     *       - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
2650     *
2651     * {@internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()}
2652     *
2653     * @see self::setup()
2654     * @see self::createInlineCryptFunction()
2655     * @see self::encrypt()
2656     * @see self::decrypt()
2657     */
2658    //protected function setupInlineCrypt();
2659
2660    /**
2661     * Creates the performance-optimized function for en/decrypt()
2662     *
2663     * Internally for phpseclib developers:
2664     *
2665     *    _createInlineCryptFunction():
2666     *
2667     *    - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
2668     *      with the current [$this->]mode of operation code
2669     *
2670     *    - create the $inline function, which called by encrypt() / decrypt()
2671     *      as its replacement to speed up the en/decryption operations.
2672     *
2673     *    - return the name of the created $inline callback function
2674     *
2675     *    - used to speed up en/decryption
2676     *
2677     *
2678     *
2679     *    The main reason why can speed up things [up to 50%] this way are:
2680     *
2681     *    - using variables more effective then regular.
2682     *      (ie no use of expensive arrays but integers $k_0, $k_1 ...
2683     *      or even, for example, the pure $key[] values hardcoded)
2684     *
2685     *    - avoiding 1000's of function calls of ie _encryptBlock()
2686     *      but inlining the crypt operations.
2687     *      in the mode of operation for() loop.
2688     *
2689     *    - full loop unroll the (sometimes key-dependent) rounds
2690     *      avoiding this way ++$i counters and runtime-if's etc...
2691     *
2692     *    The basic code architectur of the generated $inline en/decrypt()
2693     *    lambda function, in pseudo php, is:
2694     *
2695     *    <code>
2696     *    +----------------------------------------------------------------------------------------------+
2697     *    | callback $inline = create_function:                                                          |
2698     *    | lambda_function_0001_crypt_ECB($action, $text)                                               |
2699     *    | {                                                                                            |
2700     *    |     INSERT PHP CODE OF:                                                                      |
2701     *    |     $cipher_code['init_crypt'];                  // general init code.                       |
2702     *    |                                                  // ie: $sbox'es declarations used for       |
2703     *    |                                                  //     encrypt and decrypt'ing.             |
2704     *    |                                                                                              |
2705     *    |     switch ($action) {                                                                       |
2706     *    |         case 'encrypt':                                                                      |
2707     *    |             INSERT PHP CODE OF:                                                              |
2708     *    |             $cipher_code['init_encrypt'];       // encrypt sepcific init code.               |
2709     *    |                                                    ie: specified $key or $box                |
2710     *    |                                                        declarations for encrypt'ing.         |
2711     *    |                                                                                              |
2712     *    |             foreach ($ciphertext) {                                                          |
2713     *    |                 $in = $block_size of $ciphertext;                                            |
2714     *    |                                                                                              |
2715     *    |                 INSERT PHP CODE OF:                                                          |
2716     *    |                 $cipher_code['encrypt_block'];  // encrypt's (string) $in, which is always:  |
2717     *    |                                                 // strlen($in) == $this->block_size          |
2718     *    |                                                 // here comes the cipher algorithm in action |
2719     *    |                                                 // for encryption.                           |
2720     *    |                                                 // $cipher_code['encrypt_block'] has to      |
2721     *    |                                                 // encrypt the content of the $in variable   |
2722     *    |                                                                                              |
2723     *    |                 $plaintext .= $in;                                                           |
2724     *    |             }                                                                                |
2725     *    |             return $plaintext;                                                               |
2726     *    |                                                                                              |
2727     *    |         case 'decrypt':                                                                      |
2728     *    |             INSERT PHP CODE OF:                                                              |
2729     *    |             $cipher_code['init_decrypt'];       // decrypt sepcific init code                |
2730     *    |                                                    ie: specified $key or $box                |
2731     *    |                                                        declarations for decrypt'ing.         |
2732     *    |             foreach ($plaintext) {                                                           |
2733     *    |                 $in = $block_size of $plaintext;                                             |
2734     *    |                                                                                              |
2735     *    |                 INSERT PHP CODE OF:                                                          |
2736     *    |                 $cipher_code['decrypt_block'];  // decrypt's (string) $in, which is always   |
2737     *    |                                                 // strlen($in) == $this->block_size          |
2738     *    |                                                 // here comes the cipher algorithm in action |
2739     *    |                                                 // for decryption.                           |
2740     *    |                                                 // $cipher_code['decrypt_block'] has to      |
2741     *    |                                                 // decrypt the content of the $in variable   |
2742     *    |                 $ciphertext .= $in;                                                          |
2743     *    |             }                                                                                |
2744     *    |             return $ciphertext;                                                              |
2745     *    |     }                                                                                        |
2746     *    | }                                                                                            |
2747     *    +----------------------------------------------------------------------------------------------+
2748     *    </code>
2749     *
2750     *    See also the \phpseclib3\Crypt\*::_setupInlineCrypt()'s for
2751     *    productive inline $cipher_code's how they works.
2752     *
2753     *    Structure of:
2754     *    <code>
2755     *    $cipher_code = [
2756     *        'init_crypt'    => (string) '', // optional
2757     *        'init_encrypt'  => (string) '', // optional
2758     *        'init_decrypt'  => (string) '', // optional
2759     *        'encrypt_block' => (string) '', // required
2760     *        'decrypt_block' => (string) ''  // required
2761     *    ];
2762     *    </code>
2763     *
2764     * @see self::setupInlineCrypt()
2765     * @see self::encrypt()
2766     * @see self::decrypt()
2767     * @param array $cipher_code
2768     * @return string (the name of the created callback function)
2769     */
2770    protected function createInlineCryptFunction($cipher_code)
2771    {
2772        $block_size = $this->block_size;
2773
2774        // optional
2775        $init_crypt    = isset($cipher_code['init_crypt'])    ? $cipher_code['init_crypt']    : '';
2776        $init_encrypt  = isset($cipher_code['init_encrypt'])  ? $cipher_code['init_encrypt']  : '';
2777        $init_decrypt  = isset($cipher_code['init_decrypt'])  ? $cipher_code['init_decrypt']  : '';
2778        // required
2779        $encrypt_block = $cipher_code['encrypt_block'];
2780        $decrypt_block = $cipher_code['decrypt_block'];
2781
2782        // Generating mode of operation inline code,
2783        // merged with the $cipher_code algorithm
2784        // for encrypt- and decryption.
2785        switch ($this->mode) {
2786            case self::MODE_ECB:
2787                $encrypt = $init_encrypt . '
2788                    $_ciphertext = "";
2789                    $_plaintext_len = strlen($_text);
2790
2791                    for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
2792                        $in = substr($_text, $_i, ' . $block_size . ');
2793                        ' . $encrypt_block . '
2794                        $_ciphertext.= $in;
2795                    }
2796
2797                    return $_ciphertext;
2798                    ';
2799
2800                $decrypt = $init_decrypt . '
2801                    $_plaintext = "";
2802                    $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0));
2803                    $_ciphertext_len = strlen($_text);
2804
2805                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
2806                        $in = substr($_text, $_i, ' . $block_size . ');
2807                        ' . $decrypt_block . '
2808                        $_plaintext.= $in;
2809                    }
2810
2811                    return $this->unpad($_plaintext);
2812                    ';
2813                break;
2814            case self::MODE_CTR:
2815                $encrypt = $init_encrypt . '
2816                    $_ciphertext = "";
2817                    $_plaintext_len = strlen($_text);
2818                    $_xor = $this->encryptIV;
2819                    $_buffer = &$this->enbuffer;
2820                    if (strlen($_buffer["ciphertext"])) {
2821                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
2822                            $_block = substr($_text, $_i, ' . $block_size . ');
2823                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2824                                $in = $_xor;
2825                                ' . $encrypt_block . '
2826                                \phpseclib3\Common\Functions\Strings::increment_str($_xor);
2827                                $_buffer["ciphertext"].= $in;
2828                            }
2829                            $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["ciphertext"], ' . $block_size . ');
2830                            $_ciphertext.= $_block ^ $_key;
2831                        }
2832                    } else {
2833                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
2834                            $_block = substr($_text, $_i, ' . $block_size . ');
2835                            $in = $_xor;
2836                            ' . $encrypt_block . '
2837                            \phpseclib3\Common\Functions\Strings::increment_str($_xor);
2838                            $_key = $in;
2839                            $_ciphertext.= $_block ^ $_key;
2840                        }
2841                    }
2842                    if ($this->continuousBuffer) {
2843                        $this->encryptIV = $_xor;
2844                        if ($_start = $_plaintext_len % ' . $block_size . ') {
2845                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2846                        }
2847                    }
2848
2849                    return $_ciphertext;
2850                ';
2851
2852                $decrypt = $init_encrypt . '
2853                    $_plaintext = "";
2854                    $_ciphertext_len = strlen($_text);
2855                    $_xor = $this->decryptIV;
2856                    $_buffer = &$this->debuffer;
2857
2858                    if (strlen($_buffer["ciphertext"])) {
2859                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
2860                            $_block = substr($_text, $_i, ' . $block_size . ');
2861                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2862                                $in = $_xor;
2863                                ' . $encrypt_block . '
2864                                \phpseclib3\Common\Functions\Strings::increment_str($_xor);
2865                                $_buffer["ciphertext"].= $in;
2866                            }
2867                            $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["ciphertext"], ' . $block_size . ');
2868                            $_plaintext.= $_block ^ $_key;
2869                        }
2870                    } else {
2871                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
2872                            $_block = substr($_text, $_i, ' . $block_size . ');
2873                            $in = $_xor;
2874                            ' . $encrypt_block . '
2875                            \phpseclib3\Common\Functions\Strings::increment_str($_xor);
2876                            $_key = $in;
2877                            $_plaintext.= $_block ^ $_key;
2878                        }
2879                    }
2880                    if ($this->continuousBuffer) {
2881                        $this->decryptIV = $_xor;
2882                        if ($_start = $_ciphertext_len % ' . $block_size . ') {
2883                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2884                        }
2885                    }
2886
2887                    return $_plaintext;
2888                    ';
2889                break;
2890            case self::MODE_CFB:
2891                $encrypt = $init_encrypt . '
2892                    $_ciphertext = "";
2893                    $_buffer = &$this->enbuffer;
2894
2895                    if ($this->continuousBuffer) {
2896                        $_iv = &$this->encryptIV;
2897                        $_pos = &$_buffer["pos"];
2898                    } else {
2899                        $_iv = $this->encryptIV;
2900                        $_pos = 0;
2901                    }
2902                    $_len = strlen($_text);
2903                    $_i = 0;
2904                    if ($_pos) {
2905                        $_orig_pos = $_pos;
2906                        $_max = ' . $block_size . ' - $_pos;
2907                        if ($_len >= $_max) {
2908                            $_i = $_max;
2909                            $_len-= $_max;
2910                            $_pos = 0;
2911                        } else {
2912                            $_i = $_len;
2913                            $_pos+= $_len;
2914                            $_len = 0;
2915                        }
2916                        $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
2917                        $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
2918                    }
2919                    while ($_len >= ' . $block_size . ') {
2920                        $in = $_iv;
2921                        ' . $encrypt_block . ';
2922                        $_iv = $in ^ substr($_text, $_i, ' . $block_size . ');
2923                        $_ciphertext.= $_iv;
2924                        $_len-= ' . $block_size . ';
2925                        $_i+= ' . $block_size . ';
2926                    }
2927                    if ($_len) {
2928                        $in = $_iv;
2929                        ' . $encrypt_block . '
2930                        $_iv = $in;
2931                        $_block = $_iv ^ substr($_text, $_i);
2932                        $_iv = substr_replace($_iv, $_block, 0, $_len);
2933                        $_ciphertext.= $_block;
2934                        $_pos = $_len;
2935                    }
2936                    return $_ciphertext;
2937                ';
2938
2939                $decrypt = $init_encrypt . '
2940                    $_plaintext = "";
2941                    $_buffer = &$this->debuffer;
2942
2943                    if ($this->continuousBuffer) {
2944                        $_iv = &$this->decryptIV;
2945                        $_pos = &$_buffer["pos"];
2946                    } else {
2947                        $_iv = $this->decryptIV;
2948                        $_pos = 0;
2949                    }
2950                    $_len = strlen($_text);
2951                    $_i = 0;
2952                    if ($_pos) {
2953                        $_orig_pos = $_pos;
2954                        $_max = ' . $block_size . ' - $_pos;
2955                        if ($_len >= $_max) {
2956                            $_i = $_max;
2957                            $_len-= $_max;
2958                            $_pos = 0;
2959                        } else {
2960                            $_i = $_len;
2961                            $_pos+= $_len;
2962                            $_len = 0;
2963                        }
2964                        $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
2965                        $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
2966                    }
2967                    while ($_len >= ' . $block_size . ') {
2968                        $in = $_iv;
2969                        ' . $encrypt_block . '
2970                        $_iv = $in;
2971                        $cb = substr($_text, $_i, ' . $block_size . ');
2972                        $_plaintext.= $_iv ^ $cb;
2973                        $_iv = $cb;
2974                        $_len-= ' . $block_size . ';
2975                        $_i+= ' . $block_size . ';
2976                    }
2977                    if ($_len) {
2978                        $in = $_iv;
2979                        ' . $encrypt_block . '
2980                        $_iv = $in;
2981                        $_plaintext.= $_iv ^ substr($_text, $_i);
2982                        $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
2983                        $_pos = $_len;
2984                    }
2985
2986                    return $_plaintext;
2987                    ';
2988                break;
2989            case self::MODE_CFB8:
2990                $encrypt = $init_encrypt . '
2991                    $_ciphertext = "";
2992                    $_len = strlen($_text);
2993                    $_iv = $this->encryptIV;
2994
2995                    for ($_i = 0; $_i < $_len; ++$_i) {
2996                        $in = $_iv;
2997                        ' . $encrypt_block . '
2998                        $_ciphertext .= ($_c = $_text[$_i] ^ $in);
2999                        $_iv = substr($_iv, 1) . $_c;
3000                    }
3001
3002                    if ($this->continuousBuffer) {
3003                        if ($_len >= ' . $block_size . ') {
3004                            $this->encryptIV = substr($_ciphertext, -' . $block_size . ');
3005                        } else {
3006                            $this->encryptIV = substr($this->encryptIV, $_len - ' . $block_size . ') . substr($_ciphertext, -$_len);
3007                        }
3008                    }
3009
3010                    return $_ciphertext;
3011                    ';
3012                $decrypt = $init_encrypt . '
3013                    $_plaintext = "";
3014                    $_len = strlen($_text);
3015                    $_iv = $this->decryptIV;
3016
3017                    for ($_i = 0; $_i < $_len; ++$_i) {
3018                        $in = $_iv;
3019                        ' . $encrypt_block . '
3020                        $_plaintext .= $_text[$_i] ^ $in;
3021                        $_iv = substr($_iv, 1) . $_text[$_i];
3022                    }
3023
3024                    if ($this->continuousBuffer) {
3025                        if ($_len >= ' . $block_size . ') {
3026                            $this->decryptIV = substr($_text, -' . $block_size . ');
3027                        } else {
3028                            $this->decryptIV = substr($this->decryptIV, $_len - ' . $block_size . ') . substr($_text, -$_len);
3029                        }
3030                    }
3031
3032                    return $_plaintext;
3033                    ';
3034                break;
3035            case self::MODE_OFB8:
3036                $encrypt = $init_encrypt . '
3037                    $_ciphertext = "";
3038                    $_len = strlen($_text);
3039                    $_iv = $this->encryptIV;
3040
3041                    for ($_i = 0; $_i < $_len; ++$_i) {
3042                        $in = $_iv;
3043                        ' . $encrypt_block . '
3044                        $_ciphertext.= $_text[$_i] ^ $in;
3045                        $_iv = substr($_iv, 1) . $in[0];
3046                    }
3047
3048                    if ($this->continuousBuffer) {
3049                        $this->encryptIV = $_iv;
3050                    }
3051
3052                    return $_ciphertext;
3053                    ';
3054                $decrypt = $init_encrypt . '
3055                    $_plaintext = "";
3056                    $_len = strlen($_text);
3057                    $_iv = $this->decryptIV;
3058
3059                    for ($_i = 0; $_i < $_len; ++$_i) {
3060                        $in = $_iv;
3061                        ' . $encrypt_block . '
3062                        $_plaintext.= $_text[$_i] ^ $in;
3063                        $_iv = substr($_iv, 1) . $in[0];
3064                    }
3065
3066                    if ($this->continuousBuffer) {
3067                        $this->decryptIV = $_iv;
3068                    }
3069
3070                    return $_plaintext;
3071                    ';
3072                break;
3073            case self::MODE_OFB:
3074                $encrypt = $init_encrypt . '
3075                    $_ciphertext = "";
3076                    $_plaintext_len = strlen($_text);
3077                    $_xor = $this->encryptIV;
3078                    $_buffer = &$this->enbuffer;
3079
3080                    if (strlen($_buffer["xor"])) {
3081                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
3082                            $_block = substr($_text, $_i, ' . $block_size . ');
3083                            if (strlen($_block) > strlen($_buffer["xor"])) {
3084                                $in = $_xor;
3085                                ' . $encrypt_block . '
3086                                $_xor = $in;
3087                                $_buffer["xor"].= $_xor;
3088                            }
3089                            $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["xor"], ' . $block_size . ');
3090                            $_ciphertext.= $_block ^ $_key;
3091                        }
3092                    } else {
3093                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
3094                            $in = $_xor;
3095                            ' . $encrypt_block . '
3096                            $_xor = $in;
3097                            $_ciphertext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor;
3098                        }
3099                        $_key = $_xor;
3100                    }
3101                    if ($this->continuousBuffer) {
3102                        $this->encryptIV = $_xor;
3103                        if ($_start = $_plaintext_len % ' . $block_size . ') {
3104                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
3105                        }
3106                    }
3107                    return $_ciphertext;
3108                    ';
3109
3110                $decrypt = $init_encrypt . '
3111                    $_plaintext = "";
3112                    $_ciphertext_len = strlen($_text);
3113                    $_xor = $this->decryptIV;
3114                    $_buffer = &$this->debuffer;
3115
3116                    if (strlen($_buffer["xor"])) {
3117                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
3118                            $_block = substr($_text, $_i, ' . $block_size . ');
3119                            if (strlen($_block) > strlen($_buffer["xor"])) {
3120                                $in = $_xor;
3121                                ' . $encrypt_block . '
3122                                $_xor = $in;
3123                                $_buffer["xor"].= $_xor;
3124                            }
3125                            $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["xor"], ' . $block_size . ');
3126                            $_plaintext.= $_block ^ $_key;
3127                        }
3128                    } else {
3129                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
3130                            $in = $_xor;
3131                            ' . $encrypt_block . '
3132                            $_xor = $in;
3133                            $_plaintext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor;
3134                        }
3135                        $_key = $_xor;
3136                    }
3137                    if ($this->continuousBuffer) {
3138                        $this->decryptIV = $_xor;
3139                        if ($_start = $_ciphertext_len % ' . $block_size . ') {
3140                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
3141                        }
3142                    }
3143                    return $_plaintext;
3144                    ';
3145                break;
3146            case self::MODE_STREAM:
3147                $encrypt = $init_encrypt . '
3148                    $_ciphertext = "";
3149                    ' . $encrypt_block . '
3150                    return $_ciphertext;
3151                    ';
3152                $decrypt = $init_decrypt . '
3153                    $_plaintext = "";
3154                    ' . $decrypt_block . '
3155                    return $_plaintext;
3156                    ';
3157                break;
3158            // case self::MODE_CBC:
3159            default:
3160                $encrypt = $init_encrypt . '
3161                    $_ciphertext = "";
3162                    $_plaintext_len = strlen($_text);
3163
3164                    $in = $this->encryptIV;
3165
3166                    for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
3167                        $in = substr($_text, $_i, ' . $block_size . ') ^ $in;
3168                        ' . $encrypt_block . '
3169                        $_ciphertext.= $in;
3170                    }
3171
3172                    if ($this->continuousBuffer) {
3173                        $this->encryptIV = $in;
3174                    }
3175
3176                    return $_ciphertext;
3177                    ';
3178
3179                $decrypt = $init_decrypt . '
3180                    $_plaintext = "";
3181                    $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0));
3182                    $_ciphertext_len = strlen($_text);
3183
3184                    $_iv = $this->decryptIV;
3185
3186                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
3187                        $in = $_block = substr($_text, $_i, ' . $block_size . ');
3188                        ' . $decrypt_block . '
3189                        $_plaintext.= $in ^ $_iv;
3190                        $_iv = $_block;
3191                    }
3192
3193                    if ($this->continuousBuffer) {
3194                        $this->decryptIV = $_iv;
3195                    }
3196
3197                    return $this->unpad($_plaintext);
3198                    ';
3199                break;
3200        }
3201
3202        // Before discrediting this, please read the following:
3203        // @see https://github.com/phpseclib/phpseclib/issues/1293
3204        // @see https://github.com/phpseclib/phpseclib/pull/1143
3205        eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};');
3206
3207        return \Closure::bind($func, $this, static::class);
3208    }
3209
3210    /**
3211     * Convert float to int
3212     *
3213     * On ARM CPUs converting floats to ints doesn't always work
3214     *
3215     * @param string $x
3216     * @return int
3217     */
3218    protected static function safe_intval($x)
3219    {
3220        if (is_int($x)) {
3221            return $x;
3222        }
3223
3224        if (self::$use_reg_intval) {
3225            return PHP_INT_SIZE == 4 && PHP_VERSION_ID >= 80100 ? intval($x) : $x;
3226        }
3227
3228        return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
3229            ((fmod(floor($x / 0x80000000), 2) & 1) << 31);
3230    }
3231
3232    /**
3233     * eval()'able string for in-line float to int
3234     *
3235     * @return string
3236     */
3237    protected static function safe_intval_inline()
3238    {
3239        if (self::$use_reg_intval) {
3240            return PHP_INT_SIZE == 4 && PHP_VERSION_ID >= 80100 ? 'intval(%s)' : '%s';
3241        }
3242
3243        $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
3244        return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
3245    }
3246
3247    /**
3248     * Sets up GCM parameters
3249     *
3250     * See steps 1-2 of https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=23
3251     * for more info
3252     *
3253     */
3254    private function setupGCM()
3255    {
3256        // don't keep on re-calculating $this->h
3257        if (!$this->h || $this->hKey != $this->key) {
3258            $cipher = new static('ecb');
3259            $cipher->setKey($this->key);
3260            $cipher->disablePadding();
3261
3262            $this->h = self::$gcmField->newInteger(
3263                Strings::switchEndianness($cipher->encrypt("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"))
3264            );
3265            $this->hKey = $this->key;
3266        }
3267
3268        if (strlen($this->nonce) == 12) {
3269            $this->iv = $this->nonce . "\0\0\0\1";
3270        } else {
3271            $this->iv = $this->ghash(
3272                self::nullPad128($this->nonce) . str_repeat("\0", 8) . self::len64($this->nonce)
3273            );
3274        }
3275    }
3276
3277    /**
3278     * Performs GHASH operation
3279     *
3280     * See https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=20
3281     * for more info
3282     *
3283     * @see self::decrypt()
3284     * @see self::encrypt()
3285     * @param string $x
3286     * @return string
3287     */
3288    private function ghash($x)
3289    {
3290        $h = $this->h;
3291        $y = ["\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"];
3292        $x = str_split($x, 16);
3293        $n = 0;
3294        // the switchEndianness calls are necessary because the multiplication algorithm in BinaryField/Integer
3295        // interprets strings as polynomials in big endian order whereas in GCM they're interpreted in little
3296        // endian order per https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=19.
3297        // big endian order is what binary field elliptic curves use per http://www.secg.org/sec1-v2.pdf#page=18.
3298
3299        // we could switchEndianness here instead of in the while loop but doing so in the while loop seems like it
3300        // might be slightly more performant
3301        //$x = Strings::switchEndianness($x);
3302        foreach ($x as $xn) {
3303            $xn = Strings::switchEndianness($xn);
3304            $t = $y[$n] ^ $xn;
3305            $temp = self::$gcmField->newInteger($t);
3306            $y[++$n] = $temp->multiply($h)->toBytes();
3307            $y[$n] = substr($y[$n], 1);
3308        }
3309        $y[$n] = Strings::switchEndianness($y[$n]);
3310        return $y[$n];
3311    }
3312
3313    /**
3314     * Returns the bit length of a string in a packed format
3315     *
3316     * @see self::decrypt()
3317     * @see self::encrypt()
3318     * @see self::setupGCM()
3319     * @param string $str
3320     * @return string
3321     */
3322    private static function len64($str)
3323    {
3324        return "\0\0\0\0" . pack('N', 8 * strlen($str));
3325    }
3326
3327    /**
3328     * NULL pads a string to be a multiple of 128
3329     *
3330     * @see self::decrypt()
3331     * @see self::encrypt()
3332     * @see self::setupGCM()
3333     * @param string $str
3334     * @return string
3335     */
3336    protected static function nullPad128($str)
3337    {
3338        $len = strlen($str);
3339        return $str . str_repeat("\0", 16 * ceil($len / 16) - $len);
3340    }
3341
3342    /**
3343     * Calculates Poly1305 MAC
3344     *
3345     * On my system ChaCha20, with libsodium, takes 0.5s. With this custom Poly1305 implementation
3346     * it takes 1.2s.
3347     *
3348     * @see self::decrypt()
3349     * @see self::encrypt()
3350     * @param string $text
3351     * @return string
3352     */
3353    protected function poly1305($text)
3354    {
3355        $s = $this->poly1305Key; // strlen($this->poly1305Key) == 32
3356        $r = Strings::shift($s, 16);
3357        $r = strrev($r);
3358        $r &= "\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xff";
3359        $s = strrev($s);
3360
3361        $r = self::$poly1305Field->newInteger(new BigInteger($r, 256));
3362        $s = self::$poly1305Field->newInteger(new BigInteger($s, 256));
3363        $a = self::$poly1305Field->newInteger(new BigInteger());
3364
3365        $blocks = str_split($text, 16);
3366        foreach ($blocks as $block) {
3367            $n = strrev($block . chr(1));
3368            $n = self::$poly1305Field->newInteger(new BigInteger($n, 256));
3369            $a = $a->add($n);
3370            $a = $a->multiply($r);
3371        }
3372        $r = $a->toBigInteger()->add($s->toBigInteger());
3373        $mask = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
3374        return strrev($r->toBytes()) & $mask;
3375    }
3376
3377    /**
3378     * Return the mode
3379     *
3380     * You can do $obj instanceof AES or whatever to get the cipher but you can't do that to get the mode
3381     *
3382     * @return string
3383     */
3384    public function getMode()
3385    {
3386        return array_flip(self::MODE_MAP)[$this->mode];
3387    }
3388
3389    /**
3390     * Is the continuous buffer enabled?
3391     *
3392     * @return boolean
3393     */
3394    public function continuousBufferEnabled()
3395    {
3396        return $this->continuousBuffer;
3397    }
3398}
3399