Rev 1101 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
827 | daniel-mar | 1 | <?php |
2 | |||
3 | /** |
||
4 | * 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 = \phpseclib3\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 = \phpseclib3\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 | |||
54 | namespace phpseclib3\Crypt; |
||
55 | |||
56 | use phpseclib3\Crypt\Common\AsymmetricKey; |
||
57 | use phpseclib3\Crypt\RSA\Formats\Keys\PSS; |
||
58 | use phpseclib3\Crypt\RSA\PrivateKey; |
||
59 | use phpseclib3\Crypt\RSA\PublicKey; |
||
60 | use phpseclib3\Exception\InconsistentSetupException; |
||
61 | use phpseclib3\Exception\UnsupportedAlgorithmException; |
||
62 | use phpseclib3\Math\BigInteger; |
||
63 | |||
64 | /** |
||
65 | * Pure-PHP PKCS#1 compliant implementation of RSA. |
||
66 | * |
||
67 | * @author Jim Wigginton <terrafrost@php.net> |
||
68 | */ |
||
69 | abstract 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 \phpseclib3\Crypt\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 \phpseclib3\Math\BigInteger |
||
198 | */ |
||
199 | protected $modulus; |
||
200 | |||
201 | /** |
||
202 | * Modulus length |
||
203 | * |
||
204 | * @var \phpseclib3\Math\BigInteger |
||
205 | */ |
||
206 | protected $k; |
||
207 | |||
208 | /** |
||
209 | * Exponent (ie. e or d) |
||
210 | * |
||
211 | * @var \phpseclib3\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 | /** |
||
1042 | daniel-mar | 253 | * Public Exponent |
254 | * |
||
255 | * @var \phpseclib3\Math\BigInteger |
||
256 | */ |
||
257 | protected $publicExponent; |
||
258 | |||
259 | /** |
||
827 | daniel-mar | 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 | * |
||
1042 | daniel-mar | 300 | * @return RSA\PrivateKey |
827 | daniel-mar | 301 | * @param int $bits |
302 | */ |
||
303 | public static function createKey($bits = 2048) |
||
304 | { |
||
305 | self::initialize_static_variables(); |
||
306 | |||
1101 | daniel-mar | 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 | |||
827 | daniel-mar | 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 | while (openssl_error_string() !== false) { |
||
336 | } |
||
337 | |||
338 | return RSA::load($privatekeystr); |
||
339 | } |
||
340 | } |
||
341 | |||
342 | static $e; |
||
343 | if (!isset($e)) { |
||
344 | $e = new BigInteger(self::$defaultExponent); |
||
345 | } |
||
346 | |||
347 | $n = clone self::$one; |
||
348 | $exponents = $coefficients = $primes = []; |
||
349 | $lcm = [ |
||
350 | 'top' => clone self::$one, |
||
351 | 'bottom' => false |
||
352 | ]; |
||
353 | |||
354 | do { |
||
355 | for ($i = 1; $i <= $num_primes; $i++) { |
||
356 | if ($i != $num_primes) { |
||
357 | $primes[$i] = BigInteger::randomPrime($regSize); |
||
358 | } else { |
||
359 | extract(BigInteger::minMaxBits($bits)); |
||
360 | /** @var BigInteger $min |
||
361 | * @var BigInteger $max |
||
362 | */ |
||
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 | */ |
||
1042 | daniel-mar | 438 | protected static function onLoad(array $components) |
827 | daniel-mar | 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|\phpseclib3\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 \phpseclib3\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 | // \phpseclib3\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 | // \phpseclib3\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 | ]; |
||
1308 | daniel-mar | 844 | $encryptedCount = 0; |
827 | daniel-mar | 845 | $selected = 0; |
846 | foreach ($masks as $mask) { |
||
847 | if ($padding & $mask) { |
||
848 | $selected = $mask; |
||
1308 | daniel-mar | 849 | $encryptedCount++; |
827 | daniel-mar | 850 | } |
851 | } |
||
1308 | daniel-mar | 852 | if ($encryptedCount > 1) { |
827 | daniel-mar | 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 | ]; |
||
1308 | daniel-mar | 862 | $signatureCount = 0; |
827 | daniel-mar | 863 | $selected = 0; |
864 | foreach ($masks as $mask) { |
||
865 | if ($padding & $mask) { |
||
866 | $selected = $mask; |
||
1308 | daniel-mar | 867 | $signatureCount++; |
827 | daniel-mar | 868 | } |
869 | } |
||
1308 | daniel-mar | 870 | if ($signatureCount > 1) { |
827 | daniel-mar | 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; |
||
1308 | daniel-mar | 876 | if ($encryptedCount) { |
877 | $new->encryptionPadding = $encryptionPadding; |
||
878 | } |
||
879 | if ($signatureCount) { |
||
880 | $new->signaturePadding = $signaturePadding; |
||
881 | } |
||
827 | daniel-mar | 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 | } |