These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * The MIT License (MIT) |
||
5 | * |
||
6 | * Copyright (c) 2014-2016 Spomky-Labs |
||
7 | * |
||
8 | * This software may be modified and distributed under the terms |
||
9 | * of the MIT license. See the LICENSE file for details. |
||
10 | */ |
||
11 | |||
12 | namespace Jose\Util; |
||
13 | |||
14 | use Base64Url\Base64Url; |
||
15 | use Jose\Object\JWKInterface; |
||
16 | |||
17 | final class RSA |
||
18 | { |
||
19 | /** |
||
20 | * Precomputed Zero. |
||
21 | * |
||
22 | * @var \Jose\Util\BigInteger |
||
23 | */ |
||
24 | private $zero; |
||
25 | |||
26 | /** |
||
27 | * Precomputed One. |
||
28 | * |
||
29 | * @var \Jose\Util\BigInteger |
||
30 | */ |
||
31 | private $one; |
||
32 | |||
33 | /** |
||
34 | * Modulus (ie. n). |
||
35 | * |
||
36 | * @var \Jose\Util\BigInteger |
||
37 | */ |
||
38 | private $modulus; |
||
39 | |||
40 | /** |
||
41 | * Modulus length. |
||
42 | * |
||
43 | * @var int |
||
44 | */ |
||
45 | private $k; |
||
46 | |||
47 | /** |
||
48 | * Exponent (ie. e or d). |
||
49 | * |
||
50 | * @var \Jose\Util\BigInteger |
||
51 | */ |
||
52 | private $exponent; |
||
53 | |||
54 | /** |
||
55 | * Primes for Chinese Remainder Theorem (ie. p and q). |
||
56 | * |
||
57 | * @var \Jose\Util\BigInteger[] |
||
58 | */ |
||
59 | private $primes; |
||
60 | |||
61 | /** |
||
62 | * Exponents for Chinese Remainder Theorem (ie. dP and dQ). |
||
63 | * |
||
64 | * @var \Jose\Util\BigInteger[] |
||
65 | */ |
||
66 | private $exponents; |
||
67 | |||
68 | /** |
||
69 | * Coefficients for Chinese Remainder Theorem (ie. qInv). |
||
70 | * |
||
71 | * @var \Jose\Util\BigInteger[] |
||
72 | */ |
||
73 | private $coefficients; |
||
74 | |||
75 | /** |
||
76 | * Hash function. |
||
77 | * |
||
78 | * @var \Jose\Util\Hash |
||
79 | */ |
||
80 | private $hash; |
||
81 | |||
82 | /** |
||
83 | * Hash function for the Mask Generation Function. |
||
84 | * |
||
85 | * @var \Jose\Util\Hash |
||
86 | */ |
||
87 | private $mgfHash; |
||
88 | |||
89 | /** |
||
90 | * Public Exponent. |
||
91 | * |
||
92 | * @var mixed |
||
93 | */ |
||
94 | private $publicExponent = false; |
||
95 | |||
96 | /** |
||
97 | * RSA constructor. |
||
98 | */ |
||
99 | public function __construct() |
||
100 | { |
||
101 | $this->zero = BigInteger::createFromDecimalString('0'); |
||
102 | $this->one = BigInteger::createFromDecimalString('1'); |
||
103 | |||
104 | $this->hash = Hash::sha1(); |
||
105 | $this->mgfHash = Hash::sha1(); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Loads a public or private key. |
||
110 | * |
||
111 | * @param \Jose\Object\JWKInterface $key |
||
112 | */ |
||
113 | public function loadKey(JWKInterface $key) |
||
114 | { |
||
115 | $this->modulus = BigInteger::createFromBinaryString(Base64Url::decode($key->get('n'))); |
||
116 | $this->k = strlen($this->modulus->toBytes()); |
||
117 | |||
118 | if ($key->has('d')) { |
||
119 | $this->exponent = BigInteger::createFromBinaryString(Base64Url::decode($key->get('d'))); |
||
120 | $this->publicExponent = BigInteger::createFromBinaryString(Base64Url::decode($key->get('e'))); |
||
121 | } else { |
||
122 | $this->exponent = BigInteger::createFromBinaryString(Base64Url::decode($key->get('e'))); |
||
123 | } |
||
124 | |||
125 | if ($key->has('p') && $key->has('q')) { |
||
126 | $this->primes = [ |
||
127 | BigInteger::createFromBinaryString(Base64Url::decode($key->get('p'))), |
||
128 | BigInteger::createFromBinaryString(Base64Url::decode($key->get('q'))), |
||
129 | ]; |
||
130 | } else { |
||
131 | $this->primes = []; |
||
132 | } |
||
133 | |||
134 | if ($key->has('dp') && $key->has('dq') && $key->has('qi')) { |
||
135 | $this->coefficients = [ |
||
136 | BigInteger::createFromBinaryString(Base64Url::decode($key->get('dp'))), |
||
137 | BigInteger::createFromBinaryString(Base64Url::decode($key->get('dq'))), |
||
138 | BigInteger::createFromBinaryString(Base64Url::decode($key->get('qi'))), |
||
139 | ]; |
||
140 | } else { |
||
141 | $this->coefficients = []; |
||
142 | } |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * Determines which hashing function should be used. |
||
147 | * |
||
148 | * @param string $hash |
||
149 | */ |
||
150 | public function setHash($hash) |
||
151 | { |
||
152 | $this->hash = Hash::$hash(); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Determines which hashing function should be used for the mask generation function. |
||
157 | * |
||
158 | * @param string $hash |
||
159 | */ |
||
160 | public function setMGFHash($hash) |
||
161 | { |
||
162 | $this->mgfHash = Hash::$hash(); |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * Integer-to-Octet-String primitive. |
||
167 | * |
||
168 | * @param \Jose\Util\BigInteger $x |
||
169 | * @param int $xLen |
||
170 | * |
||
171 | * @return string |
||
172 | */ |
||
173 | private function convertIntegerToOctetString($x, $xLen) |
||
174 | { |
||
175 | $x = $x->toBytes(); |
||
176 | if (strlen($x) > $xLen) { |
||
177 | |||
178 | return false; |
||
179 | } |
||
180 | |||
181 | return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Octet-String-to-Integer primitive. |
||
186 | * |
||
187 | * @param string $x |
||
188 | * |
||
189 | * @return \Jose\Util\BigInteger |
||
190 | */ |
||
191 | private function convertOctetStringToInteger($x) |
||
192 | { |
||
193 | return BigInteger::createFromBinaryString($x); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Exponentiate with or without Chinese Remainder Theorem. |
||
198 | * |
||
199 | * @param \Jose\Util\BigInteger $x |
||
200 | * |
||
201 | * @return \Jose\Util\BigInteger |
||
202 | */ |
||
203 | private function _exponentiate($x) |
||
204 | { |
||
205 | if (empty($this->primes) || empty($this->coefficients) || empty($this->exponents)) { |
||
206 | return $x->modPow($this->exponent, $this->modulus); |
||
207 | } |
||
208 | |||
209 | $num_primes = count($this->primes); |
||
210 | |||
211 | $smallest = $this->primes[1]; |
||
212 | for ($i = 2; $i <= $num_primes; $i++) { |
||
213 | if ($smallest->compare($this->primes[$i]) > 0) { |
||
214 | $smallest = $this->primes[$i]; |
||
215 | } |
||
216 | } |
||
217 | |||
218 | $one = BigInteger::createFromDecimalString('1'); |
||
219 | |||
220 | $r = $one->random($one, $smallest->subtract($one)); |
||
221 | |||
222 | $m_i = [ |
||
223 | 1 => $this->_blind($x, $r, 1), |
||
224 | 2 => $this->_blind($x, $r, 2), |
||
225 | ]; |
||
226 | $h = $m_i[1]->subtract($m_i[2]); |
||
227 | $h = $h->multiply($this->coefficients[2]); |
||
228 | list(, $h) = $h->divide($this->primes[1]); |
||
229 | $m = $m_i[2]->add($h->multiply($this->primes[2])); |
||
230 | |||
231 | $r = $this->primes[1]; |
||
232 | for ($i = 3; $i <= $num_primes; $i++) { |
||
233 | $m_i = $this->_blind($x, $r, $i); |
||
234 | |||
235 | $r = $r->multiply($this->primes[$i - 1]); |
||
236 | |||
237 | $h = $m_i->subtract($m); |
||
238 | $h = $h->multiply($this->coefficients[$i]); |
||
239 | list(, $h) = $h->divide($this->primes[$i]); |
||
240 | |||
241 | $m = $m->add($r->multiply($h)); |
||
242 | } |
||
243 | |||
244 | return $m; |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * Performs RSA Blinding. |
||
249 | * |
||
250 | * @param \Jose\Util\BigInteger $x |
||
251 | * @param \Jose\Util\BigInteger $r |
||
252 | * @param int $i |
||
253 | * |
||
254 | * @return \Jose\Util\BigInteger |
||
255 | */ |
||
256 | private function _blind($x, $r, $i) |
||
257 | { |
||
258 | $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i])); |
||
259 | $x = $x->modPow($this->exponents[$i], $this->primes[$i]); |
||
260 | |||
261 | $r = $r->modInverse($this->primes[$i]); |
||
262 | $x = $x->multiply($r); |
||
263 | list(, $x) = $x->divide($this->primes[$i]); |
||
264 | |||
265 | return $x; |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * Performs blinded RSA equality testing. |
||
270 | * |
||
271 | * @param string $x |
||
272 | * @param string $y |
||
273 | * |
||
274 | * @return bool |
||
275 | */ |
||
276 | private function _equals($x, $y) |
||
277 | { |
||
278 | if (strlen($x) != strlen($y)) { |
||
279 | return false; |
||
280 | } |
||
281 | |||
282 | $result = 0; |
||
283 | for ($i = 0; $i < strlen($x); $i++) { |
||
284 | $result |= ord($x[$i]) ^ ord($y[$i]); |
||
285 | } |
||
286 | |||
287 | return $result == 0; |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * RSAEP. |
||
292 | * |
||
293 | * @param \Jose\Util\BigInteger $m |
||
294 | * |
||
295 | * @return \Jose\Util\BigInteger|false |
||
296 | */ |
||
297 | private function _rsaep($m) |
||
298 | { |
||
299 | if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { |
||
300 | |||
301 | return false; |
||
302 | } |
||
303 | |||
304 | return $this->_exponentiate($m); |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * RSADP. |
||
309 | * |
||
310 | * @param \Jose\Util\BigInteger $c |
||
311 | * |
||
312 | * @return \Jose\Util\BigInteger|false |
||
313 | */ |
||
314 | private function _rsadp($c) |
||
315 | { |
||
316 | if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) { |
||
317 | |||
318 | return false; |
||
319 | } |
||
320 | |||
321 | return $this->_exponentiate($c); |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * RSASP1. |
||
326 | * |
||
327 | * @param \Jose\Util\BigInteger $m |
||
328 | * |
||
329 | * @return \Jose\Util\BigInteger|false |
||
330 | */ |
||
331 | private function _rsasp1($m) |
||
332 | { |
||
333 | if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { |
||
334 | |||
335 | return false; |
||
336 | } |
||
337 | |||
338 | return $this->_exponentiate($m); |
||
339 | } |
||
340 | |||
341 | /** |
||
342 | * RSAVP1. |
||
343 | * |
||
344 | * @param \Jose\Util\BigInteger $s |
||
345 | * |
||
346 | * @return \Jose\Util\BigInteger|false |
||
347 | */ |
||
348 | private function _rsavp1($s) |
||
349 | { |
||
350 | if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) { |
||
351 | |||
352 | return false; |
||
353 | } |
||
354 | |||
355 | return $this->_exponentiate($s); |
||
356 | } |
||
357 | |||
358 | /** |
||
359 | * MGF1. |
||
360 | * |
||
361 | * @param string $mgfSeed |
||
362 | * @param int $maskLen |
||
363 | * |
||
364 | * @return string |
||
365 | */ |
||
366 | private function _mgf1($mgfSeed, $maskLen) |
||
367 | { |
||
368 | // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output. |
||
369 | |||
370 | $t = ''; |
||
371 | $count = ceil($maskLen / $this->mgfHash->getLength()); |
||
372 | for ($i = 0; $i < $count; $i++) { |
||
373 | $c = pack('N', $i); |
||
374 | $t .= $this->mgfHash->hash($mgfSeed.$c); |
||
375 | } |
||
376 | |||
377 | return substr($t, 0, $maskLen); |
||
378 | } |
||
379 | |||
380 | /** |
||
381 | * RSAES-OAEP-ENCRYPT. |
||
382 | * |
||
383 | * @param string $m |
||
384 | * @param string $l |
||
385 | * |
||
386 | * @return string |
||
387 | */ |
||
388 | private function _rsaes_oaep_encrypt($m, $l = '') |
||
389 | { |
||
390 | $mLen = strlen($m); |
||
391 | |||
392 | // Length checking |
||
393 | |||
394 | // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error |
||
395 | // be output. |
||
396 | |||
397 | if ($mLen > $this->k - 2 * $this->hash->getLength() - 2) { |
||
398 | |||
399 | return false; |
||
400 | } |
||
401 | |||
402 | // EME-OAEP encoding |
||
403 | |||
404 | $lHash = $this->hash->hash($l); |
||
405 | $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hash->getLength() - 2); |
||
406 | $db = $lHash.$ps.chr(1).$m; |
||
407 | $seed = random_bytes($this->hash->getLength()); |
||
408 | $dbMask = $this->_mgf1($seed, $this->k - $this->hash->getLength() - 1); |
||
409 | $maskedDB = $db ^ $dbMask; |
||
410 | $seedMask = $this->_mgf1($maskedDB, $this->hash->getLength()); |
||
411 | $maskedSeed = $seed ^ $seedMask; |
||
412 | $em = chr(0).$maskedSeed.$maskedDB; |
||
413 | |||
414 | // RSA encryption |
||
415 | |||
416 | $m = $this->convertOctetStringToInteger($em); |
||
417 | $c = $this->_rsaep($m); |
||
418 | $c = $this->convertIntegerToOctetString($c, $this->k); |
||
0 ignored issues
–
show
|
|||
419 | |||
420 | // Output the ciphertext C |
||
421 | |||
422 | return $c; |
||
423 | } |
||
424 | |||
425 | /** |
||
426 | * RSAES-OAEP-DECRYPT. |
||
427 | * |
||
428 | * @param string $c |
||
429 | * @param string $l |
||
430 | * |
||
431 | * @return string |
||
432 | */ |
||
433 | private function _rsaes_oaep_decrypt($c, $l = '') |
||
434 | { |
||
435 | // Length checking |
||
436 | |||
437 | // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error |
||
438 | // be output. |
||
439 | |||
440 | if (strlen($c) != $this->k || $this->k < 2 * $this->hash->getLength() + 2) { |
||
441 | |||
442 | return false; |
||
443 | } |
||
444 | |||
445 | // RSA decryption |
||
446 | |||
447 | $c = $this->convertOctetStringToInteger($c); |
||
448 | $m = $this->_rsadp($c); |
||
449 | if ($m === false) { |
||
450 | |||
451 | return false; |
||
452 | } |
||
453 | $em = $this->convertIntegerToOctetString($m, $this->k); |
||
454 | |||
455 | // EME-OAEP decoding |
||
456 | |||
457 | $lHash = $this->hash->hash($l); |
||
458 | $maskedSeed = substr($em, 1, $this->hash->getLength()); |
||
459 | $maskedDB = substr($em, $this->hash->getLength() + 1); |
||
460 | $seedMask = $this->_mgf1($maskedDB, $this->hash->getLength()); |
||
461 | $seed = $maskedSeed ^ $seedMask; |
||
462 | $dbMask = $this->_mgf1($seed, $this->k - $this->hash->getLength() - 1); |
||
463 | $db = $maskedDB ^ $dbMask; |
||
464 | $lHash2 = substr($db, 0, $this->hash->getLength()); |
||
465 | $m = substr($db, $this->hash->getLength()); |
||
466 | if ($lHash != $lHash2) { |
||
467 | |||
468 | return false; |
||
469 | } |
||
470 | $m = ltrim($m, chr(0)); |
||
471 | if (ord($m[0]) != 1) { |
||
472 | |||
473 | return false; |
||
474 | } |
||
475 | |||
476 | // Output the message M |
||
477 | |||
478 | return substr($m, 1); |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * EMSA-PSS-ENCODE. |
||
483 | * |
||
484 | * @param string $m |
||
485 | * @param int $emBits |
||
486 | * |
||
487 | * @return bool |
||
488 | */ |
||
489 | private function _emsa_pss_encode($m, $emBits) |
||
490 | { |
||
491 | // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error |
||
492 | // be output. |
||
493 | |||
494 | $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8) |
||
495 | $sLen = $this->hash->getLength(); |
||
496 | |||
497 | $mHash = $this->hash->hash($m); |
||
498 | if ($emLen < $this->hash->getLength() + $sLen + 2) { |
||
499 | |||
500 | return false; |
||
501 | } |
||
502 | |||
503 | $salt = random_bytes($sLen); |
||
504 | $m2 = "\0\0\0\0\0\0\0\0".$mHash.$salt; |
||
505 | $h = $this->hash->hash($m2); |
||
506 | $ps = str_repeat(chr(0), $emLen - $sLen - $this->hash->getLength() - 2); |
||
507 | $db = $ps.chr(1).$salt; |
||
508 | $dbMask = $this->_mgf1($h, $emLen - $this->hash->getLength() - 1); |
||
509 | $maskedDB = $db ^ $dbMask; |
||
510 | $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0]; |
||
511 | $em = $maskedDB.$h.chr(0xBC); |
||
512 | |||
513 | return $em; |
||
514 | } |
||
515 | |||
516 | /** |
||
517 | * EMSA-PSS-VERIFY. |
||
518 | * |
||
519 | * @param string $m |
||
520 | * @param string $em |
||
521 | * @param int $emBits |
||
522 | * |
||
523 | * @return string |
||
524 | */ |
||
525 | private function _emsa_pss_verify($m, $em, $emBits) |
||
526 | { |
||
527 | // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error |
||
528 | // be output. |
||
529 | |||
530 | $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8); |
||
531 | $sLen = $this->hash->getLength(); |
||
532 | |||
533 | $mHash = $this->hash->hash($m); |
||
534 | if ($emLen < $this->hash->getLength() + $sLen + 2) { |
||
535 | return false; |
||
536 | } |
||
537 | |||
538 | if ($em[strlen($em) - 1] != chr(0xBC)) { |
||
539 | return false; |
||
540 | } |
||
541 | |||
542 | $maskedDB = substr($em, 0, -$this->hash->getLength() - 1); |
||
543 | $h = substr($em, -$this->hash->getLength() - 1, $this->hash->getLength()); |
||
544 | $temp = chr(0xFF << ($emBits & 7)); |
||
545 | if ((~$maskedDB[0] & $temp) != $temp) { |
||
546 | return false; |
||
547 | } |
||
548 | $dbMask = $this->_mgf1($h, $emLen - $this->hash->getLength() - 1); |
||
549 | $db = $maskedDB ^ $dbMask; |
||
550 | $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; |
||
551 | $temp = $emLen - $this->hash->getLength() - $sLen - 2; |
||
552 | if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) { |
||
553 | return false; |
||
554 | } |
||
555 | $salt = substr($db, $temp + 1); // should be $sLen long |
||
556 | $m2 = "\0\0\0\0\0\0\0\0".$mHash.$salt; |
||
557 | $h2 = $this->hash->hash($m2); |
||
558 | |||
559 | return $this->_equals($h, $h2); |
||
560 | } |
||
561 | |||
562 | /** |
||
563 | * RSASSA-PSS-SIGN. |
||
564 | * |
||
565 | * @param string $m |
||
566 | * |
||
567 | * @return string |
||
568 | */ |
||
569 | private function _rsassa_pss_sign($m) |
||
570 | { |
||
571 | // EMSA-PSS encoding |
||
572 | |||
573 | $em = $this->_emsa_pss_encode($m, 8 * $this->k - 1); |
||
574 | |||
575 | // RSA signature |
||
576 | |||
577 | $m = $this->convertOctetStringToInteger($em); |
||
0 ignored issues
–
show
It seems like
$em defined by $this->_emsa_pss_encode($m, 8 * $this->k - 1) on line 573 can also be of type false ; however, Jose\Util\RSA::convertOctetStringToInteger() does only seem to accept string , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
|||
578 | $s = $this->_rsasp1($m); |
||
579 | $s = $this->convertIntegerToOctetString($s, $this->k); |
||
0 ignored issues
–
show
It seems like
$s defined by $this->convertIntegerToOctetString($s, $this->k) on line 579 can also be of type false ; however, Jose\Util\RSA::convertIntegerToOctetString() does only seem to accept object<Jose\Util\BigInteger> , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
|||
580 | |||
581 | // Output the signature S |
||
582 | |||
583 | return $s; |
||
584 | } |
||
585 | |||
586 | /** |
||
587 | * RSASSA-PSS-VERIFY. |
||
588 | * |
||
589 | * @param string $m |
||
590 | * @param string $s |
||
591 | * |
||
592 | * @return string |
||
593 | */ |
||
594 | private function _rsassa_pss_verify($m, $s) |
||
595 | { |
||
596 | // Length checking |
||
597 | |||
598 | if (strlen($s) != $this->k) { |
||
599 | |||
600 | return false; |
||
601 | } |
||
602 | |||
603 | // RSA verification |
||
604 | |||
605 | $modBits = 8 * $this->k; |
||
606 | |||
607 | $s2 = $this->convertOctetStringToInteger($s); |
||
608 | $m2 = $this->_rsavp1($s2); |
||
609 | if ($m2 === false) { |
||
610 | |||
611 | return false; |
||
612 | } |
||
613 | $em = $this->convertIntegerToOctetString($m2, $modBits >> 3); |
||
614 | if ($em === false) { |
||
615 | |||
616 | return false; |
||
617 | } |
||
618 | |||
619 | // EMSA-PSS verification |
||
620 | |||
621 | return $this->_emsa_pss_verify($m, $em, $modBits - 1); |
||
622 | } |
||
623 | |||
624 | /** |
||
625 | * Encryption. |
||
626 | * |
||
627 | * Both self::ENCRYPTION_OAEP and self::ENCRYPTION_PKCS1 both place limits on how long $plaintext can be. |
||
628 | * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will |
||
629 | * be concatenated together. |
||
630 | * |
||
631 | * @see self::decrypt() |
||
632 | * |
||
633 | * @param string $plaintext |
||
634 | * |
||
635 | * @return string |
||
636 | */ |
||
637 | public function encrypt($plaintext) |
||
638 | { |
||
639 | $length = $this->k - 2 * $this->hash->getLength() - 2; |
||
640 | if ($length <= 0) { |
||
641 | return false; |
||
642 | } |
||
643 | |||
644 | $plaintext = str_split($plaintext, $length); |
||
645 | $ciphertext = ''; |
||
646 | foreach ($plaintext as $m) { |
||
647 | $ciphertext .= $this->_rsaes_oaep_encrypt($m); |
||
648 | } |
||
649 | |||
650 | return $ciphertext; |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * Decryption. |
||
655 | * |
||
656 | * @param string $ciphertext |
||
657 | * |
||
658 | * @return string |
||
659 | */ |
||
660 | public function decrypt($ciphertext) |
||
661 | { |
||
662 | if ($this->k <= 0) { |
||
663 | return false; |
||
664 | } |
||
665 | |||
666 | $ciphertext = str_split($ciphertext, $this->k); |
||
667 | $ciphertext[count($ciphertext) - 1] = str_pad($ciphertext[count($ciphertext) - 1], $this->k, chr(0), STR_PAD_LEFT); |
||
668 | |||
669 | $plaintext = ''; |
||
670 | |||
671 | foreach ($ciphertext as $c) { |
||
672 | $temp = $this->_rsaes_oaep_decrypt($c); |
||
673 | if ($temp === false) { |
||
674 | return false; |
||
675 | } |
||
676 | $plaintext .= $temp; |
||
677 | } |
||
678 | |||
679 | return $plaintext; |
||
680 | } |
||
681 | |||
682 | /** |
||
683 | * Create a signature. |
||
684 | * |
||
685 | * @param string $message |
||
686 | * |
||
687 | * @return string |
||
688 | */ |
||
689 | public function sign($message) |
||
690 | { |
||
691 | if (empty($this->modulus) || empty($this->exponent)) { |
||
692 | return false; |
||
693 | } |
||
694 | |||
695 | |||
696 | return $this->_rsassa_pss_sign($message); |
||
697 | } |
||
698 | |||
699 | /** |
||
700 | * Verifies a signature. |
||
701 | * |
||
702 | * @param string $message |
||
703 | * @param string $signature |
||
704 | * |
||
705 | * @return bool |
||
706 | */ |
||
707 | public function verify($message, $signature) |
||
708 | { |
||
709 | if (empty($this->modulus) || empty($this->exponent)) { |
||
710 | return false; |
||
711 | } |
||
712 | |||
713 | return $this->_rsassa_pss_verify($message, $signature); |
||
714 | } |
||
715 | } |
||
716 |
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTime
object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.