Subversion Repositories oidplus

Rev

Rev 1417 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
827 daniel-mar 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
 
35
namespace phpseclib3\Crypt\Common;
36
 
37
use phpseclib3\Common\Functions\Strings;
1042 daniel-mar 38
use phpseclib3\Crypt\Blowfish;
827 daniel-mar 39
use phpseclib3\Crypt\Hash;
40
use phpseclib3\Exception\BadDecryptionException;
41
use phpseclib3\Exception\BadModeException;
42
use phpseclib3\Exception\InconsistentSetupException;
43
use phpseclib3\Exception\InsufficientSetupException;
44
use phpseclib3\Exception\UnsupportedAlgorithmException;
45
use phpseclib3\Math\BigInteger;
46
use phpseclib3\Math\BinaryField;
47
use 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
 */
55
abstract 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
    /**
1042 daniel-mar 221
     * HMAC Key
222
     *
223
     * @see self::setupGCM()
224
     * @var ?string
225
     */
226
    protected $hKey = false;
227
 
228
    /**
827 daniel-mar 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
    /**
1042 daniel-mar 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
    /**
827 daniel-mar 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;
1042 daniel-mar 658
 
659
        static::initialize_static_variables();
827 daniel-mar 660
    }
661
 
662
    /**
1042 daniel-mar 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':
1441 daniel-mar 671
                case !function_exists('php_uname'):
672
                case !is_string(php_uname('m')):
673
                case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
1042 daniel-mar 674
                case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
675
                    self::$use_reg_intval = true;
676
                    break;
1441 daniel-mar 677
                case (php_uname('m') & "\xDF\xDF\xDF") == 'ARM':
1042 daniel-mar 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
    /**
827 daniel-mar 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
1042 daniel-mar 912
     *     {@link https://en.wikipedia.org/wiki/Bcrypt bcypt}:
913
     *         $salt, $rounds, $keylen
827 daniel-mar 914
     *
1042 daniel-mar 915
     *         This is a modified version of bcrypt used by OpenSSH.
916
     *
827 daniel-mar 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
1261 daniel-mar 922
     * @param int|string ...$func_args
827 daniel-mar 923
     * @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
1042 daniel-mar 924
     * @throws \RuntimeException if bcrypt is being used and a salt isn't provided
827 daniel-mar 925
     * @return bool
926
     */
927
    public function setPassword($password, $method = 'pbkdf2', ...$func_args)
928
    {
929
        $key = '';
930
 
931
        $method = strtolower($method);
932
        switch ($method) {
1042 daniel-mar 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;
827 daniel-mar 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;
1042 daniel-mar 1593
                        $pos = &$this->debuffer['pos'];
827 daniel-mar 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
        }
1042 daniel-mar 2330
        $engine = is_string($engine) ? strtolower($engine) : '';
827 daniel-mar 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
    {
1042 daniel-mar 3220
        if (is_int($x)) {
3221
            return $x;
827 daniel-mar 3222
        }
1042 daniel-mar 3223
 
3224
        if (self::$use_reg_intval) {
3225
            return PHP_INT_SIZE == 4 && PHP_VERSION_ID >= 80100 ? intval($x) : $x;
3226
        }
3227
 
827 daniel-mar 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
    {
1042 daniel-mar 3239
        if (self::$use_reg_intval) {
3240
            return PHP_INT_SIZE == 4 && PHP_VERSION_ID >= 80100 ? 'intval(%s)' : '%s';
827 daniel-mar 3241
        }
1042 daniel-mar 3242
 
3243
        $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
3244
        return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
827 daniel-mar 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
1042 daniel-mar 3257
        if (!$this->h || $this->hKey != $this->key) {
827 daniel-mar 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
            );
1042 daniel-mar 3265
            $this->hKey = $this->key;
827 daniel-mar 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
    }
1042 daniel-mar 3388
 
3389
    /**
3390
     * Is the continuous buffer enabled?
3391
     *
3392
     * @return boolean
3393
     */
3394
    public function continuousBufferEnabled()
3395
    {
3396
        return $this->continuousBuffer;
3397
    }
827 daniel-mar 3398
}