Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/tutor-pro/vendor/web-token/jwt-util-ecc/Curve.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
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\Ecc;
15 +
16 + use Brick\Math\BigInteger;
17 + use function is_null;
18 + use RuntimeException;
19 +
20 + /**
21 + * @internal
22 + */
23 + class Curve
24 + {
25 + /**
26 + * Elliptic curve over the field of integers modulo a prime.
27 + *
28 + * @var BigInteger
29 + */
30 + private $a;
31 +
32 + /**
33 + * @var BigInteger
34 + */
35 + private $b;
36 +
37 + /**
38 + * @var BigInteger
39 + */
40 + private $prime;
41 +
42 + /**
43 + * Binary length of keys associated with these curve parameters.
44 + *
45 + * @var int
46 + */
47 + private $size;
48 +
49 + /**
50 + * @var Point
51 + */
52 + private $generator;
53 +
54 + public function __construct(int $size, BigInteger $prime, BigInteger $a, BigInteger $b, Point $generator)
55 + {
56 + $this->size = $size;
57 + $this->prime = $prime;
58 + $this->a = $a;
59 + $this->b = $b;
60 + $this->generator = $generator;
61 + }
62 +
63 + public function __toString(): string
64 + {
65 + return 'curve('.Math::toString($this->getA()).', '.Math::toString($this->getB()).', '.Math::toString($this->getPrime()).')';
66 + }
67 +
68 + public function getA(): BigInteger
69 + {
70 + return $this->a;
71 + }
72 +
73 + public function getB(): BigInteger
74 + {
75 + return $this->b;
76 + }
77 +
78 + public function getPrime(): BigInteger
79 + {
80 + return $this->prime;
81 + }
82 +
83 + public function getSize(): int
84 + {
85 + return $this->size;
86 + }
87 +
88 + /**
89 + * @throws RuntimeException if the curve does not contain the point
90 + */
91 + public function getPoint(BigInteger $x, BigInteger $y, ?BigInteger $order = null): Point
92 + {
93 + if (!$this->contains($x, $y)) {
94 + throw new RuntimeException('Curve '.$this->__toString().' does not contain point ('.Math::toString($x).', '.Math::toString($y).')');
95 + }
96 + $point = Point::create($x, $y, $order);
97 + if (!is_null($order)) {
98 + $mul = $this->mul($point, $order);
99 + if (!$mul->isInfinity()) {
100 + throw new RuntimeException('SELF * ORDER MUST EQUAL INFINITY.');
101 + }
102 + }
103 +
104 + return $point;
105 + }
106 +
107 + /**
108 + * @throws RuntimeException if the coordinates are out of range
109 + */
110 + public function getPublicKeyFrom(BigInteger $x, BigInteger $y): PublicKey
111 + {
112 + $zero = BigInteger::zero();
113 + if ($x->compareTo($zero) < 0 || $y->compareTo($zero) < 0 || $this->generator->getOrder()->compareTo($x) <= 0 || $this->generator->getOrder()->compareTo($y) <= 0) {
114 + throw new RuntimeException('Generator point has x and y out of range.');
115 + }
116 + $point = $this->getPoint($x, $y);
117 +
118 + return new PublicKey($point);
119 + }
120 +
121 + public function contains(BigInteger $x, BigInteger $y): bool
122 + {
123 + return Math::equals(
124 + ModularArithmetic::sub(
125 + $y->power(2),
126 + Math::add(
127 + Math::add(
128 + $x->power(3),
129 + $this->getA()->multipliedBy($x)
130 + ),
131 + $this->getB()
132 + ),
133 + $this->getPrime()
134 + ),
135 + BigInteger::zero()
136 + );
137 + }
138 +
139 + public function add(Point $one, Point $two): Point
140 + {
141 + if ($two->isInfinity()) {
142 + return clone $one;
143 + }
144 +
145 + if ($one->isInfinity()) {
146 + return clone $two;
147 + }
148 +
149 + if ($two->getX()->isEqualTo($one->getX())) {
150 + if ($two->getY()->isEqualTo($one->getY())) {
151 + return $this->getDouble($one);
152 + }
153 +
154 + return Point::infinity();
155 + }
156 +
157 + $slope = ModularArithmetic::div(
158 + $two->getY()->minus($one->getY()),
159 + $two->getX()->minus($one->getX()),
160 + $this->getPrime()
161 + );
162 +
163 + $xR = ModularArithmetic::sub(
164 + $slope->power(2)->minus($one->getX()),
165 + $two->getX(),
166 + $this->getPrime()
167 + );
168 +
169 + $yR = ModularArithmetic::sub(
170 + $slope->multipliedBy($one->getX()->minus($xR)),
171 + $one->getY(),
172 + $this->getPrime()
173 + );
174 +
175 + return $this->getPoint($xR, $yR, $one->getOrder());
176 + }
177 +
178 + public function mul(Point $one, BigInteger $n): Point
179 + {
180 + if ($one->isInfinity()) {
181 + return Point::infinity();
182 + }
183 +
184 + /** @var BigInteger $zero */
185 + $zero = BigInteger::zero();
186 + if ($one->getOrder()->compareTo($zero) > 0) {
187 + $n = $n->mod($one->getOrder());
188 + }
189 +
190 + if ($n->isEqualTo($zero)) {
191 + return Point::infinity();
192 + }
193 +
194 + /** @var Point[] $r */
195 + $r = [
196 + Point::infinity(),
197 + clone $one,
198 + ];
199 +
200 + $k = $this->getSize();
201 + $n1 = str_pad(Math::baseConvert(Math::toString($n), 10, 2), $k, '0', STR_PAD_LEFT);
202 +
203 + for ($i = 0; $i < $k; ++$i) {
204 + $j = $n1[$i];
205 + Point::cswap($r[0], $r[1], $j ^ 1);
206 + $r[0] = $this->add($r[0], $r[1]);
207 + $r[1] = $this->getDouble($r[1]);
208 + Point::cswap($r[0], $r[1], $j ^ 1);
209 + }
210 +
211 + $this->validate($r[0]);
212 +
213 + return $r[0];
214 + }
215 +
216 + /**
217 + * @param Curve $other
218 + */
219 + public function cmp(self $other): int
220 + {
221 + $equal = $this->getA()->isEqualTo($other->getA())
222 + && $this->getB()->isEqualTo($other->getB())
223 + && $this->getPrime()->isEqualTo($other->getPrime());
224 +
225 + return $equal ? 0 : 1;
226 + }
227 +
228 + /**
229 + * @param Curve $other
230 + */
231 + public function equals(self $other): bool
232 + {
233 + return 0 === $this->cmp($other);
234 + }
235 +
236 + public function getDouble(Point $point): Point
237 + {
238 + if ($point->isInfinity()) {
239 + return Point::infinity();
240 + }
241 +
242 + $a = $this->getA();
243 + $threeX2 = BigInteger::of(3)->multipliedBy($point->getX()->power(2));
244 +
245 + $tangent = ModularArithmetic::div(
246 + $threeX2->plus($a),
247 + BigInteger::of(2)->multipliedBy($point->getY()),
248 + $this->getPrime()
249 + );
250 +
251 + $x3 = ModularArithmetic::sub(
252 + $tangent->power(2),
253 + BigInteger::of(2)->multipliedBy($point->getX()),
254 + $this->getPrime()
255 + );
256 +
257 + $y3 = ModularArithmetic::sub(
258 + $tangent->multipliedBy($point->getX()->minus($x3)),
259 + $point->getY(),
260 + $this->getPrime()
261 + );
262 +
263 + return $this->getPoint($x3, $y3, $point->getOrder());
264 + }
265 +
266 + public function createPrivateKey(): PrivateKey
267 + {
268 + return PrivateKey::create($this->generate());
269 + }
270 +
271 + public function createPublicKey(PrivateKey $privateKey): PublicKey
272 + {
273 + $point = $this->mul($this->generator, $privateKey->getSecret());
274 +
275 + return new PublicKey($point);
276 + }
277 +
278 + public function getGenerator(): Point
279 + {
280 + return $this->generator;
281 + }
282 +
283 + /**
284 + * @throws RuntimeException if the point is invalid
285 + */
286 + private function validate(Point $point): void
287 + {
288 + if (!$point->isInfinity() && !$this->contains($point->getX(), $point->getY())) {
289 + throw new RuntimeException('Invalid point');
290 + }
291 + }
292 +
293 + private function generate(): BigInteger
294 + {
295 + $max = $this->generator->getOrder();
296 + $numBits = $this->bnNumBits($max);
297 + $numBytes = (int) ceil($numBits / 8);
298 + // Generate an integer of size >= $numBits
299 + $bytes = BigInteger::randomBits($numBytes);
300 + $mask = BigInteger::of(2)->power($numBits)->minus(1);
301 +
302 + return $bytes->and($mask);
303 + }
304 +
305 + /**
306 + * Returns the number of bits used to store this number. Non-significant upper bits are not counted.
307 + *
308 + * @see https://www.openssl.org/docs/crypto/BN_num_bytes.html
309 + */
310 + private function bnNumBits(BigInteger $x): int
311 + {
312 + $zero = BigInteger::of(0);
313 + if ($x->isEqualTo($zero)) {
314 + return 0;
315 + }
316 + $log2 = 0;
317 + while (!$x->isEqualTo($zero)) {
318 + $x = $x->shiftedRight(1);
319 + ++$log2;
320 + }
321 +
322 + return $log2;
323 + }
324 + }
325 +