Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/tutor-pro/vendor/web-token/jwt-core/Util/RSAKey.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
3
+
declare(strict_types=1);
4
+
5
+
/*
6
+
* The MIT License (MIT)
7
+
*
8
+
* Copyright (c) 2014-2020 Spomky-Labs
9
+
*
10
+
* This software may be modified and distributed under the terms
11
+
* of the MIT license. See the LICENSE file for details.
12
+
*/
13
+
14
+
namespace Jose\Component\Core\Util;
15
+
16
+
use function array_key_exists;
17
+
use Base64Url\Base64Url;
18
+
use function count;
19
+
use FG\ASN1\Universal\BitString;
20
+
use FG\ASN1\Universal\Integer;
21
+
use FG\ASN1\Universal\NullObject;
22
+
use FG\ASN1\Universal\ObjectIdentifier;
23
+
use FG\ASN1\Universal\OctetString;
24
+
use FG\ASN1\Universal\Sequence;
25
+
use InvalidArgumentException;
26
+
use function is_array;
27
+
use Jose\Component\Core\JWK;
28
+
use RuntimeException;
29
+
30
+
/**
31
+
* @internal
32
+
*/
33
+
class RSAKey
34
+
{
35
+
/**
36
+
* @var Sequence
37
+
*/
38
+
private $sequence;
39
+
40
+
/**
41
+
* @var bool
42
+
*/
43
+
private $private;
44
+
45
+
/**
46
+
* @var array
47
+
*/
48
+
private $values;
49
+
50
+
/**
51
+
* @var BigInteger
52
+
*/
53
+
private $modulus;
54
+
55
+
/**
56
+
* @var int
57
+
*/
58
+
private $modulus_length;
59
+
60
+
/**
61
+
* @var BigInteger
62
+
*/
63
+
private $public_exponent;
64
+
65
+
/**
66
+
* @var null|BigInteger
67
+
*/
68
+
private $private_exponent;
69
+
70
+
/**
71
+
* @var BigInteger[]
72
+
*/
73
+
private $primes = [];
74
+
75
+
/**
76
+
* @var BigInteger[]
77
+
*/
78
+
private $exponents = [];
79
+
80
+
/**
81
+
* @var null|BigInteger
82
+
*/
83
+
private $coefficient;
84
+
85
+
private function __construct(JWK $data)
86
+
{
87
+
$this->values = $data->all();
88
+
$this->populateBigIntegers();
89
+
$this->private = array_key_exists('d', $this->values);
90
+
}
91
+
92
+
/**
93
+
* @return RSAKey
94
+
*/
95
+
public static function createFromJWK(JWK $jwk): self
96
+
{
97
+
return new self($jwk);
98
+
}
99
+
100
+
public function getModulus(): BigInteger
101
+
{
102
+
return $this->modulus;
103
+
}
104
+
105
+
public function getModulusLength(): int
106
+
{
107
+
return $this->modulus_length;
108
+
}
109
+
110
+
public function getExponent(): BigInteger
111
+
{
112
+
$d = $this->getPrivateExponent();
113
+
if (null !== $d) {
114
+
return $d;
115
+
}
116
+
117
+
return $this->getPublicExponent();
118
+
}
119
+
120
+
public function getPublicExponent(): BigInteger
121
+
{
122
+
return $this->public_exponent;
123
+
}
124
+
125
+
public function getPrivateExponent(): ?BigInteger
126
+
{
127
+
return $this->private_exponent;
128
+
}
129
+
130
+
/**
131
+
* @return BigInteger[]
132
+
*/
133
+
public function getPrimes(): array
134
+
{
135
+
return $this->primes;
136
+
}
137
+
138
+
/**
139
+
* @return BigInteger[]
140
+
*/
141
+
public function getExponents(): array
142
+
{
143
+
return $this->exponents;
144
+
}
145
+
146
+
public function getCoefficient(): ?BigInteger
147
+
{
148
+
return $this->coefficient;
149
+
}
150
+
151
+
public function isPublic(): bool
152
+
{
153
+
return !array_key_exists('d', $this->values);
154
+
}
155
+
156
+
/**
157
+
* @param RSAKey $private
158
+
*
159
+
* @return RSAKey
160
+
*/
161
+
public static function toPublic(self $private): self
162
+
{
163
+
$data = $private->toArray();
164
+
$keys = ['p', 'd', 'q', 'dp', 'dq', 'qi'];
165
+
foreach ($keys as $key) {
166
+
if (array_key_exists($key, $data)) {
167
+
unset($data[$key]);
168
+
}
169
+
}
170
+
171
+
return new self(new JWK($data));
172
+
}
173
+
174
+
public function toArray(): array
175
+
{
176
+
return $this->values;
177
+
}
178
+
179
+
public function toPEM(): string
180
+
{
181
+
if (null === $this->sequence) {
182
+
$this->sequence = new Sequence();
183
+
if (array_key_exists('d', $this->values)) {
184
+
$this->initPrivateKey();
185
+
} else {
186
+
$this->initPublicKey();
187
+
}
188
+
}
189
+
$result = '-----BEGIN '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL;
190
+
$result .= chunk_split(base64_encode($this->sequence->getBinary()), 64, PHP_EOL);
191
+
$result .= '-----END '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL;
192
+
193
+
return $result;
194
+
}
195
+
196
+
/**
197
+
* Exponentiate with or without Chinese Remainder Theorem.
198
+
* Operation with primes 'p' and 'q' is appox. 2x faster.
199
+
*
200
+
* @param RSAKey $key
201
+
*
202
+
* @throws RuntimeException if the exponentiation cannot be achieved
203
+
*/
204
+
public static function exponentiate(self $key, BigInteger $c): BigInteger
205
+
{
206
+
if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare($key->getModulus()) > 0) {
207
+
throw new RuntimeException();
208
+
}
209
+
if ($key->isPublic() || null === $key->getCoefficient() || 0 === count($key->getPrimes()) || 0 === count($key->getExponents())) {
210
+
return $c->modPow($key->getExponent(), $key->getModulus());
211
+
}
212
+
213
+
$p = $key->getPrimes()[0];
214
+
$q = $key->getPrimes()[1];
215
+
$dP = $key->getExponents()[0];
216
+
$dQ = $key->getExponents()[1];
217
+
$qInv = $key->getCoefficient();
218
+
219
+
$m1 = $c->modPow($dP, $p);
220
+
$m2 = $c->modPow($dQ, $q);
221
+
$h = $qInv->multiply($m1->subtract($m2)->add($p))->mod($p);
222
+
223
+
return $m2->add($h->multiply($q));
224
+
}
225
+
226
+
private function populateBigIntegers(): void
227
+
{
228
+
$this->modulus = $this->convertBase64StringToBigInteger($this->values['n']);
229
+
$this->modulus_length = mb_strlen($this->getModulus()->toBytes(), '8bit');
230
+
$this->public_exponent = $this->convertBase64StringToBigInteger($this->values['e']);
231
+
232
+
if (!$this->isPublic()) {
233
+
$this->private_exponent = $this->convertBase64StringToBigInteger($this->values['d']);
234
+
235
+
if (array_key_exists('p', $this->values) && array_key_exists('q', $this->values)) {
236
+
$this->primes = [
237
+
$this->convertBase64StringToBigInteger($this->values['p']),
238
+
$this->convertBase64StringToBigInteger($this->values['q']),
239
+
];
240
+
if (array_key_exists('dp', $this->values) && array_key_exists('dq', $this->values) && array_key_exists('qi', $this->values)) {
241
+
$this->exponents = [
242
+
$this->convertBase64StringToBigInteger($this->values['dp']),
243
+
$this->convertBase64StringToBigInteger($this->values['dq']),
244
+
];
245
+
$this->coefficient = $this->convertBase64StringToBigInteger($this->values['qi']);
246
+
}
247
+
}
248
+
}
249
+
}
250
+
251
+
private function convertBase64StringToBigInteger(string $value): BigInteger
252
+
{
253
+
return BigInteger::createFromBinaryString(Base64Url::decode($value));
254
+
}
255
+
256
+
private function initPublicKey(): void
257
+
{
258
+
$oid_sequence = new Sequence();
259
+
$oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1'));
260
+
$oid_sequence->addChild(new NullObject());
261
+
$this->sequence->addChild($oid_sequence);
262
+
$n = new Integer($this->fromBase64ToInteger($this->values['n']));
263
+
$e = new Integer($this->fromBase64ToInteger($this->values['e']));
264
+
$key_sequence = new Sequence();
265
+
$key_sequence->addChild($n);
266
+
$key_sequence->addChild($e);
267
+
$key_bit_string = new BitString(bin2hex($key_sequence->getBinary()));
268
+
$this->sequence->addChild($key_bit_string);
269
+
}
270
+
271
+
private function initPrivateKey(): void
272
+
{
273
+
$this->sequence->addChild(new Integer(0));
274
+
$oid_sequence = new Sequence();
275
+
$oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1'));
276
+
$oid_sequence->addChild(new NullObject());
277
+
$this->sequence->addChild($oid_sequence);
278
+
$v = new Integer(0);
279
+
$n = new Integer($this->fromBase64ToInteger($this->values['n']));
280
+
$e = new Integer($this->fromBase64ToInteger($this->values['e']));
281
+
$d = new Integer($this->fromBase64ToInteger($this->values['d']));
282
+
$p = new Integer($this->fromBase64ToInteger($this->values['p']));
283
+
$q = new Integer($this->fromBase64ToInteger($this->values['q']));
284
+
$dp = array_key_exists('dp', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dp'])) : new Integer(0);
285
+
$dq = array_key_exists('dq', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dq'])) : new Integer(0);
286
+
$qi = array_key_exists('qi', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['qi'])) : new Integer(0);
287
+
$key_sequence = new Sequence();
288
+
$key_sequence->addChild($v);
289
+
$key_sequence->addChild($n);
290
+
$key_sequence->addChild($e);
291
+
$key_sequence->addChild($d);
292
+
$key_sequence->addChild($p);
293
+
$key_sequence->addChild($q);
294
+
$key_sequence->addChild($dp);
295
+
$key_sequence->addChild($dq);
296
+
$key_sequence->addChild($qi);
297
+
$key_octet_string = new OctetString(bin2hex($key_sequence->getBinary()));
298
+
$this->sequence->addChild($key_octet_string);
299
+
}
300
+
301
+
/**
302
+
* @param string $value
303
+
*
304
+
* @return string
305
+
*/
306
+
private function fromBase64ToInteger($value)
307
+
{
308
+
$unpacked = unpack('H*', Base64Url::decode($value));
309
+
if (!is_array($unpacked) || 0 === count($unpacked)) {
310
+
throw new InvalidArgumentException('Unable to get the private key');
311
+
}
312
+
313
+
return \Brick\Math\BigInteger::fromBase(current($unpacked), 16)->toBase(10);
314
+
}
315
+
}
316
+