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