Subversion Repositories oidplus

Rev

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