1 | <?php |
||
17 | final class RSA |
||
18 | { |
||
19 | /** |
||
20 | * Integer-to-Octet-String primitive. |
||
21 | * |
||
22 | * @param \Jose\Util\BigInteger $x |
||
23 | * @param int $xLen |
||
24 | * |
||
25 | * @return string |
||
26 | */ |
||
27 | private static function convertIntegerToOctetString($x, $xLen) |
||
36 | |||
37 | /** |
||
38 | * Octet-String-to-Integer primitive. |
||
39 | * |
||
40 | * @param string $x |
||
41 | * |
||
42 | * @return \Jose\Util\BigInteger |
||
43 | */ |
||
44 | private static function convertOctetStringToInteger($x) |
||
48 | |||
49 | /** |
||
50 | * Exponentiate with or without Chinese Remainder Theorem. |
||
51 | * Operation with primes 'p' and 'q' is appox. 2x faster. |
||
52 | * |
||
53 | * @param \Jose\KeyConverter\RSAKey $key |
||
54 | * @param \Jose\Util\BigInteger $c |
||
55 | * |
||
56 | * @return \Jose\Util\BigInteger |
||
57 | */ |
||
58 | private static function exponentiate(RSAKey $key, BigInteger $c) |
||
77 | |||
78 | /** |
||
79 | * RSA EP. |
||
80 | * |
||
81 | * @param \Jose\KeyConverter\RSAKey $key |
||
82 | * @param \Jose\Util\BigInteger $m |
||
83 | * |
||
84 | * @return \Jose\Util\BigInteger|false |
||
85 | */ |
||
86 | private static function getRSAEP(RSAKey $key, BigInteger $m) |
||
87 | { |
||
88 | if ($m->compare(BigInteger::createFromDecimal(0)) < 0 || $m->compare($key->getModulus()) > 0) { |
||
89 | return false; |
||
90 | } |
||
91 | |||
92 | return self::exponentiate($key, $m); |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * RSA DP. |
||
97 | * |
||
98 | * @param \Jose\KeyConverter\RSAKey $key |
||
99 | * @param \Jose\Util\BigInteger $c |
||
100 | * |
||
101 | * @return \Jose\Util\BigInteger|false |
||
102 | */ |
||
103 | private static function getRSADP(RSAKey $key, BigInteger $c) |
||
104 | { |
||
105 | if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare($key->getModulus()) > 0) { |
||
106 | return false; |
||
107 | } |
||
108 | |||
109 | return self::exponentiate($key, $c); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * RSA SP1. |
||
114 | * |
||
115 | * @param \Jose\KeyConverter\RSAKey $key |
||
116 | * @param \Jose\Util\BigInteger $m |
||
117 | * |
||
118 | * @return \Jose\Util\BigInteger|false |
||
119 | */ |
||
120 | private static function getRSASP1(RSAKey $key, BigInteger $m) |
||
121 | { |
||
122 | if ($m->compare(BigInteger::createFromDecimal(0)) < 0 || $m->compare($key->getModulus()) > 0) { |
||
123 | return false; |
||
124 | } |
||
125 | |||
126 | return self::exponentiate($key, $m); |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * RSAVP1. |
||
131 | * |
||
132 | * @param \Jose\KeyConverter\RSAKey $key |
||
133 | * @param \Jose\Util\BigInteger $s |
||
134 | * |
||
135 | * @return \Jose\Util\BigInteger|false |
||
136 | */ |
||
137 | private static function getRSAVP1(RSAKey $key, BigInteger $s) |
||
138 | { |
||
139 | if ($s->compare(BigInteger::createFromDecimal(0)) < 0 || $s->compare($key->getModulus()) > 0) { |
||
140 | return false; |
||
141 | } |
||
142 | |||
143 | return self::exponentiate($key, $s); |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * MGF1. |
||
148 | * |
||
149 | * @param string $mgfSeed |
||
150 | * @param int $maskLen |
||
151 | * @param \Jose\Util\Hash $mgfHash |
||
152 | * |
||
153 | * @return string |
||
154 | */ |
||
155 | private static function getMGF1($mgfSeed, $maskLen, Hash $mgfHash) |
||
156 | { |
||
157 | $t = ''; |
||
158 | $count = ceil($maskLen / $mgfHash->getLength()); |
||
159 | for ($i = 0; $i < $count; $i++) { |
||
160 | $c = pack('N', $i); |
||
161 | $t .= $mgfHash->hash($mgfSeed.$c); |
||
162 | } |
||
163 | |||
164 | return mb_substr($t, 0, $maskLen, '8bit'); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * RSAES-OAEP-ENCRYPT. |
||
169 | * |
||
170 | * @param \Jose\KeyConverter\RSAKey $key |
||
171 | * @param string $m |
||
172 | * @param \Jose\Util\Hash $hash |
||
173 | * |
||
174 | * @return string |
||
175 | */ |
||
176 | private static function encryptRSAESOAEP(RSAKey $key, $m, Hash $hash) |
||
177 | { |
||
178 | $mLen = mb_strlen($m, '8bit'); |
||
179 | $lHash = $hash->hash(''); |
||
180 | $ps = str_repeat(chr(0), $key->getModulusLength() - $mLen - 2 * $hash->getLength() - 2); |
||
181 | $db = $lHash.$ps.chr(1).$m; |
||
182 | $seed = random_bytes($hash->getLength()); |
||
183 | $dbMask = self::getMGF1($seed, $key->getModulusLength() - $hash->getLength() - 1, $hash/*MGF*/); |
||
184 | $maskedDB = $db ^ $dbMask; |
||
185 | $seedMask = self::getMGF1($maskedDB, $hash->getLength(), $hash/*MGF*/); |
||
186 | $maskedSeed = $seed ^ $seedMask; |
||
187 | $em = chr(0).$maskedSeed.$maskedDB; |
||
188 | |||
189 | $m = self::convertOctetStringToInteger($em); |
||
190 | $c = self::getRSAEP($key, $m); |
||
191 | $c = self::convertIntegerToOctetString($c, $key->getModulusLength()); |
||
|
|||
192 | |||
193 | return $c; |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * RSAES-OAEP-DECRYPT. |
||
198 | * |
||
199 | * @param \Jose\KeyConverter\RSAKey $key |
||
200 | * @param string $c |
||
201 | * @param \Jose\Util\Hash $hash |
||
202 | * |
||
203 | * @return string |
||
204 | */ |
||
205 | private static function getRSAESOAEP(RSAKey $key, $c, Hash $hash) |
||
206 | { |
||
207 | $c = self::convertOctetStringToInteger($c); |
||
208 | $m = self::getRSADP($key, $c); |
||
209 | Assertion::isInstanceOf($m, BigInteger::class); |
||
210 | $em = self::convertIntegerToOctetString($m, $key->getModulusLength()); |
||
211 | $lHash = $hash->hash(''); |
||
212 | $maskedSeed = mb_substr($em, 1, $hash->getLength(), '8bit'); |
||
213 | $maskedDB = mb_substr($em, $hash->getLength() + 1, null, '8bit'); |
||
214 | $seedMask = self::getMGF1($maskedDB, $hash->getLength(), $hash/*MGF*/); |
||
215 | $seed = $maskedSeed ^ $seedMask; |
||
216 | $dbMask = self::getMGF1($seed, $key->getModulusLength() - $hash->getLength() - 1, $hash/*MGF*/); |
||
217 | $db = $maskedDB ^ $dbMask; |
||
218 | $lHash2 = mb_substr($db, 0, $hash->getLength(), '8bit'); |
||
219 | $m = mb_substr($db, $hash->getLength(), null, '8bit'); |
||
220 | Assertion::eq($lHash, $lHash2); |
||
221 | $m = ltrim($m, chr(0)); |
||
222 | Assertion::eq(ord($m[0]), 1); |
||
223 | |||
224 | return mb_substr($m, 1, null, '8bit'); |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * EMSA-PSS-ENCODE. |
||
229 | * |
||
230 | * @param string $m |
||
231 | * @param int $emBits |
||
232 | * @param \Jose\Util\Hash $hash |
||
233 | * |
||
234 | * @return string|bool |
||
235 | */ |
||
236 | private static function encodeEMSAPSS($m, $emBits, Hash $hash) |
||
254 | |||
255 | /** |
||
256 | * EMSA-PSS-VERIFY. |
||
257 | * |
||
258 | * @param string $m |
||
259 | * @param string $em |
||
260 | * @param int $emBits |
||
261 | * @param \Jose\Util\Hash $hash |
||
262 | * |
||
263 | * @return string |
||
264 | */ |
||
265 | private static function verifyEMSAPSS($m, $em, $emBits, Hash $hash) |
||
288 | |||
289 | /** |
||
290 | * Encryption. |
||
291 | * |
||
292 | * @param \Jose\KeyConverter\RSAKey $key |
||
293 | * @param string $plaintext |
||
294 | * @param string $hash_algorithm |
||
295 | * |
||
296 | * @return string |
||
297 | */ |
||
298 | public static function encrypt(RSAKey $key, $plaintext, $hash_algorithm) |
||
314 | |||
315 | /** |
||
316 | * Decryption. |
||
317 | * |
||
318 | * @param \Jose\KeyConverter\RSAKey $key |
||
319 | * @param string $ciphertext |
||
320 | * @param string $hash_algorithm |
||
321 | * |
||
322 | * @return string |
||
323 | */ |
||
324 | public static function decrypt(RSAKey $key, $ciphertext, $hash_algorithm) |
||
338 | |||
339 | /** |
||
340 | * Create a signature. |
||
341 | * |
||
342 | * @param \Jose\KeyConverter\RSAKey $key |
||
343 | * @param string $message |
||
344 | * @param string $hash |
||
345 | * |
||
346 | * @return string |
||
347 | */ |
||
348 | public static function sign(RSAKey $key, $message, $hash) |
||
361 | |||
362 | /** |
||
363 | * Verifies a signature. |
||
364 | * |
||
365 | * @param \Jose\KeyConverter\RSAKey $key |
||
366 | * @param string $message |
||
367 | * @param string $signature |
||
368 | * @param string $hash |
||
369 | * |
||
370 | * @return bool |
||
371 | */ |
||
372 | public static function verify(RSAKey $key, $message, $signature, $hash) |
||
387 | } |
||
388 |
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
.