1<?php
2
3/**
4 * Pure-PHP PKCS#1 (v2.1) compliant implementation of RSA.
5 *
6 * PHP version 5
7 *
8 * Here's an example of how to encrypt and decrypt text with this library:
9 * <code>
10 * <?php
11 * include 'vendor/autoload.php';
12 *
13 * $private = Crypt\RSA::createKey();
14 * $public = $private->getPublicKey();
15 *
16 * $plaintext = 'terrafrost';
17 *
18 * $ciphertext = $public->encrypt($plaintext);
19 *
20 * echo $private->decrypt($ciphertext);
21 * ?>
22 * </code>
23 *
24 * Here's an example of how to create signatures and verify signatures with this library:
25 * <code>
26 * <?php
27 * include 'vendor/autoload.php';
28 *
29 * $private = Crypt\RSA::createKey();
30 * $public = $private->getPublicKey();
31 *
32 * $plaintext = 'terrafrost';
33 *
34 * $signature = $private->sign($plaintext);
35 *
36 * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
37 * ?>
38 * </code>
39 *
40 * One thing to consider when using this: so phpseclib uses PSS mode by default.
41 * Technically, id-RSASSA-PSS has a different key format than rsaEncryption. So
42 * should phpseclib save to the id-RSASSA-PSS format by default or the
43 * rsaEncryption format? For stand-alone keys I figure rsaEncryption is better
44 * because SSH doesn't use PSS and idk how many SSH servers would be able to
45 * decode an id-RSASSA-PSS key. For X.509 certificates the id-RSASSA-PSS
46 * format is used by default (unless you change it up to use PKCS1 instead)
47 *
48 * @author    Jim Wigginton <terrafrost@php.net>
49 * @copyright 2009 Jim Wigginton
50 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
51 * @link      http://phpseclib.sourceforge.net
52 */
53
54namespace phpseclib3\Crypt;
55
56use phpseclib3\Crypt\Common\AsymmetricKey;
57use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
58use phpseclib3\Crypt\RSA\PrivateKey;
59use phpseclib3\Crypt\RSA\PublicKey;
60use phpseclib3\Exception\InconsistentSetupException;
61use phpseclib3\Exception\UnsupportedAlgorithmException;
62use phpseclib3\Math\BigInteger;
63
64/**
65 * Pure-PHP PKCS#1 compliant implementation of RSA.
66 *
67 * @author  Jim Wigginton <terrafrost@php.net>
68 */
69abstract class RSA extends AsymmetricKey
70{
71    /**
72     * Algorithm Name
73     *
74     * @var string
75     */
76    const ALGORITHM = 'RSA';
77
78    /**
79     * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
80     * (OAEP) for encryption / decryption.
81     *
82     * Uses sha256 by default
83     *
84     * @see self::setHash()
85     * @see self::setMGFHash()
86     * @see self::encrypt()
87     * @see self::decrypt()
88     */
89    const ENCRYPTION_OAEP = 1;
90
91    /**
92     * Use PKCS#1 padding.
93     *
94     * Although self::PADDING_OAEP / self::PADDING_PSS  offers more security, including PKCS#1 padding is necessary for purposes of backwards
95     * compatibility with protocols (like SSH-1) written before OAEP's introduction.
96     *
97     * @see self::encrypt()
98     * @see self::decrypt()
99     */
100    const ENCRYPTION_PKCS1 = 2;
101
102    /**
103     * Do not use any padding
104     *
105     * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
106     * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
107     *
108     * @see self::encrypt()
109     * @see self::decrypt()
110     */
111    const ENCRYPTION_NONE = 4;
112
113    /**
114     * Use the Probabilistic Signature Scheme for signing
115     *
116     * Uses sha256 and 0 as the salt length
117     *
118     * @see self::setSaltLength()
119     * @see self::setMGFHash()
120     * @see self::setHash()
121     * @see self::sign()
122     * @see self::verify()
123     * @see self::setHash()
124     */
125    const SIGNATURE_PSS = 16;
126
127    /**
128     * Use a relaxed version of PKCS#1 padding for signature verification
129     *
130     * @see self::sign()
131     * @see self::verify()
132     * @see self::setHash()
133     */
134    const SIGNATURE_RELAXED_PKCS1 = 32;
135
136    /**
137     * Use PKCS#1 padding for signature verification
138     *
139     * @see self::sign()
140     * @see self::verify()
141     * @see self::setHash()
142     */
143    const SIGNATURE_PKCS1 = 64;
144
145    /**
146     * Encryption padding mode
147     *
148     * @var int
149     */
150    protected $encryptionPadding = self::ENCRYPTION_OAEP;
151
152    /**
153     * Signature padding mode
154     *
155     * @var int
156     */
157    protected $signaturePadding = self::SIGNATURE_PSS;
158
159    /**
160     * Length of hash function output
161     *
162     * @var int
163     */
164    protected $hLen;
165
166    /**
167     * Length of salt
168     *
169     * @var int
170     */
171    protected $sLen;
172
173    /**
174     * Label
175     *
176     * @var string
177     */
178    protected $label = '';
179
180    /**
181     * Hash function for the Mask Generation Function
182     *
183     * @var Hash
184     */
185    protected $mgfHash;
186
187    /**
188     * Length of MGF hash function output
189     *
190     * @var int
191     */
192    protected $mgfHLen;
193
194    /**
195     * Modulus (ie. n)
196     *
197     * @var Math\BigInteger
198     */
199    protected $modulus;
200
201    /**
202     * Modulus length
203     *
204     * @var Math\BigInteger
205     */
206    protected $k;
207
208    /**
209     * Exponent (ie. e or d)
210     *
211     * @var Math\BigInteger
212     */
213    protected $exponent;
214
215    /**
216     * Default public exponent
217     *
218     * @var int
219     * @link http://en.wikipedia.org/wiki/65537_%28number%29
220     */
221    private static $defaultExponent = 65537;
222
223    /**
224     * Enable Blinding?
225     *
226     * @var bool
227     */
228    protected static $enableBlinding = true;
229
230    /**
231     * OpenSSL configuration file name.
232     *
233     * @see self::createKey()
234     * @var ?string
235     */
236    protected static $configFile;
237
238    /**
239     * Smallest Prime
240     *
241     * Per <http://cseweb.ucsd.edu/~hovav/dist/survey.pdf#page=5>, this number ought not result in primes smaller
242     * than 256 bits. As a consequence if the key you're trying to create is 1024 bits and you've set smallestPrime
243     * to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). At least if
244     * engine is set to self::ENGINE_INTERNAL. If Engine is set to self::ENGINE_OPENSSL then smallest Prime is
245     * ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key generation when there's
246     * a chance neither gmp nor OpenSSL are installed)
247     *
248     * @var int
249     */
250    private static $smallestPrime = 4096;
251
252    /**
253     * Public Exponent
254     *
255     * @var Math\BigInteger
256     */
257    protected $publicExponent;
258
259    /**
260     * Sets the public exponent for key generation
261     *
262     * This will be 65537 unless changed.
263     *
264     * @param int $val
265     */
266    public static function setExponent($val)
267    {
268        self::$defaultExponent = $val;
269    }
270
271    /**
272     * Sets the smallest prime number in bits. Used for key generation
273     *
274     * This will be 4096 unless changed.
275     *
276     * @param int $val
277     */
278    public static function setSmallestPrime($val)
279    {
280        self::$smallestPrime = $val;
281    }
282
283    /**
284     * Sets the OpenSSL config file path
285     *
286     * Set to the empty string to use the default config file
287     *
288     * @param string $val
289     */
290    public static function setOpenSSLConfigPath($val)
291    {
292        self::$configFile = $val;
293    }
294
295    /**
296     * Create a private key
297     *
298     * The public key can be extracted from the private key
299     *
300     * @return PrivateKey
301     * @param int $bits
302     */
303    public static function createKey($bits = 2048)
304    {
305        self::initialize_static_variables();
306
307        $class = new \ReflectionClass(static::class);
308        if ($class->isFinal()) {
309            throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
310        }
311
312        $regSize = $bits >> 1; // divide by two to see how many bits P and Q would be
313        if ($regSize > self::$smallestPrime) {
314            $num_primes = floor($bits / self::$smallestPrime);
315            $regSize = self::$smallestPrime;
316        } else {
317            $num_primes = 2;
318        }
319
320        if ($num_primes == 2 && $bits >= 384 && self::$defaultExponent == 65537) {
321            if (!isset(self::$engines['PHP'])) {
322                self::useBestEngine();
323            }
324
325            // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
326            if (self::$engines['OpenSSL']) {
327                $config = [];
328                if (self::$configFile) {
329                    $config['config'] = self::$configFile;
330                }
331                $rsa = openssl_pkey_new(['private_key_bits' => $bits] + $config);
332                openssl_pkey_export($rsa, $privatekeystr, null, $config);
333
334                // clear the buffer of error strings stemming from a minimalistic openssl.cnf
335                // https://github.com/php/php-src/issues/11054 talks about other errors this'll pick up
336                while (openssl_error_string() !== false) {
337                }
338
339                return RSA::load($privatekeystr);
340            }
341        }
342
343        static $e;
344        if (!isset($e)) {
345            $e = new BigInteger(self::$defaultExponent);
346        }
347
348        $n = clone self::$one;
349        $exponents = $coefficients = $primes = [];
350        $lcm = [
351            'top' => clone self::$one,
352            'bottom' => false
353        ];
354
355        do {
356            for ($i = 1; $i <= $num_primes; $i++) {
357                if ($i != $num_primes) {
358                    $primes[$i] = BigInteger::randomPrime($regSize);
359                } else {
360                    extract(BigInteger::minMaxBits($bits));
361                    /** @var BigInteger $min
362                     *  @var BigInteger $max
363                     */
364                    list($min) = $min->divide($n);
365                    $min = $min->add(self::$one);
366                    list($max) = $max->divide($n);
367                    $primes[$i] = BigInteger::randomRangePrime($min, $max);
368                }
369
370                // the first coefficient is calculated differently from the rest
371                // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1])
372                if ($i > 2) {
373                    $coefficients[$i] = $n->modInverse($primes[$i]);
374                }
375
376                $n = $n->multiply($primes[$i]);
377
378                $temp = $primes[$i]->subtract(self::$one);
379
380                // textbook RSA implementations use Euler's totient function instead of the least common multiple.
381                // see http://en.wikipedia.org/wiki/Euler%27s_totient_function
382                $lcm['top'] = $lcm['top']->multiply($temp);
383                $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp);
384            }
385
386            list($temp) = $lcm['top']->divide($lcm['bottom']);
387            $gcd = $temp->gcd($e);
388            $i0 = 1;
389        } while (!$gcd->equals(self::$one));
390
391        $coefficients[2] = $primes[2]->modInverse($primes[1]);
392
393        $d = $e->modInverse($temp);
394
395        foreach ($primes as $i => $prime) {
396            $temp = $prime->subtract(self::$one);
397            $exponents[$i] = $e->modInverse($temp);
398        }
399
400        // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.2>:
401        // RSAPrivateKey ::= SEQUENCE {
402        //     version           Version,
403        //     modulus           INTEGER,  -- n
404        //     publicExponent    INTEGER,  -- e
405        //     privateExponent   INTEGER,  -- d
406        //     prime1            INTEGER,  -- p
407        //     prime2            INTEGER,  -- q
408        //     exponent1         INTEGER,  -- d mod (p-1)
409        //     exponent2         INTEGER,  -- d mod (q-1)
410        //     coefficient       INTEGER,  -- (inverse of q) mod p
411        //     otherPrimeInfos   OtherPrimeInfos OPTIONAL
412        // }
413        $privatekey = new PrivateKey();
414        $privatekey->modulus = $n;
415        $privatekey->k = $bits >> 3;
416        $privatekey->publicExponent = $e;
417        $privatekey->exponent = $d;
418        $privatekey->primes = $primes;
419        $privatekey->exponents = $exponents;
420        $privatekey->coefficients = $coefficients;
421
422        /*
423        $publickey = new PublicKey;
424        $publickey->modulus = $n;
425        $publickey->k = $bits >> 3;
426        $publickey->exponent = $e;
427        $publickey->publicExponent = $e;
428        $publickey->isPublic = true;
429        */
430
431        return $privatekey;
432    }
433
434    /**
435     * OnLoad Handler
436     *
437     * @return bool
438     */
439    protected static function onLoad(array $components)
440    {
441        $key = $components['isPublicKey'] ?
442            new PublicKey() :
443            new PrivateKey();
444
445        $key->modulus = $components['modulus'];
446        $key->publicExponent = $components['publicExponent'];
447        $key->k = $key->modulus->getLengthInBytes();
448
449        if ($components['isPublicKey'] || !isset($components['privateExponent'])) {
450            $key->exponent = $key->publicExponent;
451        } else {
452            $key->privateExponent = $components['privateExponent'];
453            $key->exponent = $key->privateExponent;
454            $key->primes = $components['primes'];
455            $key->exponents = $components['exponents'];
456            $key->coefficients = $components['coefficients'];
457        }
458
459        if ($components['format'] == PSS::class) {
460            // in the X509 world RSA keys are assumed to use PKCS1 padding by default. only if the key is
461            // explicitly a PSS key is the use of PSS assumed. phpseclib does not work like this. phpseclib
462            // uses PSS padding by default. it assumes the more secure method by default and altho it provides
463            // for the less secure PKCS1 method you have to go out of your way to use it. this is consistent
464            // with the latest trends in crypto. libsodium (NaCl) is actually a little more extreme in that
465            // not only does it defaults to the most secure methods - it doesn't even let you choose less
466            // secure methods
467            //$key = $key->withPadding(self::SIGNATURE_PSS);
468            if (isset($components['hash'])) {
469                $key = $key->withHash($components['hash']);
470            }
471            if (isset($components['MGFHash'])) {
472                $key = $key->withMGFHash($components['MGFHash']);
473            }
474            if (isset($components['saltLength'])) {
475                $key = $key->withSaltLength($components['saltLength']);
476            }
477        }
478
479        return $key;
480    }
481
482    /**
483     * Initialize static variables
484     */
485    protected static function initialize_static_variables()
486    {
487        if (!isset(self::$configFile)) {
488            self::$configFile = dirname(__FILE__) . '/../openssl.cnf';
489        }
490
491        parent::initialize_static_variables();
492    }
493
494    /**
495     * Constructor
496     *
497     * PublicKey and PrivateKey objects can only be created from abstract RSA class
498     */
499    protected function __construct()
500    {
501        parent::__construct();
502
503        $this->hLen = $this->hash->getLengthInBytes();
504        $this->mgfHash = new Hash('sha256');
505        $this->mgfHLen = $this->mgfHash->getLengthInBytes();
506    }
507
508    /**
509     * Integer-to-Octet-String primitive
510     *
511     * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
512     *
513     * @param bool|Math\BigInteger $x
514     * @param int $xLen
515     * @return bool|string
516     */
517    protected function i2osp($x, $xLen)
518    {
519        if ($x === false) {
520            return false;
521        }
522        $x = $x->toBytes();
523        if (strlen($x) > $xLen) {
524            throw new \OutOfRangeException('Resultant string length out of range');
525        }
526        return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
527    }
528
529    /**
530     * Octet-String-to-Integer primitive
531     *
532     * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
533     *
534     * @param string $x
535     * @return Math\BigInteger
536     */
537    protected function os2ip($x)
538    {
539        return new BigInteger($x, 256);
540    }
541
542    /**
543     * EMSA-PKCS1-V1_5-ENCODE
544     *
545     * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
546     *
547     * @param string $m
548     * @param int $emLen
549     * @throws \LengthException if the intended encoded message length is too short
550     * @return string
551     */
552    protected function emsa_pkcs1_v1_5_encode($m, $emLen)
553    {
554        $h = $this->hash->hash($m);
555
556        // see http://tools.ietf.org/html/rfc3447#page-43
557        switch ($this->hash->getHash()) {
558            case 'md2':
559                $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02\x05\x00\x04\x10";
560                break;
561            case 'md5':
562                $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10";
563                break;
564            case 'sha1':
565                $t = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14";
566                break;
567            case 'sha256':
568                $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
569                break;
570            case 'sha384':
571                $t = "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30";
572                break;
573            case 'sha512':
574                $t = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40";
575                break;
576            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
577            case 'sha224':
578                $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c";
579                break;
580            case 'sha512/224':
581                $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x05\x00\x04\x1c";
582                break;
583            case 'sha512/256':
584                $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x05\x00\x04\x20";
585        }
586        $t .= $h;
587        $tLen = strlen($t);
588
589        if ($emLen < $tLen + 11) {
590            throw new \LengthException('Intended encoded message length too short');
591        }
592
593        $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
594
595        $em = "\0\1$ps\0$t";
596
597        return $em;
598    }
599
600    /**
601     * EMSA-PKCS1-V1_5-ENCODE (without NULL)
602     *
603     * Quoting https://tools.ietf.org/html/rfc8017#page-65,
604     *
605     * "The parameters field associated with id-sha1, id-sha224, id-sha256,
606     *  id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should
607     *  generally be omitted, but if present, it shall have a value of type
608     *  NULL"
609     *
610     * @param string $m
611     * @param int $emLen
612     * @return string
613     */
614    protected function emsa_pkcs1_v1_5_encode_without_null($m, $emLen)
615    {
616        $h = $this->hash->hash($m);
617
618        // see http://tools.ietf.org/html/rfc3447#page-43
619        switch ($this->hash->getHash()) {
620            case 'sha1':
621                $t = "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14";
622                break;
623            case 'sha256':
624                $t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x04\x20";
625                break;
626            case 'sha384':
627                $t = "\x30\x3f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x04\x30";
628                break;
629            case 'sha512':
630                $t = "\x30\x4f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x04\x40";
631                break;
632            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
633            case 'sha224':
634                $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x04\x1c";
635                break;
636            case 'sha512/224':
637                $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x04\x1c";
638                break;
639            case 'sha512/256':
640                $t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x04\x20";
641                break;
642            default:
643                throw new UnsupportedAlgorithmException('md2 and md5 require NULLs');
644        }
645        $t .= $h;
646        $tLen = strlen($t);
647
648        if ($emLen < $tLen + 11) {
649            throw new \LengthException('Intended encoded message length too short');
650        }
651
652        $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
653
654        $em = "\0\1$ps\0$t";
655
656        return $em;
657    }
658
659    /**
660     * MGF1
661     *
662     * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
663     *
664     * @param string $mgfSeed
665     * @param int $maskLen
666     * @return string
667     */
668    protected function mgf1($mgfSeed, $maskLen)
669    {
670        // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
671
672        $t = '';
673        $count = ceil($maskLen / $this->mgfHLen);
674        for ($i = 0; $i < $count; $i++) {
675            $c = pack('N', $i);
676            $t .= $this->mgfHash->hash($mgfSeed . $c);
677        }
678
679        return substr($t, 0, $maskLen);
680    }
681
682    /**
683     * Returns the key size
684     *
685     * More specifically, this returns the size of the modulo in bits.
686     *
687     * @return int
688     */
689    public function getLength()
690    {
691        return !isset($this->modulus) ? 0 : $this->modulus->getLength();
692    }
693
694    /**
695     * Determines which hashing function should be used
696     *
697     * Used with signature production / verification and (if the encryption mode is self::PADDING_OAEP) encryption and
698     * decryption.
699     *
700     * @param string $hash
701     */
702    public function withHash($hash)
703    {
704        $new = clone $this;
705
706        // Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
707        switch (strtolower($hash)) {
708            case 'md2':
709            case 'md5':
710            case 'sha1':
711            case 'sha256':
712            case 'sha384':
713            case 'sha512':
714            case 'sha224':
715            case 'sha512/224':
716            case 'sha512/256':
717                $new->hash = new Hash($hash);
718                break;
719            default:
720                throw new UnsupportedAlgorithmException(
721                    'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256'
722                );
723        }
724        $new->hLen = $new->hash->getLengthInBytes();
725
726        return $new;
727    }
728
729    /**
730     * Determines which hashing function should be used for the mask generation function
731     *
732     * The mask generation function is used by self::PADDING_OAEP and self::PADDING_PSS and although it's
733     * best if Hash and MGFHash are set to the same thing this is not a requirement.
734     *
735     * @param string $hash
736     */
737    public function withMGFHash($hash)
738    {
739        $new = clone $this;
740
741        // Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
742        switch (strtolower($hash)) {
743            case 'md2':
744            case 'md5':
745            case 'sha1':
746            case 'sha256':
747            case 'sha384':
748            case 'sha512':
749            case 'sha224':
750            case 'sha512/224':
751            case 'sha512/256':
752                $new->mgfHash = new Hash($hash);
753                break;
754            default:
755                throw new UnsupportedAlgorithmException(
756                    'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256'
757                );
758        }
759        $new->mgfHLen = $new->mgfHash->getLengthInBytes();
760
761        return $new;
762    }
763
764    /**
765     * Returns the MGF hash algorithm currently being used
766     *
767     */
768    public function getMGFHash()
769    {
770        return clone $this->mgfHash;
771    }
772
773    /**
774     * Determines the salt length
775     *
776     * Used by RSA::PADDING_PSS
777     *
778     * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}:
779     *
780     *    Typical salt lengths in octets are hLen (the length of the output
781     *    of the hash function Hash) and 0.
782     *
783     * @param int $sLen
784     */
785    public function withSaltLength($sLen)
786    {
787        $new = clone $this;
788        $new->sLen = $sLen;
789        return $new;
790    }
791
792    /**
793     * Returns the salt length currently being used
794     *
795     */
796    public function getSaltLength()
797    {
798        return $this->sLen !== null ? $this->sLen : $this->hLen;
799    }
800
801    /**
802     * Determines the label
803     *
804     * Used by RSA::PADDING_OAEP
805     *
806     * To quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}:
807     *
808     *    Both the encryption and the decryption operations of RSAES-OAEP take
809     *    the value of a label L as input.  In this version of PKCS #1, L is
810     *    the empty string; other uses of the label are outside the scope of
811     *    this document.
812     *
813     * @param string $label
814     */
815    public function withLabel($label)
816    {
817        $new = clone $this;
818        $new->label = $label;
819        return $new;
820    }
821
822    /**
823     * Returns the label currently being used
824     *
825     */
826    public function getLabel()
827    {
828        return $this->label;
829    }
830
831    /**
832     * Determines the padding modes
833     *
834     * Example: $key->withPadding(RSA::ENCRYPTION_PKCS1 | RSA::SIGNATURE_PKCS1);
835     *
836     * @param int $padding
837     */
838    public function withPadding($padding)
839    {
840        $masks = [
841            self::ENCRYPTION_OAEP,
842            self::ENCRYPTION_PKCS1,
843            self::ENCRYPTION_NONE
844        ];
845        $encryptedCount = 0;
846        $selected = 0;
847        foreach ($masks as $mask) {
848            if ($padding & $mask) {
849                $selected = $mask;
850                $encryptedCount++;
851            }
852        }
853        if ($encryptedCount > 1) {
854            throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected');
855        }
856        $encryptionPadding = $selected;
857
858        $masks = [
859            self::SIGNATURE_PSS,
860            self::SIGNATURE_RELAXED_PKCS1,
861            self::SIGNATURE_PKCS1
862        ];
863        $signatureCount = 0;
864        $selected = 0;
865        foreach ($masks as $mask) {
866            if ($padding & $mask) {
867                $selected = $mask;
868                $signatureCount++;
869            }
870        }
871        if ($signatureCount > 1) {
872            throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected');
873        }
874        $signaturePadding = $selected;
875
876        $new = clone $this;
877        if ($encryptedCount) {
878            $new->encryptionPadding = $encryptionPadding;
879        }
880        if ($signatureCount) {
881            $new->signaturePadding = $signaturePadding;
882        }
883        return $new;
884    }
885
886    /**
887     * Returns the padding currently being used
888     *
889     */
890    public function getPadding()
891    {
892        return $this->signaturePadding | $this->encryptionPadding;
893    }
894
895    /**
896     * Returns the current engine being used
897     *
898     * OpenSSL is only used in this class (and it's subclasses) for key generation
899     * Even then it depends on the parameters you're using. It's not used for
900     * multi-prime RSA nor is it used if the key length is outside of the range
901     * supported by OpenSSL
902     *
903     * @see self::useInternalEngine()
904     * @see self::useBestEngine()
905     * @return string
906     */
907    public function getEngine()
908    {
909        if (!isset(self::$engines['PHP'])) {
910            self::useBestEngine();
911        }
912        return self::$engines['OpenSSL'] && self::$defaultExponent == 65537 ?
913            'OpenSSL' :
914            'PHP';
915    }
916
917    /**
918     * Enable RSA Blinding
919     *
920     */
921    public static function enableBlinding()
922    {
923        static::$enableBlinding = true;
924    }
925
926    /**
927     * Disable RSA Blinding
928     *
929     */
930    public static function disableBlinding()
931    {
932        static::$enableBlinding = false;
933    }
934}
935