xref: /dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php (revision 8e88a29b81301f78509349ab1152bb09c229123e)
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                    $minMax = BigInteger::minMaxBits($bits);
361                    $min = $minMax['min'];
362                    $max = $minMax['max'];
363                    list($min) = $min->divide($n);
364                    $min = $min->add(self::$one);
365                    list($max) = $max->divide($n);
366                    $primes[$i] = BigInteger::randomRangePrime($min, $max);
367                }
368
369                // the first coefficient is calculated differently from the rest
370                // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1])
371                if ($i > 2) {
372                    $coefficients[$i] = $n->modInverse($primes[$i]);
373                }
374
375                $n = $n->multiply($primes[$i]);
376
377                $temp = $primes[$i]->subtract(self::$one);
378
379                // textbook RSA implementations use Euler's totient function instead of the least common multiple.
380                // see http://en.wikipedia.org/wiki/Euler%27s_totient_function
381                $lcm['top'] = $lcm['top']->multiply($temp);
382                $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp);
383            }
384
385            list($temp) = $lcm['top']->divide($lcm['bottom']);
386            $gcd = $temp->gcd($e);
387            $i0 = 1;
388        } while (!$gcd->equals(self::$one));
389
390        $coefficients[2] = $primes[2]->modInverse($primes[1]);
391
392        $d = $e->modInverse($temp);
393
394        foreach ($primes as $i => $prime) {
395            $temp = $prime->subtract(self::$one);
396            $exponents[$i] = $e->modInverse($temp);
397        }
398
399        // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.2>:
400        // RSAPrivateKey ::= SEQUENCE {
401        //     version           Version,
402        //     modulus           INTEGER,  -- n
403        //     publicExponent    INTEGER,  -- e
404        //     privateExponent   INTEGER,  -- d
405        //     prime1            INTEGER,  -- p
406        //     prime2            INTEGER,  -- q
407        //     exponent1         INTEGER,  -- d mod (p-1)
408        //     exponent2         INTEGER,  -- d mod (q-1)
409        //     coefficient       INTEGER,  -- (inverse of q) mod p
410        //     otherPrimeInfos   OtherPrimeInfos OPTIONAL
411        // }
412        $privatekey = new PrivateKey();
413        $privatekey->modulus = $n;
414        $privatekey->k = $bits >> 3;
415        $privatekey->publicExponent = $e;
416        $privatekey->exponent = $d;
417        $privatekey->primes = $primes;
418        $privatekey->exponents = $exponents;
419        $privatekey->coefficients = $coefficients;
420
421        /*
422        $publickey = new PublicKey;
423        $publickey->modulus = $n;
424        $publickey->k = $bits >> 3;
425        $publickey->exponent = $e;
426        $publickey->publicExponent = $e;
427        $publickey->isPublic = true;
428        */
429
430        return $privatekey;
431    }
432
433    /**
434     * OnLoad Handler
435     *
436     * @return bool
437     */
438    protected static function onLoad(array $components)
439    {
440        $key = $components['isPublicKey'] ?
441            new PublicKey() :
442            new PrivateKey();
443
444        $key->modulus = $components['modulus'];
445        $key->publicExponent = $components['publicExponent'];
446        $key->k = $key->modulus->getLengthInBytes();
447
448        if ($components['isPublicKey'] || !isset($components['privateExponent'])) {
449            $key->exponent = $key->publicExponent;
450        } else {
451            $key->privateExponent = $components['privateExponent'];
452            $key->exponent = $key->privateExponent;
453            $key->primes = $components['primes'];
454            $key->exponents = $components['exponents'];
455            $key->coefficients = $components['coefficients'];
456        }
457
458        if ($components['format'] == PSS::class) {
459            // in the X509 world RSA keys are assumed to use PKCS1 padding by default. only if the key is
460            // explicitly a PSS key is the use of PSS assumed. phpseclib does not work like this. phpseclib
461            // uses PSS padding by default. it assumes the more secure method by default and altho it provides
462            // for the less secure PKCS1 method you have to go out of your way to use it. this is consistent
463            // with the latest trends in crypto. libsodium (NaCl) is actually a little more extreme in that
464            // not only does it defaults to the most secure methods - it doesn't even let you choose less
465            // secure methods
466            //$key = $key->withPadding(self::SIGNATURE_PSS);
467            if (isset($components['hash'])) {
468                $key = $key->withHash($components['hash']);
469            }
470            if (isset($components['MGFHash'])) {
471                $key = $key->withMGFHash($components['MGFHash']);
472            }
473            if (isset($components['saltLength'])) {
474                $key = $key->withSaltLength($components['saltLength']);
475            }
476        }
477
478        return $key;
479    }
480
481    /**
482     * Initialize static variables
483     */
484    protected static function initialize_static_variables()
485    {
486        if (!isset(self::$configFile)) {
487            self::$configFile = dirname(__FILE__) . '/../openssl.cnf';
488        }
489
490        parent::initialize_static_variables();
491    }
492
493    /**
494     * Constructor
495     *
496     * PublicKey and PrivateKey objects can only be created from abstract RSA class
497     */
498    protected function __construct()
499    {
500        parent::__construct();
501
502        $this->hLen = $this->hash->getLengthInBytes();
503        $this->mgfHash = new Hash('sha256');
504        $this->mgfHLen = $this->mgfHash->getLengthInBytes();
505    }
506
507    /**
508     * Integer-to-Octet-String primitive
509     *
510     * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
511     *
512     * @param bool|Math\BigInteger $x
513     * @param int $xLen
514     * @return bool|string
515     */
516    protected function i2osp($x, $xLen)
517    {
518        if ($x === false) {
519            return false;
520        }
521        $x = $x->toBytes();
522        if (strlen($x) > $xLen) {
523            throw new \OutOfRangeException('Resultant string length out of range');
524        }
525        return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
526    }
527
528    /**
529     * Octet-String-to-Integer primitive
530     *
531     * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
532     *
533     * @param string $x
534     * @return Math\BigInteger
535     */
536    protected function os2ip($x)
537    {
538        return new BigInteger($x, 256);
539    }
540
541    /**
542     * EMSA-PKCS1-V1_5-ENCODE
543     *
544     * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
545     *
546     * @param string $m
547     * @param int $emLen
548     * @throws \LengthException if the intended encoded message length is too short
549     * @return string
550     */
551    protected function emsa_pkcs1_v1_5_encode($m, $emLen)
552    {
553        $h = $this->hash->hash($m);
554
555        // see http://tools.ietf.org/html/rfc3447#page-43
556        switch ($this->hash->getHash()) {
557            case 'md2':
558                $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02\x05\x00\x04\x10";
559                break;
560            case 'md5':
561                $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10";
562                break;
563            case 'sha1':
564                $t = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14";
565                break;
566            case 'sha256':
567                $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
568                break;
569            case 'sha384':
570                $t = "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30";
571                break;
572            case 'sha512':
573                $t = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40";
574                break;
575            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
576            case 'sha224':
577                $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c";
578                break;
579            case 'sha512/224':
580                $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x05\x00\x04\x1c";
581                break;
582            case 'sha512/256':
583                $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x05\x00\x04\x20";
584        }
585        $t .= $h;
586        $tLen = strlen($t);
587
588        if ($emLen < $tLen + 11) {
589            throw new \LengthException('Intended encoded message length too short');
590        }
591
592        $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
593
594        $em = "\0\1$ps\0$t";
595
596        return $em;
597    }
598
599    /**
600     * EMSA-PKCS1-V1_5-ENCODE (without NULL)
601     *
602     * Quoting https://tools.ietf.org/html/rfc8017#page-65,
603     *
604     * "The parameters field associated with id-sha1, id-sha224, id-sha256,
605     *  id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should
606     *  generally be omitted, but if present, it shall have a value of type
607     *  NULL"
608     *
609     * @param string $m
610     * @param int $emLen
611     * @return string
612     */
613    protected function emsa_pkcs1_v1_5_encode_without_null($m, $emLen)
614    {
615        $h = $this->hash->hash($m);
616
617        // see http://tools.ietf.org/html/rfc3447#page-43
618        switch ($this->hash->getHash()) {
619            case 'sha1':
620                $t = "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14";
621                break;
622            case 'sha256':
623                $t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x04\x20";
624                break;
625            case 'sha384':
626                $t = "\x30\x3f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x04\x30";
627                break;
628            case 'sha512':
629                $t = "\x30\x4f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x04\x40";
630                break;
631            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
632            case 'sha224':
633                $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x04\x1c";
634                break;
635            case 'sha512/224':
636                $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x04\x1c";
637                break;
638            case 'sha512/256':
639                $t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x04\x20";
640                break;
641            default:
642                throw new UnsupportedAlgorithmException('md2 and md5 require NULLs');
643        }
644        $t .= $h;
645        $tLen = strlen($t);
646
647        if ($emLen < $tLen + 11) {
648            throw new \LengthException('Intended encoded message length too short');
649        }
650
651        $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
652
653        $em = "\0\1$ps\0$t";
654
655        return $em;
656    }
657
658    /**
659     * MGF1
660     *
661     * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
662     *
663     * @param string $mgfSeed
664     * @param int $maskLen
665     * @return string
666     */
667    protected function mgf1($mgfSeed, $maskLen)
668    {
669        // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
670
671        $t = '';
672        $count = ceil($maskLen / $this->mgfHLen);
673        for ($i = 0; $i < $count; $i++) {
674            $c = pack('N', $i);
675            $t .= $this->mgfHash->hash($mgfSeed . $c);
676        }
677
678        return substr($t, 0, $maskLen);
679    }
680
681    /**
682     * Returns the key size
683     *
684     * More specifically, this returns the size of the modulo in bits.
685     *
686     * @return int
687     */
688    public function getLength()
689    {
690        return !isset($this->modulus) ? 0 : $this->modulus->getLength();
691    }
692
693    /**
694     * Determines which hashing function should be used
695     *
696     * Used with signature production / verification and (if the encryption mode is self::PADDING_OAEP) encryption and
697     * decryption.
698     *
699     * @param string $hash
700     */
701    public function withHash($hash)
702    {
703        $new = clone $this;
704
705        // Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
706        switch (strtolower($hash)) {
707            case 'md2':
708            case 'md5':
709            case 'sha1':
710            case 'sha256':
711            case 'sha384':
712            case 'sha512':
713            case 'sha224':
714            case 'sha512/224':
715            case 'sha512/256':
716                $new->hash = new Hash($hash);
717                break;
718            default:
719                throw new UnsupportedAlgorithmException(
720                    'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256'
721                );
722        }
723        $new->hLen = $new->hash->getLengthInBytes();
724
725        return $new;
726    }
727
728    /**
729     * Determines which hashing function should be used for the mask generation function
730     *
731     * The mask generation function is used by self::PADDING_OAEP and self::PADDING_PSS and although it's
732     * best if Hash and MGFHash are set to the same thing this is not a requirement.
733     *
734     * @param string $hash
735     */
736    public function withMGFHash($hash)
737    {
738        $new = clone $this;
739
740        // Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
741        switch (strtolower($hash)) {
742            case 'md2':
743            case 'md5':
744            case 'sha1':
745            case 'sha256':
746            case 'sha384':
747            case 'sha512':
748            case 'sha224':
749            case 'sha512/224':
750            case 'sha512/256':
751                $new->mgfHash = new Hash($hash);
752                break;
753            default:
754                throw new UnsupportedAlgorithmException(
755                    'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256'
756                );
757        }
758        $new->mgfHLen = $new->mgfHash->getLengthInBytes();
759
760        return $new;
761    }
762
763    /**
764     * Returns the MGF hash algorithm currently being used
765     *
766     */
767    public function getMGFHash()
768    {
769        return clone $this->mgfHash;
770    }
771
772    /**
773     * Determines the salt length
774     *
775     * Used by RSA::PADDING_PSS
776     *
777     * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}:
778     *
779     *    Typical salt lengths in octets are hLen (the length of the output
780     *    of the hash function Hash) and 0.
781     *
782     * @param int $sLen
783     */
784    public function withSaltLength($sLen)
785    {
786        $new = clone $this;
787        $new->sLen = $sLen;
788        return $new;
789    }
790
791    /**
792     * Returns the salt length currently being used
793     *
794     */
795    public function getSaltLength()
796    {
797        return $this->sLen !== null ? $this->sLen : $this->hLen;
798    }
799
800    /**
801     * Determines the label
802     *
803     * Used by RSA::PADDING_OAEP
804     *
805     * To quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}:
806     *
807     *    Both the encryption and the decryption operations of RSAES-OAEP take
808     *    the value of a label L as input.  In this version of PKCS #1, L is
809     *    the empty string; other uses of the label are outside the scope of
810     *    this document.
811     *
812     * @param string $label
813     */
814    public function withLabel($label)
815    {
816        $new = clone $this;
817        $new->label = $label;
818        return $new;
819    }
820
821    /**
822     * Returns the label currently being used
823     *
824     */
825    public function getLabel()
826    {
827        return $this->label;
828    }
829
830    /**
831     * Determines the padding modes
832     *
833     * Example: $key->withPadding(RSA::ENCRYPTION_PKCS1 | RSA::SIGNATURE_PKCS1);
834     *
835     * @param int $padding
836     */
837    public function withPadding($padding)
838    {
839        $masks = [
840            self::ENCRYPTION_OAEP,
841            self::ENCRYPTION_PKCS1,
842            self::ENCRYPTION_NONE
843        ];
844        $encryptedCount = 0;
845        $selected = 0;
846        foreach ($masks as $mask) {
847            if ($padding & $mask) {
848                $selected = $mask;
849                $encryptedCount++;
850            }
851        }
852        if ($encryptedCount > 1) {
853            throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected');
854        }
855        $encryptionPadding = $selected;
856
857        $masks = [
858            self::SIGNATURE_PSS,
859            self::SIGNATURE_RELAXED_PKCS1,
860            self::SIGNATURE_PKCS1
861        ];
862        $signatureCount = 0;
863        $selected = 0;
864        foreach ($masks as $mask) {
865            if ($padding & $mask) {
866                $selected = $mask;
867                $signatureCount++;
868            }
869        }
870        if ($signatureCount > 1) {
871            throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected');
872        }
873        $signaturePadding = $selected;
874
875        $new = clone $this;
876        if ($encryptedCount) {
877            $new->encryptionPadding = $encryptionPadding;
878        }
879        if ($signatureCount) {
880            $new->signaturePadding = $signaturePadding;
881        }
882        return $new;
883    }
884
885    /**
886     * Returns the padding currently being used
887     *
888     */
889    public function getPadding()
890    {
891        return $this->signaturePadding | $this->encryptionPadding;
892    }
893
894    /**
895     * Returns the current engine being used
896     *
897     * OpenSSL is only used in this class (and it's subclasses) for key generation
898     * Even then it depends on the parameters you're using. It's not used for
899     * multi-prime RSA nor is it used if the key length is outside of the range
900     * supported by OpenSSL
901     *
902     * @see self::useInternalEngine()
903     * @see self::useBestEngine()
904     * @return string
905     */
906    public function getEngine()
907    {
908        if (!isset(self::$engines['PHP'])) {
909            self::useBestEngine();
910        }
911        return self::$engines['OpenSSL'] && self::$defaultExponent == 65537 ?
912            'OpenSSL' :
913            'PHP';
914    }
915
916    /**
917     * Enable RSA Blinding
918     *
919     */
920    public static function enableBlinding()
921    {
922        static::$enableBlinding = true;
923    }
924
925    /**
926     * Disable RSA Blinding
927     *
928     */
929    public static function disableBlinding()
930    {
931        static::$enableBlinding = false;
932    }
933}
934