Subversion Repositories oidplus

Rev

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