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