1<?php
2
3if (class_exists('ParagonIE_Sodium_Core32_Curve25519', false)) {
4 return;
5}
6
7/**
8 * Class ParagonIE_Sodium_Core32_Curve25519
9 *
10 * Implements Curve25519 core functions
11 *
12 * Based on the ref10 curve25519 code provided by libsodium
13 *
14 * @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
15 */
16abstract class ParagonIE_Sodium_Core32_Curve25519 extends ParagonIE_Sodium_Core32_Curve25519_H
17{
18 /**
19 * Get a field element of size 10 with a value of 0
20 *
21 * @internal You should not use this directly from another application
22 *
23 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
24 * @throws SodiumException
25 * @throws TypeError
26 */
27 public static function fe_0()
28 {
29 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
30 array(
31 new ParagonIE_Sodium_Core32_Int32(),
32 new ParagonIE_Sodium_Core32_Int32(),
33 new ParagonIE_Sodium_Core32_Int32(),
34 new ParagonIE_Sodium_Core32_Int32(),
35 new ParagonIE_Sodium_Core32_Int32(),
36 new ParagonIE_Sodium_Core32_Int32(),
37 new ParagonIE_Sodium_Core32_Int32(),
38 new ParagonIE_Sodium_Core32_Int32(),
39 new ParagonIE_Sodium_Core32_Int32(),
40 new ParagonIE_Sodium_Core32_Int32()
41 )
42 );
43 }
44
45 /**
46 * Get a field element of size 10 with a value of 1
47 *
48 * @internal You should not use this directly from another application
49 *
50 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
51 * @throws SodiumException
52 * @throws TypeError
53 */
54 public static function fe_1()
55 {
56 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
57 array(
58 ParagonIE_Sodium_Core32_Int32::fromInt(1),
59 new ParagonIE_Sodium_Core32_Int32(),
60 new ParagonIE_Sodium_Core32_Int32(),
61 new ParagonIE_Sodium_Core32_Int32(),
62 new ParagonIE_Sodium_Core32_Int32(),
63 new ParagonIE_Sodium_Core32_Int32(),
64 new ParagonIE_Sodium_Core32_Int32(),
65 new ParagonIE_Sodium_Core32_Int32(),
66 new ParagonIE_Sodium_Core32_Int32(),
67 new ParagonIE_Sodium_Core32_Int32()
68 )
69 );
70 }
71
72 /**
73 * Add two field elements.
74 *
75 * @internal You should not use this directly from another application
76 *
77 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
78 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
79 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
80 * @throws SodiumException
81 * @throws TypeError
82 * @psalm-suppress MixedAssignment
83 * @psalm-suppress MixedMethodCall
84 */
85 public static function fe_add(
86 ParagonIE_Sodium_Core32_Curve25519_Fe $f,
87 ParagonIE_Sodium_Core32_Curve25519_Fe $g
88 ) {
89 $arr = array();
90 for ($i = 0; $i < 10; ++$i) {
91 $arr[$i] = $f[$i]->addInt32($g[$i]);
92 }
93 /** @var array<int, ParagonIE_Sodium_Core32_Int32> $arr */
94 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($arr);
95 }
96
97 /**
98 * Constant-time conditional move.
99 *
100 * @internal You should not use this directly from another application
101 *
102 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
103 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
104 * @param int $b
105 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
106 * @throws SodiumException
107 * @throws TypeError
108 * @psalm-suppress MixedAssignment
109 * @psalm-suppress MixedMethodCall
110 */
111 public static function fe_cmov(
112 ParagonIE_Sodium_Core32_Curve25519_Fe $f,
113 ParagonIE_Sodium_Core32_Curve25519_Fe $g,
114 $b = 0
115 ) {
116 /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
117 $h = array();
118 for ($i = 0; $i < 10; ++$i) {
119 if (!($f[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
120 throw new TypeError('Expected Int32');
121 }
122 if (!($g[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
123 throw new TypeError('Expected Int32');
124 }
125 $h[$i] = $f[$i]->xorInt32(
126 $f[$i]->xorInt32($g[$i])->mask($b)
127 );
128 }
129 /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
130 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h);
131 }
132
133 /**
134 * Create a copy of a field element.
135 *
136 * @internal You should not use this directly from another application
137 *
138 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
139 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
140 */
141 public static function fe_copy(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
142 {
143 $h = clone $f;
144 return $h;
145 }
146
147 /**
148 * Give: 32-byte string.
149 * Receive: A field element object to use for internal calculations.
150 *
151 * @internal You should not use this directly from another application
152 *
153 * @param string $s
154 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
155 * @throws RangeException
156 * @throws SodiumException
157 * @throws TypeError
158 * @psalm-suppress MixedMethodCall
159 */
160 public static function fe_frombytes($s)
161 {
162 if (self::strlen($s) !== 32) {
163 throw new RangeException('Expected a 32-byte string.');
164 }
165 /** @var ParagonIE_Sodium_Core32_Int32 $h0 */
166 $h0 = ParagonIE_Sodium_Core32_Int32::fromInt(
167 self::load_4($s)
168 );
169 /** @var ParagonIE_Sodium_Core32_Int32 $h1 */
170 $h1 = ParagonIE_Sodium_Core32_Int32::fromInt(
171 self::load_3(self::substr($s, 4, 3)) << 6
172 );
173 /** @var ParagonIE_Sodium_Core32_Int32 $h2 */
174 $h2 = ParagonIE_Sodium_Core32_Int32::fromInt(
175 self::load_3(self::substr($s, 7, 3)) << 5
176 );
177 /** @var ParagonIE_Sodium_Core32_Int32 $h3 */
178 $h3 = ParagonIE_Sodium_Core32_Int32::fromInt(
179 self::load_3(self::substr($s, 10, 3)) << 3
180 );
181 /** @var ParagonIE_Sodium_Core32_Int32 $h4 */
182 $h4 = ParagonIE_Sodium_Core32_Int32::fromInt(
183 self::load_3(self::substr($s, 13, 3)) << 2
184 );
185 /** @var ParagonIE_Sodium_Core32_Int32 $h5 */
186 $h5 = ParagonIE_Sodium_Core32_Int32::fromInt(
187 self::load_4(self::substr($s, 16, 4))
188 );
189 /** @var ParagonIE_Sodium_Core32_Int32 $h6 */
190 $h6 = ParagonIE_Sodium_Core32_Int32::fromInt(
191 self::load_3(self::substr($s, 20, 3)) << 7
192 );
193 /** @var ParagonIE_Sodium_Core32_Int32 $h7 */
194 $h7 = ParagonIE_Sodium_Core32_Int32::fromInt(
195 self::load_3(self::substr($s, 23, 3)) << 5
196 );
197 /** @var ParagonIE_Sodium_Core32_Int32 $h8 */
198 $h8 = ParagonIE_Sodium_Core32_Int32::fromInt(
199 self::load_3(self::substr($s, 26, 3)) << 4
200 );
201 /** @var ParagonIE_Sodium_Core32_Int32 $h9 */
202 $h9 = ParagonIE_Sodium_Core32_Int32::fromInt(
203 (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2
204 );
205
206 $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
207 $h0 = $h0->addInt32($carry9->mulInt(19, 5));
208 $h9 = $h9->subInt32($carry9->shiftLeft(25));
209
210 $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
211 $h2 = $h2->addInt32($carry1);
212 $h1 = $h1->subInt32($carry1->shiftLeft(25));
213
214 $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
215 $h4 = $h4->addInt32($carry3);
216 $h3 = $h3->subInt32($carry3->shiftLeft(25));
217
218 $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
219 $h6 = $h6->addInt32($carry5);
220 $h5 = $h5->subInt32($carry5->shiftLeft(25));
221
222 $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
223 $h8 = $h8->addInt32($carry7);
224 $h7 = $h7->subInt32($carry7->shiftLeft(25));
225
226 $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
227 $h1 = $h1->addInt32($carry0);
228 $h0 = $h0->subInt32($carry0->shiftLeft(26));
229
230 $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
231 $h3 = $h3->addInt32($carry2);
232 $h2 = $h2->subInt32($carry2->shiftLeft(26));
233
234 $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
235 $h5 = $h5->addInt32($carry4);
236 $h4 = $h4->subInt32($carry4->shiftLeft(26));
237
238 $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
239 $h7 = $h7->addInt32($carry6);
240 $h6 = $h6->subInt32($carry6->shiftLeft(26));
241
242 $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
243 $h9 = $h9->addInt32($carry8);
244 $h8 = $h8->subInt32($carry8->shiftLeft(26));
245
246 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
247 array($h0, $h1, $h2,$h3, $h4, $h5, $h6, $h7, $h8, $h9)
248 );
249 }
250
251 /**
252 * Convert a field element to a byte string.
253 *
254 * @internal You should not use this directly from another application
255 *
256 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $h
257 * @return string
258 * @throws SodiumException
259 * @throws TypeError
260 * @psalm-suppress MixedAssignment
261 * @psalm-suppress MixedMethodCall
262 */
263 public static function fe_tobytes(ParagonIE_Sodium_Core32_Curve25519_Fe $h)
264 {
265 /**
266 * @var ParagonIE_Sodium_Core32_Int64[] $f
267 * @var ParagonIE_Sodium_Core32_Int64 $q
268 */
269 $f = array();
270
271 for ($i = 0; $i < 10; ++$i) {
272 $f[$i] = $h[$i]->toInt64();
273 }
274
275 $q = $f[9]->mulInt(19, 5)->addInt(1 << 14)->shiftRight(25)
276 ->addInt64($f[0])->shiftRight(26)
277 ->addInt64($f[1])->shiftRight(25)
278 ->addInt64($f[2])->shiftRight(26)
279 ->addInt64($f[3])->shiftRight(25)
280 ->addInt64($f[4])->shiftRight(26)
281 ->addInt64($f[5])->shiftRight(25)
282 ->addInt64($f[6])->shiftRight(26)
283 ->addInt64($f[7])->shiftRight(25)
284 ->addInt64($f[8])->shiftRight(26)
285 ->addInt64($f[9])->shiftRight(25);
286
287 $f[0] = $f[0]->addInt64($q->mulInt(19, 5));
288
289 $carry0 = $f[0]->shiftRight(26);
290 $f[1] = $f[1]->addInt64($carry0);
291 $f[0] = $f[0]->subInt64($carry0->shiftLeft(26));
292
293 $carry1 = $f[1]->shiftRight(25);
294 $f[2] = $f[2]->addInt64($carry1);
295 $f[1] = $f[1]->subInt64($carry1->shiftLeft(25));
296
297 $carry2 = $f[2]->shiftRight(26);
298 $f[3] = $f[3]->addInt64($carry2);
299 $f[2] = $f[2]->subInt64($carry2->shiftLeft(26));
300
301 $carry3 = $f[3]->shiftRight(25);
302 $f[4] = $f[4]->addInt64($carry3);
303 $f[3] = $f[3]->subInt64($carry3->shiftLeft(25));
304
305 $carry4 = $f[4]->shiftRight(26);
306 $f[5] = $f[5]->addInt64($carry4);
307 $f[4] = $f[4]->subInt64($carry4->shiftLeft(26));
308
309 $carry5 = $f[5]->shiftRight(25);
310 $f[6] = $f[6]->addInt64($carry5);
311 $f[5] = $f[5]->subInt64($carry5->shiftLeft(25));
312
313 $carry6 = $f[6]->shiftRight(26);
314 $f[7] = $f[7]->addInt64($carry6);
315 $f[6] = $f[6]->subInt64($carry6->shiftLeft(26));
316
317 $carry7 = $f[7]->shiftRight(25);
318 $f[8] = $f[8]->addInt64($carry7);
319 $f[7] = $f[7]->subInt64($carry7->shiftLeft(25));
320
321 $carry8 = $f[8]->shiftRight(26);
322 $f[9] = $f[9]->addInt64($carry8);
323 $f[8] = $f[8]->subInt64($carry8->shiftLeft(26));
324
325 $carry9 = $f[9]->shiftRight(25);
326 $f[9] = $f[9]->subInt64($carry9->shiftLeft(25));
327
328 $h0 = $f[0]->toInt32()->toInt();
329 $h1 = $f[1]->toInt32()->toInt();
330 $h2 = $f[2]->toInt32()->toInt();
331 $h3 = $f[3]->toInt32()->toInt();
332 $h4 = $f[4]->toInt32()->toInt();
333 $h5 = $f[5]->toInt32()->toInt();
334 $h6 = $f[6]->toInt32()->toInt();
335 $h7 = $f[7]->toInt32()->toInt();
336 $h8 = $f[8]->toInt32()->toInt();
337 $h9 = $f[9]->toInt32()->toInt();
338
339 /**
340 * @var array<int, int>
341 */
342 $s = array(
343 (int) (($h0 >> 0) & 0xff),
344 (int) (($h0 >> 8) & 0xff),
345 (int) (($h0 >> 16) & 0xff),
346 (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
347 (int) (($h1 >> 6) & 0xff),
348 (int) (($h1 >> 14) & 0xff),
349 (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
350 (int) (($h2 >> 5) & 0xff),
351 (int) (($h2 >> 13) & 0xff),
352 (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
353 (int) (($h3 >> 3) & 0xff),
354 (int) (($h3 >> 11) & 0xff),
355 (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
356 (int) (($h4 >> 2) & 0xff),
357 (int) (($h4 >> 10) & 0xff),
358 (int) (($h4 >> 18) & 0xff),
359 (int) (($h5 >> 0) & 0xff),
360 (int) (($h5 >> 8) & 0xff),
361 (int) (($h5 >> 16) & 0xff),
362 (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
363 (int) (($h6 >> 7) & 0xff),
364 (int) (($h6 >> 15) & 0xff),
365 (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
366 (int) (($h7 >> 5) & 0xff),
367 (int) (($h7 >> 13) & 0xff),
368 (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
369 (int) (($h8 >> 4) & 0xff),
370 (int) (($h8 >> 12) & 0xff),
371 (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
372 (int) (($h9 >> 2) & 0xff),
373 (int) (($h9 >> 10) & 0xff),
374 (int) (($h9 >> 18) & 0xff)
375 );
376 return self::intArrayToString($s);
377 }
378
379 /**
380 * Is a field element negative? (1 = yes, 0 = no. Used in calculations.)
381 *
382 * @internal You should not use this directly from another application
383 *
384 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
385 * @return int
386 * @throws SodiumException
387 * @throws TypeError
388 */
389 public static function fe_isnegative(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
390 {
391 $str = self::fe_tobytes($f);
392 return (int) (self::chrToInt($str[0]) & 1);
393 }
394
395 /**
396 * Returns 0 if this field element results in all NUL bytes.
397 *
398 * @internal You should not use this directly from another application
399 *
400 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
401 * @return bool
402 * @throws SodiumException
403 * @throws TypeError
404 */
405 public static function fe_isnonzero(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
406 {
407 static $zero;
408 if ($zero === null) {
409 $zero = str_repeat("\x00", 32);
410 }
411 $str = self::fe_tobytes($f);
412 /** @var string $zero */
413 return !self::verify_32($str, $zero);
414 }
415
416 /**
417 * Multiply two field elements
418 *
419 * h = f * g
420 *
421 * @internal You should not use this directly from another application
422 *
423 * @security Is multiplication a source of timing leaks? If so, can we do
424 * anything to prevent that from happening?
425 *
426 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
427 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
428 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
429 * @throws SodiumException
430 * @throws TypeError
431 */
432 public static function fe_mul(
433 ParagonIE_Sodium_Core32_Curve25519_Fe $f,
434 ParagonIE_Sodium_Core32_Curve25519_Fe $g
435 ) {
436 /**
437 * @var ParagonIE_Sodium_Core32_Int32[] $f
438 * @var ParagonIE_Sodium_Core32_Int32[] $g
439 * @var ParagonIE_Sodium_Core32_Int64 $f0
440 * @var ParagonIE_Sodium_Core32_Int64 $f1
441 * @var ParagonIE_Sodium_Core32_Int64 $f2
442 * @var ParagonIE_Sodium_Core32_Int64 $f3
443 * @var ParagonIE_Sodium_Core32_Int64 $f4
444 * @var ParagonIE_Sodium_Core32_Int64 $f5
445 * @var ParagonIE_Sodium_Core32_Int64 $f6
446 * @var ParagonIE_Sodium_Core32_Int64 $f7
447 * @var ParagonIE_Sodium_Core32_Int64 $f8
448 * @var ParagonIE_Sodium_Core32_Int64 $f9
449 * @var ParagonIE_Sodium_Core32_Int64 $g0
450 * @var ParagonIE_Sodium_Core32_Int64 $g1
451 * @var ParagonIE_Sodium_Core32_Int64 $g2
452 * @var ParagonIE_Sodium_Core32_Int64 $g3
453 * @var ParagonIE_Sodium_Core32_Int64 $g4
454 * @var ParagonIE_Sodium_Core32_Int64 $g5
455 * @var ParagonIE_Sodium_Core32_Int64 $g6
456 * @var ParagonIE_Sodium_Core32_Int64 $g7
457 * @var ParagonIE_Sodium_Core32_Int64 $g8
458 * @var ParagonIE_Sodium_Core32_Int64 $g9
459 */
460 $f0 = $f[0]->toInt64();
461 $f1 = $f[1]->toInt64();
462 $f2 = $f[2]->toInt64();
463 $f3 = $f[3]->toInt64();
464 $f4 = $f[4]->toInt64();
465 $f5 = $f[5]->toInt64();
466 $f6 = $f[6]->toInt64();
467 $f7 = $f[7]->toInt64();
468 $f8 = $f[8]->toInt64();
469 $f9 = $f[9]->toInt64();
470 $g0 = $g[0]->toInt64();
471 $g1 = $g[1]->toInt64();
472 $g2 = $g[2]->toInt64();
473 $g3 = $g[3]->toInt64();
474 $g4 = $g[4]->toInt64();
475 $g5 = $g[5]->toInt64();
476 $g6 = $g[6]->toInt64();
477 $g7 = $g[7]->toInt64();
478 $g8 = $g[8]->toInt64();
479 $g9 = $g[9]->toInt64();
480 $g1_19 = $g1->mulInt(19, 5); /* 2^4 <= 19 <= 2^5, but we only want 5 bits */
481 $g2_19 = $g2->mulInt(19, 5);
482 $g3_19 = $g3->mulInt(19, 5);
483 $g4_19 = $g4->mulInt(19, 5);
484 $g5_19 = $g5->mulInt(19, 5);
485 $g6_19 = $g6->mulInt(19, 5);
486 $g7_19 = $g7->mulInt(19, 5);
487 $g8_19 = $g8->mulInt(19, 5);
488 $g9_19 = $g9->mulInt(19, 5);
489 $f1_2 = $f1->shiftLeft(1);
490 $f3_2 = $f3->shiftLeft(1);
491 $f5_2 = $f5->shiftLeft(1);
492 $f7_2 = $f7->shiftLeft(1);
493 $f9_2 = $f9->shiftLeft(1);
494 $f0g0 = $f0->mulInt64($g0, 27);
495 $f0g1 = $f0->mulInt64($g1, 27);
496 $f0g2 = $f0->mulInt64($g2, 27);
497 $f0g3 = $f0->mulInt64($g3, 27);
498 $f0g4 = $f0->mulInt64($g4, 27);
499 $f0g5 = $f0->mulInt64($g5, 27);
500 $f0g6 = $f0->mulInt64($g6, 27);
501 $f0g7 = $f0->mulInt64($g7, 27);
502 $f0g8 = $f0->mulInt64($g8, 27);
503 $f0g9 = $f0->mulInt64($g9, 27);
504 $f1g0 = $f1->mulInt64($g0, 27);
505 $f1g1_2 = $f1_2->mulInt64($g1, 27);
506 $f1g2 = $f1->mulInt64($g2, 27);
507 $f1g3_2 = $f1_2->mulInt64($g3, 27);
508 $f1g4 = $f1->mulInt64($g4, 30);
509 $f1g5_2 = $f1_2->mulInt64($g5, 30);
510 $f1g6 = $f1->mulInt64($g6, 30);
511 $f1g7_2 = $f1_2->mulInt64($g7, 30);
512 $f1g8 = $f1->mulInt64($g8, 30);
513 $f1g9_38 = $g9_19->mulInt64($f1_2, 30);
514 $f2g0 = $f2->mulInt64($g0, 30);
515 $f2g1 = $f2->mulInt64($g1, 29);
516 $f2g2 = $f2->mulInt64($g2, 30);
517 $f2g3 = $f2->mulInt64($g3, 29);
518 $f2g4 = $f2->mulInt64($g4, 30);
519 $f2g5 = $f2->mulInt64($g5, 29);
520 $f2g6 = $f2->mulInt64($g6, 30);
521 $f2g7 = $f2->mulInt64($g7, 29);
522 $f2g8_19 = $g8_19->mulInt64($f2, 30);
523 $f2g9_19 = $g9_19->mulInt64($f2, 30);
524 $f3g0 = $f3->mulInt64($g0, 30);
525 $f3g1_2 = $f3_2->mulInt64($g1, 30);
526 $f3g2 = $f3->mulInt64($g2, 30);
527 $f3g3_2 = $f3_2->mulInt64($g3, 30);
528 $f3g4 = $f3->mulInt64($g4, 30);
529 $f3g5_2 = $f3_2->mulInt64($g5, 30);
530 $f3g6 = $f3->mulInt64($g6, 30);
531 $f3g7_38 = $g7_19->mulInt64($f3_2, 30);
532 $f3g8_19 = $g8_19->mulInt64($f3, 30);
533 $f3g9_38 = $g9_19->mulInt64($f3_2, 30);
534 $f4g0 = $f4->mulInt64($g0, 30);
535 $f4g1 = $f4->mulInt64($g1, 30);
536 $f4g2 = $f4->mulInt64($g2, 30);
537 $f4g3 = $f4->mulInt64($g3, 30);
538 $f4g4 = $f4->mulInt64($g4, 30);
539 $f4g5 = $f4->mulInt64($g5, 30);
540 $f4g6_19 = $g6_19->mulInt64($f4, 30);
541 $f4g7_19 = $g7_19->mulInt64($f4, 30);
542 $f4g8_19 = $g8_19->mulInt64($f4, 30);
543 $f4g9_19 = $g9_19->mulInt64($f4, 30);
544 $f5g0 = $f5->mulInt64($g0, 30);
545 $f5g1_2 = $f5_2->mulInt64($g1, 30);
546 $f5g2 = $f5->mulInt64($g2, 30);
547 $f5g3_2 = $f5_2->mulInt64($g3, 30);
548 $f5g4 = $f5->mulInt64($g4, 30);
549 $f5g5_38 = $g5_19->mulInt64($f5_2, 30);
550 $f5g6_19 = $g6_19->mulInt64($f5, 30);
551 $f5g7_38 = $g7_19->mulInt64($f5_2, 30);
552 $f5g8_19 = $g8_19->mulInt64($f5, 30);
553 $f5g9_38 = $g9_19->mulInt64($f5_2, 30);
554 $f6g0 = $f6->mulInt64($g0, 30);
555 $f6g1 = $f6->mulInt64($g1, 30);
556 $f6g2 = $f6->mulInt64($g2, 30);
557 $f6g3 = $f6->mulInt64($g3, 30);
558 $f6g4_19 = $g4_19->mulInt64($f6, 30);
559 $f6g5_19 = $g5_19->mulInt64($f6, 30);
560 $f6g6_19 = $g6_19->mulInt64($f6, 30);
561 $f6g7_19 = $g7_19->mulInt64($f6, 30);
562 $f6g8_19 = $g8_19->mulInt64($f6, 30);
563 $f6g9_19 = $g9_19->mulInt64($f6, 30);
564 $f7g0 = $f7->mulInt64($g0, 30);
565 $f7g1_2 = $g1->mulInt64($f7_2, 30);
566 $f7g2 = $f7->mulInt64($g2, 30);
567 $f7g3_38 = $g3_19->mulInt64($f7_2, 30);
568 $f7g4_19 = $g4_19->mulInt64($f7, 30);
569 $f7g5_38 = $g5_19->mulInt64($f7_2, 30);
570 $f7g6_19 = $g6_19->mulInt64($f7, 30);
571 $f7g7_38 = $g7_19->mulInt64($f7_2, 30);
572 $f7g8_19 = $g8_19->mulInt64($f7, 30);
573 $f7g9_38 = $g9_19->mulInt64($f7_2, 30);
574 $f8g0 = $f8->mulInt64($g0, 30);
575 $f8g1 = $f8->mulInt64($g1, 29);
576 $f8g2_19 = $g2_19->mulInt64($f8, 30);
577 $f8g3_19 = $g3_19->mulInt64($f8, 30);
578 $f8g4_19 = $g4_19->mulInt64($f8, 30);
579 $f8g5_19 = $g5_19->mulInt64($f8, 30);
580 $f8g6_19 = $g6_19->mulInt64($f8, 30);
581 $f8g7_19 = $g7_19->mulInt64($f8, 30);
582 $f8g8_19 = $g8_19->mulInt64($f8, 30);
583 $f8g9_19 = $g9_19->mulInt64($f8, 30);
584 $f9g0 = $f9->mulInt64($g0, 30);
585 $f9g1_38 = $g1_19->mulInt64($f9_2, 30);
586 $f9g2_19 = $g2_19->mulInt64($f9, 30);
587 $f9g3_38 = $g3_19->mulInt64($f9_2, 30);
588 $f9g4_19 = $g4_19->mulInt64($f9, 30);
589 $f9g5_38 = $g5_19->mulInt64($f9_2, 30);
590 $f9g6_19 = $g6_19->mulInt64($f9, 30);
591 $f9g7_38 = $g7_19->mulInt64($f9_2, 30);
592 $f9g8_19 = $g8_19->mulInt64($f9, 30);
593 $f9g9_38 = $g9_19->mulInt64($f9_2, 30);
594
595 // $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
596 $h0 = $f0g0->addInt64($f1g9_38)->addInt64($f2g8_19)->addInt64($f3g7_38)
597 ->addInt64($f4g6_19)->addInt64($f5g5_38)->addInt64($f6g4_19)
598 ->addInt64($f7g3_38)->addInt64($f8g2_19)->addInt64($f9g1_38);
599
600 // $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
601 $h1 = $f0g1->addInt64($f1g0)->addInt64($f2g9_19)->addInt64($f3g8_19)
602 ->addInt64($f4g7_19)->addInt64($f5g6_19)->addInt64($f6g5_19)
603 ->addInt64($f7g4_19)->addInt64($f8g3_19)->addInt64($f9g2_19);
604
605 // $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
606 $h2 = $f0g2->addInt64($f1g1_2)->addInt64($f2g0)->addInt64($f3g9_38)
607 ->addInt64($f4g8_19)->addInt64($f5g7_38)->addInt64($f6g6_19)
608 ->addInt64($f7g5_38)->addInt64($f8g4_19)->addInt64($f9g3_38);
609
610 // $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
611 $h3 = $f0g3->addInt64($f1g2)->addInt64($f2g1)->addInt64($f3g0)
612 ->addInt64($f4g9_19)->addInt64($f5g8_19)->addInt64($f6g7_19)
613 ->addInt64($f7g6_19)->addInt64($f8g5_19)->addInt64($f9g4_19);
614
615 // $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
616 $h4 = $f0g4->addInt64($f1g3_2)->addInt64($f2g2)->addInt64($f3g1_2)
617 ->addInt64($f4g0)->addInt64($f5g9_38)->addInt64($f6g8_19)
618 ->addInt64($f7g7_38)->addInt64($f8g6_19)->addInt64($f9g5_38);
619
620 // $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
621 $h5 = $f0g5->addInt64($f1g4)->addInt64($f2g3)->addInt64($f3g2)
622 ->addInt64($f4g1)->addInt64($f5g0)->addInt64($f6g9_19)
623 ->addInt64($f7g8_19)->addInt64($f8g7_19)->addInt64($f9g6_19);
624
625 // $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38;
626 $h6 = $f0g6->addInt64($f1g5_2)->addInt64($f2g4)->addInt64($f3g3_2)
627 ->addInt64($f4g2)->addInt64($f5g1_2)->addInt64($f6g0)
628 ->addInt64($f7g9_38)->addInt64($f8g8_19)->addInt64($f9g7_38);
629
630 // $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19;
631 $h7 = $f0g7->addInt64($f1g6)->addInt64($f2g5)->addInt64($f3g4)
632 ->addInt64($f4g3)->addInt64($f5g2)->addInt64($f6g1)
633 ->addInt64($f7g0)->addInt64($f8g9_19)->addInt64($f9g8_19);
634
635 // $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38;
636 $h8 = $f0g8->addInt64($f1g7_2)->addInt64($f2g6)->addInt64($f3g5_2)
637 ->addInt64($f4g4)->addInt64($f5g3_2)->addInt64($f6g2)
638 ->addInt64($f7g1_2)->addInt64($f8g0)->addInt64($f9g9_38);
639
640 // $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ;
641 $h9 = $f0g9->addInt64($f1g8)->addInt64($f2g7)->addInt64($f3g6)
642 ->addInt64($f4g5)->addInt64($f5g4)->addInt64($f6g3)
643 ->addInt64($f7g2)->addInt64($f8g1)->addInt64($f9g0);
644
645 /**
646 * @var ParagonIE_Sodium_Core32_Int64 $h0
647 * @var ParagonIE_Sodium_Core32_Int64 $h1
648 * @var ParagonIE_Sodium_Core32_Int64 $h2
649 * @var ParagonIE_Sodium_Core32_Int64 $h3
650 * @var ParagonIE_Sodium_Core32_Int64 $h4
651 * @var ParagonIE_Sodium_Core32_Int64 $h5
652 * @var ParagonIE_Sodium_Core32_Int64 $h6
653 * @var ParagonIE_Sodium_Core32_Int64 $h7
654 * @var ParagonIE_Sodium_Core32_Int64 $h8
655 * @var ParagonIE_Sodium_Core32_Int64 $h9
656 * @var ParagonIE_Sodium_Core32_Int64 $carry0
657 * @var ParagonIE_Sodium_Core32_Int64 $carry1
658 * @var ParagonIE_Sodium_Core32_Int64 $carry2
659 * @var ParagonIE_Sodium_Core32_Int64 $carry3
660 * @var ParagonIE_Sodium_Core32_Int64 $carry4
661 * @var ParagonIE_Sodium_Core32_Int64 $carry5
662 * @var ParagonIE_Sodium_Core32_Int64 $carry6
663 * @var ParagonIE_Sodium_Core32_Int64 $carry7
664 * @var ParagonIE_Sodium_Core32_Int64 $carry8
665 * @var ParagonIE_Sodium_Core32_Int64 $carry9
666 */
667 $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
668 $h1 = $h1->addInt64($carry0);
669 $h0 = $h0->subInt64($carry0->shiftLeft(26));
670 $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
671 $h5 = $h5->addInt64($carry4);
672 $h4 = $h4->subInt64($carry4->shiftLeft(26));
673
674 $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
675 $h2 = $h2->addInt64($carry1);
676 $h1 = $h1->subInt64($carry1->shiftLeft(25));
677 $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
678 $h6 = $h6->addInt64($carry5);
679 $h5 = $h5->subInt64($carry5->shiftLeft(25));
680
681 $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
682 $h3 = $h3->addInt64($carry2);
683 $h2 = $h2->subInt64($carry2->shiftLeft(26));
684 $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
685 $h7 = $h7->addInt64($carry6);
686 $h6 = $h6->subInt64($carry6->shiftLeft(26));
687
688 $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
689 $h4 = $h4->addInt64($carry3);
690 $h3 = $h3->subInt64($carry3->shiftLeft(25));
691 $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
692 $h8 = $h8->addInt64($carry7);
693 $h7 = $h7->subInt64($carry7->shiftLeft(25));
694
695 $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
696 $h5 = $h5->addInt64($carry4);
697 $h4 = $h4->subInt64($carry4->shiftLeft(26));
698 $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
699 $h9 = $h9->addInt64($carry8);
700 $h8 = $h8->subInt64($carry8->shiftLeft(26));
701
702 $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
703 $h0 = $h0->addInt64($carry9->mulInt(19, 5));
704 $h9 = $h9->subInt64($carry9->shiftLeft(25));
705
706 $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
707 $h1 = $h1->addInt64($carry0);
708 $h0 = $h0->subInt64($carry0->shiftLeft(26));
709
710 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
711 array(
712 $h0->toInt32(),
713 $h1->toInt32(),
714 $h2->toInt32(),
715 $h3->toInt32(),
716 $h4->toInt32(),
717 $h5->toInt32(),
718 $h6->toInt32(),
719 $h7->toInt32(),
720 $h8->toInt32(),
721 $h9->toInt32()
722 )
723 );
724 }
725
726 /**
727 * Get the negative values for each piece of the field element.
728 *
729 * h = -f
730 *
731 * @internal You should not use this directly from another application
732 *
733 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
734 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
735 * @psalm-suppress MixedAssignment
736 * @psalm-suppress MixedMethodCall
737 */
738 public static function fe_neg(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
739 {
740 $h = new ParagonIE_Sodium_Core32_Curve25519_Fe();
741 for ($i = 0; $i < 10; ++$i) {
742 $h[$i] = $h[$i]->subInt32($f[$i]);
743 }
744 return $h;
745 }
746
747 /**
748 * Square a field element
749 *
750 * h = f * f
751 *
752 * @internal You should not use this directly from another application
753 *
754 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
755 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
756 * @throws SodiumException
757 * @throws TypeError
758 * @psalm-suppress MixedMethodCall
759 */
760 public static function fe_sq(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
761 {
762 $f0 = $f[0]->toInt64();
763 $f1 = $f[1]->toInt64();
764 $f2 = $f[2]->toInt64();
765 $f3 = $f[3]->toInt64();
766 $f4 = $f[4]->toInt64();
767 $f5 = $f[5]->toInt64();
768 $f6 = $f[6]->toInt64();
769 $f7 = $f[7]->toInt64();
770 $f8 = $f[8]->toInt64();
771 $f9 = $f[9]->toInt64();
772
773 $f0_2 = $f0->shiftLeft(1);
774 $f1_2 = $f1->shiftLeft(1);
775 $f2_2 = $f2->shiftLeft(1);
776 $f3_2 = $f3->shiftLeft(1);
777 $f4_2 = $f4->shiftLeft(1);
778 $f5_2 = $f5->shiftLeft(1);
779 $f6_2 = $f6->shiftLeft(1);
780 $f7_2 = $f7->shiftLeft(1);
781 $f5_38 = $f5->mulInt(38, 6);
782 $f6_19 = $f6->mulInt(19, 5);
783 $f7_38 = $f7->mulInt(38, 6);
784 $f8_19 = $f8->mulInt(19, 5);
785 $f9_38 = $f9->mulInt(38, 6);
786
787 $f0f0 = $f0->mulInt64($f0, 28);
788 $f0f1_2 = $f0_2->mulInt64($f1, 28);
789 $f0f2_2 = $f0_2->mulInt64($f2, 28);
790 $f0f3_2 = $f0_2->mulInt64($f3, 28);
791 $f0f4_2 = $f0_2->mulInt64($f4, 28);
792 $f0f5_2 = $f0_2->mulInt64($f5, 28);
793 $f0f6_2 = $f0_2->mulInt64($f6, 28);
794 $f0f7_2 = $f0_2->mulInt64($f7, 28);
795 $f0f8_2 = $f0_2->mulInt64($f8, 28);
796 $f0f9_2 = $f0_2->mulInt64($f9, 28);
797
798 $f1f1_2 = $f1_2->mulInt64($f1, 28);
799 $f1f2_2 = $f1_2->mulInt64($f2, 28);
800 $f1f3_4 = $f1_2->mulInt64($f3_2, 28);
801 $f1f4_2 = $f1_2->mulInt64($f4, 28);
802 $f1f5_4 = $f1_2->mulInt64($f5_2, 30);
803 $f1f6_2 = $f1_2->mulInt64($f6, 28);
804 $f1f7_4 = $f1_2->mulInt64($f7_2, 28);
805 $f1f8_2 = $f1_2->mulInt64($f8, 28);
806 $f1f9_76 = $f9_38->mulInt64($f1_2, 30);
807
808 $f2f2 = $f2->mulInt64($f2, 28);
809 $f2f3_2 = $f2_2->mulInt64($f3, 28);
810 $f2f4_2 = $f2_2->mulInt64($f4, 28);
811 $f2f5_2 = $f2_2->mulInt64($f5, 28);
812 $f2f6_2 = $f2_2->mulInt64($f6, 28);
813 $f2f7_2 = $f2_2->mulInt64($f7, 28);
814 $f2f8_38 = $f8_19->mulInt64($f2_2, 30);
815 $f2f9_38 = $f9_38->mulInt64($f2, 30);
816
817 $f3f3_2 = $f3_2->mulInt64($f3, 28);
818 $f3f4_2 = $f3_2->mulInt64($f4, 28);
819 $f3f5_4 = $f3_2->mulInt64($f5_2, 30);
820 $f3f6_2 = $f3_2->mulInt64($f6, 28);
821 $f3f7_76 = $f7_38->mulInt64($f3_2, 30);
822 $f3f8_38 = $f8_19->mulInt64($f3_2, 30);
823 $f3f9_76 = $f9_38->mulInt64($f3_2, 30);
824
825 $f4f4 = $f4->mulInt64($f4, 28);
826 $f4f5_2 = $f4_2->mulInt64($f5, 28);
827 $f4f6_38 = $f6_19->mulInt64($f4_2, 30);
828 $f4f7_38 = $f7_38->mulInt64($f4, 30);
829 $f4f8_38 = $f8_19->mulInt64($f4_2, 30);
830 $f4f9_38 = $f9_38->mulInt64($f4, 30);
831
832 $f5f5_38 = $f5_38->mulInt64($f5, 30);
833 $f5f6_38 = $f6_19->mulInt64($f5_2, 30);
834 $f5f7_76 = $f7_38->mulInt64($f5_2, 30);
835 $f5f8_38 = $f8_19->mulInt64($f5_2, 30);
836 $f5f9_76 = $f9_38->mulInt64($f5_2, 30);
837
838 $f6f6_19 = $f6_19->mulInt64($f6, 30);
839 $f6f7_38 = $f7_38->mulInt64($f6, 30);
840 $f6f8_38 = $f8_19->mulInt64($f6_2, 30);
841 $f6f9_38 = $f9_38->mulInt64($f6, 30);
842
843 $f7f7_38 = $f7_38->mulInt64($f7, 28);
844 $f7f8_38 = $f8_19->mulInt64($f7_2, 30);
845 $f7f9_76 = $f9_38->mulInt64($f7_2, 30);
846
847 $f8f8_19 = $f8_19->mulInt64($f8, 30);
848 $f8f9_38 = $f9_38->mulInt64($f8, 30);
849
850 $f9f9_38 = $f9_38->mulInt64($f9, 28);
851
852 $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
853 $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
854 $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
855 $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
856 $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
857 $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
858 $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
859 $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
860 $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
861 $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
862
863 /**
864 * @var ParagonIE_Sodium_Core32_Int64 $h0
865 * @var ParagonIE_Sodium_Core32_Int64 $h1
866 * @var ParagonIE_Sodium_Core32_Int64 $h2
867 * @var ParagonIE_Sodium_Core32_Int64 $h3
868 * @var ParagonIE_Sodium_Core32_Int64 $h4
869 * @var ParagonIE_Sodium_Core32_Int64 $h5
870 * @var ParagonIE_Sodium_Core32_Int64 $h6
871 * @var ParagonIE_Sodium_Core32_Int64 $h7
872 * @var ParagonIE_Sodium_Core32_Int64 $h8
873 * @var ParagonIE_Sodium_Core32_Int64 $h9
874 */
875
876 $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
877 $h1 = $h1->addInt64($carry0);
878 $h0 = $h0->subInt64($carry0->shiftLeft(26));
879
880 $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
881 $h5 = $h5->addInt64($carry4);
882 $h4 = $h4->subInt64($carry4->shiftLeft(26));
883
884 $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
885 $h2 = $h2->addInt64($carry1);
886 $h1 = $h1->subInt64($carry1->shiftLeft(25));
887
888 $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
889 $h6 = $h6->addInt64($carry5);
890 $h5 = $h5->subInt64($carry5->shiftLeft(25));
891
892 $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
893 $h3 = $h3->addInt64($carry2);
894 $h2 = $h2->subInt64($carry2->shiftLeft(26));
895
896 $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
897 $h7 = $h7->addInt64($carry6);
898 $h6 = $h6->subInt64($carry6->shiftLeft(26));
899
900 $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
901 $h4 = $h4->addInt64($carry3);
902 $h3 = $h3->subInt64($carry3->shiftLeft(25));
903
904 $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
905 $h8 = $h8->addInt64($carry7);
906 $h7 = $h7->subInt64($carry7->shiftLeft(25));
907
908 $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
909 $h5 = $h5->addInt64($carry4);
910 $h4 = $h4->subInt64($carry4->shiftLeft(26));
911
912 $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
913 $h9 = $h9->addInt64($carry8);
914 $h8 = $h8->subInt64($carry8->shiftLeft(26));
915
916 $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
917 $h0 = $h0->addInt64($carry9->mulInt(19, 5));
918 $h9 = $h9->subInt64($carry9->shiftLeft(25));
919
920 $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
921 $h1 = $h1->addInt64($carry0);
922 $h0 = $h0->subInt64($carry0->shiftLeft(26));
923
924 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
925 array(
926 $h0->toInt32(),
927 $h1->toInt32(),
928 $h2->toInt32(),
929 $h3->toInt32(),
930 $h4->toInt32(),
931 $h5->toInt32(),
932 $h6->toInt32(),
933 $h7->toInt32(),
934 $h8->toInt32(),
935 $h9->toInt32()
936 )
937 );
938 }
939
940 /**
941 * Square and double a field element
942 *
943 * h = 2 * f * f
944 *
945 * @internal You should not use this directly from another application
946 *
947 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
948 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
949 * @throws SodiumException
950 * @throws TypeError
951 * @psalm-suppress MixedMethodCall
952 */
953 public static function fe_sq2(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
954 {
955 $f0 = $f[0]->toInt64();
956 $f1 = $f[1]->toInt64();
957 $f2 = $f[2]->toInt64();
958 $f3 = $f[3]->toInt64();
959 $f4 = $f[4]->toInt64();
960 $f5 = $f[5]->toInt64();
961 $f6 = $f[6]->toInt64();
962 $f7 = $f[7]->toInt64();
963 $f8 = $f[8]->toInt64();
964 $f9 = $f[9]->toInt64();
965
966 $f0_2 = $f0->shiftLeft(1);
967 $f1_2 = $f1->shiftLeft(1);
968 $f2_2 = $f2->shiftLeft(1);
969 $f3_2 = $f3->shiftLeft(1);
970 $f4_2 = $f4->shiftLeft(1);
971 $f5_2 = $f5->shiftLeft(1);
972 $f6_2 = $f6->shiftLeft(1);
973 $f7_2 = $f7->shiftLeft(1);
974 $f5_38 = $f5->mulInt(38, 6); /* 1.959375*2^30 */
975 $f6_19 = $f6->mulInt(19, 5); /* 1.959375*2^30 */
976 $f7_38 = $f7->mulInt(38, 6); /* 1.959375*2^30 */
977 $f8_19 = $f8->mulInt(19, 5); /* 1.959375*2^30 */
978 $f9_38 = $f9->mulInt(38, 6); /* 1.959375*2^30 */
979 $f0f0 = $f0->mulInt64($f0, 28);
980 $f0f1_2 = $f0_2->mulInt64($f1, 28);
981 $f0f2_2 = $f0_2->mulInt64($f2, 28);
982 $f0f3_2 = $f0_2->mulInt64($f3, 28);
983 $f0f4_2 = $f0_2->mulInt64($f4, 28);
984 $f0f5_2 = $f0_2->mulInt64($f5, 28);
985 $f0f6_2 = $f0_2->mulInt64($f6, 28);
986 $f0f7_2 = $f0_2->mulInt64($f7, 28);
987 $f0f8_2 = $f0_2->mulInt64($f8, 28);
988 $f0f9_2 = $f0_2->mulInt64($f9, 28);
989 $f1f1_2 = $f1_2->mulInt64($f1, 28);
990 $f1f2_2 = $f1_2->mulInt64($f2, 28);
991 $f1f3_4 = $f1_2->mulInt64($f3_2, 29);
992 $f1f4_2 = $f1_2->mulInt64($f4, 28);
993 $f1f5_4 = $f1_2->mulInt64($f5_2, 29);
994 $f1f6_2 = $f1_2->mulInt64($f6, 28);
995 $f1f7_4 = $f1_2->mulInt64($f7_2, 29);
996 $f1f8_2 = $f1_2->mulInt64($f8, 28);
997 $f1f9_76 = $f9_38->mulInt64($f1_2, 29);
998 $f2f2 = $f2->mulInt64($f2, 28);
999 $f2f3_2 = $f2_2->mulInt64($f3, 28);
1000 $f2f4_2 = $f2_2->mulInt64($f4, 28);
1001 $f2f5_2 = $f2_2->mulInt64($f5, 28);
1002 $f2f6_2 = $f2_2->mulInt64($f6, 28);
1003 $f2f7_2 = $f2_2->mulInt64($f7, 28);
1004 $f2f8_38 = $f8_19->mulInt64($f2_2, 29);
1005 $f2f9_38 = $f9_38->mulInt64($f2, 29);
1006 $f3f3_2 = $f3_2->mulInt64($f3, 28);
1007 $f3f4_2 = $f3_2->mulInt64($f4, 28);
1008 $f3f5_4 = $f3_2->mulInt64($f5_2, 28);
1009 $f3f6_2 = $f3_2->mulInt64($f6, 28);
1010 $f3f7_76 = $f7_38->mulInt64($f3_2, 29);
1011 $f3f8_38 = $f8_19->mulInt64($f3_2, 29);
1012 $f3f9_76 = $f9_38->mulInt64($f3_2, 29);
1013 $f4f4 = $f4->mulInt64($f4, 28);
1014 $f4f5_2 = $f4_2->mulInt64($f5, 28);
1015 $f4f6_38 = $f6_19->mulInt64($f4_2, 29);
1016 $f4f7_38 = $f7_38->mulInt64($f4, 29);
1017 $f4f8_38 = $f8_19->mulInt64($f4_2, 29);
1018 $f4f9_38 = $f9_38->mulInt64($f4, 29);
1019 $f5f5_38 = $f5_38->mulInt64($f5, 29);
1020 $f5f6_38 = $f6_19->mulInt64($f5_2, 29);
1021 $f5f7_76 = $f7_38->mulInt64($f5_2, 29);
1022 $f5f8_38 = $f8_19->mulInt64($f5_2, 29);
1023 $f5f9_76 = $f9_38->mulInt64($f5_2, 29);
1024 $f6f6_19 = $f6_19->mulInt64($f6, 29);
1025 $f6f7_38 = $f7_38->mulInt64($f6, 29);
1026 $f6f8_38 = $f8_19->mulInt64($f6_2, 29);
1027 $f6f9_38 = $f9_38->mulInt64($f6, 29);
1028 $f7f7_38 = $f7_38->mulInt64($f7, 29);
1029 $f7f8_38 = $f8_19->mulInt64($f7_2, 29);
1030 $f7f9_76 = $f9_38->mulInt64($f7_2, 29);
1031 $f8f8_19 = $f8_19->mulInt64($f8, 29);
1032 $f8f9_38 = $f9_38->mulInt64($f8, 29);
1033 $f9f9_38 = $f9_38->mulInt64($f9, 29);
1034
1035 $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
1036 $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
1037 $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
1038 $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
1039 $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
1040 $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
1041 $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
1042 $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
1043 $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
1044 $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
1045
1046 /**
1047 * @var ParagonIE_Sodium_Core32_Int64 $h0
1048 * @var ParagonIE_Sodium_Core32_Int64 $h1
1049 * @var ParagonIE_Sodium_Core32_Int64 $h2
1050 * @var ParagonIE_Sodium_Core32_Int64 $h3
1051 * @var ParagonIE_Sodium_Core32_Int64 $h4
1052 * @var ParagonIE_Sodium_Core32_Int64 $h5
1053 * @var ParagonIE_Sodium_Core32_Int64 $h6
1054 * @var ParagonIE_Sodium_Core32_Int64 $h7
1055 * @var ParagonIE_Sodium_Core32_Int64 $h8
1056 * @var ParagonIE_Sodium_Core32_Int64 $h9
1057 */
1058 $h0 = $h0->shiftLeft(1);
1059 $h1 = $h1->shiftLeft(1);
1060 $h2 = $h2->shiftLeft(1);
1061 $h3 = $h3->shiftLeft(1);
1062 $h4 = $h4->shiftLeft(1);
1063 $h5 = $h5->shiftLeft(1);
1064 $h6 = $h6->shiftLeft(1);
1065 $h7 = $h7->shiftLeft(1);
1066 $h8 = $h8->shiftLeft(1);
1067 $h9 = $h9->shiftLeft(1);
1068
1069 $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
1070 $h1 = $h1->addInt64($carry0);
1071 $h0 = $h0->subInt64($carry0->shiftLeft(26));
1072 $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
1073 $h5 = $h5->addInt64($carry4);
1074 $h4 = $h4->subInt64($carry4->shiftLeft(26));
1075
1076 $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
1077 $h2 = $h2->addInt64($carry1);
1078 $h1 = $h1->subInt64($carry1->shiftLeft(25));
1079 $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
1080 $h6 = $h6->addInt64($carry5);
1081 $h5 = $h5->subInt64($carry5->shiftLeft(25));
1082
1083 $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
1084 $h3 = $h3->addInt64($carry2);
1085 $h2 = $h2->subInt64($carry2->shiftLeft(26));
1086 $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
1087 $h7 = $h7->addInt64($carry6);
1088 $h6 = $h6->subInt64($carry6->shiftLeft(26));
1089
1090 $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
1091 $h4 = $h4->addInt64($carry3);
1092 $h3 = $h3->subInt64($carry3->shiftLeft(25));
1093 $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
1094 $h8 = $h8->addInt64($carry7);
1095 $h7 = $h7->subInt64($carry7->shiftLeft(25));
1096
1097 $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
1098 $h5 = $h5->addInt64($carry4);
1099 $h4 = $h4->subInt64($carry4->shiftLeft(26));
1100 $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
1101 $h9 = $h9->addInt64($carry8);
1102 $h8 = $h8->subInt64($carry8->shiftLeft(26));
1103
1104 $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
1105 $h0 = $h0->addInt64($carry9->mulInt(19, 5));
1106 $h9 = $h9->subInt64($carry9->shiftLeft(25));
1107
1108 $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
1109 $h1 = $h1->addInt64($carry0);
1110 $h0 = $h0->subInt64($carry0->shiftLeft(26));
1111
1112 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1113 array(
1114 $h0->toInt32(),
1115 $h1->toInt32(),
1116 $h2->toInt32(),
1117 $h3->toInt32(),
1118 $h4->toInt32(),
1119 $h5->toInt32(),
1120 $h6->toInt32(),
1121 $h7->toInt32(),
1122 $h8->toInt32(),
1123 $h9->toInt32()
1124 )
1125 );
1126 }
1127
1128 /**
1129 * @internal You should not use this directly from another application
1130 *
1131 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $Z
1132 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
1133 * @throws SodiumException
1134 * @throws TypeError
1135 */
1136 public static function fe_invert(ParagonIE_Sodium_Core32_Curve25519_Fe $Z)
1137 {
1138 $z = clone $Z;
1139 $t0 = self::fe_sq($z);
1140 $t1 = self::fe_sq($t0);
1141 $t1 = self::fe_sq($t1);
1142 $t1 = self::fe_mul($z, $t1);
1143 $t0 = self::fe_mul($t0, $t1);
1144 $t2 = self::fe_sq($t0);
1145 $t1 = self::fe_mul($t1, $t2);
1146 $t2 = self::fe_sq($t1);
1147 for ($i = 1; $i < 5; ++$i) {
1148 $t2 = self::fe_sq($t2);
1149 }
1150 $t1 = self::fe_mul($t2, $t1);
1151 $t2 = self::fe_sq($t1);
1152 for ($i = 1; $i < 10; ++$i) {
1153 $t2 = self::fe_sq($t2);
1154 }
1155 $t2 = self::fe_mul($t2, $t1);
1156 $t3 = self::fe_sq($t2);
1157 for ($i = 1; $i < 20; ++$i) {
1158 $t3 = self::fe_sq($t3);
1159 }
1160 $t2 = self::fe_mul($t3, $t2);
1161 $t2 = self::fe_sq($t2);
1162 for ($i = 1; $i < 10; ++$i) {
1163 $t2 = self::fe_sq($t2);
1164 }
1165 $t1 = self::fe_mul($t2, $t1);
1166 $t2 = self::fe_sq($t1);
1167 for ($i = 1; $i < 50; ++$i) {
1168 $t2 = self::fe_sq($t2);
1169 }
1170 $t2 = self::fe_mul($t2, $t1);
1171 $t3 = self::fe_sq($t2);
1172 for ($i = 1; $i < 100; ++$i) {
1173 $t3 = self::fe_sq($t3);
1174 }
1175 $t2 = self::fe_mul($t3, $t2);
1176 $t2 = self::fe_sq($t2);
1177 for ($i = 1; $i < 50; ++$i) {
1178 $t2 = self::fe_sq($t2);
1179 }
1180 $t1 = self::fe_mul($t2, $t1);
1181 $t1 = self::fe_sq($t1);
1182 for ($i = 1; $i < 5; ++$i) {
1183 $t1 = self::fe_sq($t1);
1184 }
1185 return self::fe_mul($t1, $t0);
1186 }
1187
1188 /**
1189 * @internal You should not use this directly from another application
1190 *
1191 * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
1192 *
1193 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $z
1194 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
1195 * @throws SodiumException
1196 * @throws TypeError
1197 */
1198 public static function fe_pow22523(ParagonIE_Sodium_Core32_Curve25519_Fe $z)
1199 {
1200 # fe_sq(t0, z);
1201 # fe_sq(t1, t0);
1202 # fe_sq(t1, t1);
1203 # fe_mul(t1, z, t1);
1204 # fe_mul(t0, t0, t1);
1205 # fe_sq(t0, t0);
1206 # fe_mul(t0, t1, t0);
1207 # fe_sq(t1, t0);
1208 $t0 = self::fe_sq($z);
1209 $t1 = self::fe_sq($t0);
1210 $t1 = self::fe_sq($t1);
1211 $t1 = self::fe_mul($z, $t1);
1212 $t0 = self::fe_mul($t0, $t1);
1213 $t0 = self::fe_sq($t0);
1214 $t0 = self::fe_mul($t1, $t0);
1215 $t1 = self::fe_sq($t0);
1216
1217 # for (i = 1; i < 5; ++i) {
1218 # fe_sq(t1, t1);
1219 # }
1220 for ($i = 1; $i < 5; ++$i) {
1221 $t1 = self::fe_sq($t1);
1222 }
1223
1224 # fe_mul(t0, t1, t0);
1225 # fe_sq(t1, t0);
1226 $t0 = self::fe_mul($t1, $t0);
1227 $t1 = self::fe_sq($t0);
1228
1229 # for (i = 1; i < 10; ++i) {
1230 # fe_sq(t1, t1);
1231 # }
1232 for ($i = 1; $i < 10; ++$i) {
1233 $t1 = self::fe_sq($t1);
1234 }
1235
1236 # fe_mul(t1, t1, t0);
1237 # fe_sq(t2, t1);
1238 $t1 = self::fe_mul($t1, $t0);
1239 $t2 = self::fe_sq($t1);
1240
1241 # for (i = 1; i < 20; ++i) {
1242 # fe_sq(t2, t2);
1243 # }
1244 for ($i = 1; $i < 20; ++$i) {
1245 $t2 = self::fe_sq($t2);
1246 }
1247
1248 # fe_mul(t1, t2, t1);
1249 # fe_sq(t1, t1);
1250 $t1 = self::fe_mul($t2, $t1);
1251 $t1 = self::fe_sq($t1);
1252
1253 # for (i = 1; i < 10; ++i) {
1254 # fe_sq(t1, t1);
1255 # }
1256 for ($i = 1; $i < 10; ++$i) {
1257 $t1 = self::fe_sq($t1);
1258 }
1259
1260 # fe_mul(t0, t1, t0);
1261 # fe_sq(t1, t0);
1262 $t0 = self::fe_mul($t1, $t0);
1263 $t1 = self::fe_sq($t0);
1264
1265 # for (i = 1; i < 50; ++i) {
1266 # fe_sq(t1, t1);
1267 # }
1268 for ($i = 1; $i < 50; ++$i) {
1269 $t1 = self::fe_sq($t1);
1270 }
1271
1272 # fe_mul(t1, t1, t0);
1273 # fe_sq(t2, t1);
1274 $t1 = self::fe_mul($t1, $t0);
1275 $t2 = self::fe_sq($t1);
1276
1277 # for (i = 1; i < 100; ++i) {
1278 # fe_sq(t2, t2);
1279 # }
1280 for ($i = 1; $i < 100; ++$i) {
1281 $t2 = self::fe_sq($t2);
1282 }
1283
1284 # fe_mul(t1, t2, t1);
1285 # fe_sq(t1, t1);
1286 $t1 = self::fe_mul($t2, $t1);
1287 $t1 = self::fe_sq($t1);
1288
1289 # for (i = 1; i < 50; ++i) {
1290 # fe_sq(t1, t1);
1291 # }
1292 for ($i = 1; $i < 50; ++$i) {
1293 $t1 = self::fe_sq($t1);
1294 }
1295
1296 # fe_mul(t0, t1, t0);
1297 # fe_sq(t0, t0);
1298 # fe_sq(t0, t0);
1299 # fe_mul(out, t0, z);
1300 $t0 = self::fe_mul($t1, $t0);
1301 $t0 = self::fe_sq($t0);
1302 $t0 = self::fe_sq($t0);
1303 return self::fe_mul($t0, $z);
1304 }
1305
1306 /**
1307 * Subtract two field elements.
1308 *
1309 * h = f - g
1310 *
1311 * Preconditions:
1312 * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
1313 * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
1314 *
1315 * Postconditions:
1316 * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
1317 *
1318 * @internal You should not use this directly from another application
1319 *
1320 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
1321 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
1322 * @return ParagonIE_Sodium_Core32_Curve25519_Fe
1323 * @throws SodiumException
1324 * @throws TypeError
1325 * @psalm-suppress MixedMethodCall
1326 * @psalm-suppress MixedTypeCoercion
1327 */
1328 public static function fe_sub(ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g)
1329 {
1330 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1331 array(
1332 $f[0]->subInt32($g[0]),
1333 $f[1]->subInt32($g[1]),
1334 $f[2]->subInt32($g[2]),
1335 $f[3]->subInt32($g[3]),
1336 $f[4]->subInt32($g[4]),
1337 $f[5]->subInt32($g[5]),
1338 $f[6]->subInt32($g[6]),
1339 $f[7]->subInt32($g[7]),
1340 $f[8]->subInt32($g[8]),
1341 $f[9]->subInt32($g[9])
1342 )
1343 );
1344 }
1345
1346 /**
1347 * Add two group elements.
1348 *
1349 * r = p + q
1350 *
1351 * @internal You should not use this directly from another application
1352 *
1353 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1354 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1355 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1356 * @throws SodiumException
1357 * @throws TypeError
1358 */
1359 public static function ge_add(
1360 ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1361 ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1362 ) {
1363 $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
1364 $r->X = self::fe_add($p->Y, $p->X);
1365 $r->Y = self::fe_sub($p->Y, $p->X);
1366 $r->Z = self::fe_mul($r->X, $q->YplusX);
1367 $r->Y = self::fe_mul($r->Y, $q->YminusX);
1368 $r->T = self::fe_mul($q->T2d, $p->T);
1369 $r->X = self::fe_mul($p->Z, $q->Z);
1370 $t0 = self::fe_add($r->X, $r->X);
1371 $r->X = self::fe_sub($r->Z, $r->Y);
1372 $r->Y = self::fe_add($r->Z, $r->Y);
1373 $r->Z = self::fe_add($t0, $r->T);
1374 $r->T = self::fe_sub($t0, $r->T);
1375 return $r;
1376 }
1377
1378 /**
1379 * @internal You should not use this directly from another application
1380 *
1381 * @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
1382 * @param string $a
1383 * @return array<int, mixed>
1384 * @throws SodiumException
1385 * @throws TypeError
1386 * @psalm-suppress MixedArrayOffset
1387 */
1388 public static function slide($a)
1389 {
1390 if (self::strlen($a) < 256) {
1391 if (self::strlen($a) < 16) {
1392 $a = str_pad($a, 256, '0', STR_PAD_RIGHT);
1393 }
1394 }
1395 /** @var array<int, int> $r */
1396 $r = array();
1397 for ($i = 0; $i < 256; ++$i) {
1398 $r[$i] = (int) (1 &
1399 (
1400 self::chrToInt($a[$i >> 3])
1401 >>
1402 ($i & 7)
1403 )
1404 );
1405 }
1406
1407 for ($i = 0;$i < 256;++$i) {
1408 if ($r[$i]) {
1409 for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
1410 if ($r[$i + $b]) {
1411 if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
1412 $r[$i] += $r[$i + $b] << $b;
1413 $r[$i + $b] = 0;
1414 } elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) {
1415 $r[$i] -= $r[$i + $b] << $b;
1416 for ($k = $i + $b; $k < 256; ++$k) {
1417 if (!$r[$k]) {
1418 $r[$k] = 1;
1419 break;
1420 }
1421 $r[$k] = 0;
1422 }
1423 } else {
1424 break;
1425 }
1426 }
1427 }
1428 }
1429 }
1430 return $r;
1431 }
1432
1433 /**
1434 * @internal You should not use this directly from another application
1435 *
1436 * @param string $s
1437 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
1438 * @throws SodiumException
1439 * @throws TypeError
1440 */
1441 public static function ge_frombytes_negate_vartime($s)
1442 {
1443 static $d = null;
1444 if (!$d) {
1445 $d = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1446 array(
1447 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[0]),
1448 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[1]),
1449 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[2]),
1450 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[3]),
1451 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[4]),
1452 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[5]),
1453 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[6]),
1454 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[7]),
1455 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[8]),
1456 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[9])
1457 )
1458 );
1459 }
1460 /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
1461
1462 # fe_frombytes(h->Y,s);
1463 # fe_1(h->Z);
1464 $h = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
1465 self::fe_0(),
1466 self::fe_frombytes($s),
1467 self::fe_1()
1468 );
1469
1470 # fe_sq(u,h->Y);
1471 # fe_mul(v,u,d);
1472 # fe_sub(u,u,h->Z); /* u = y^2-1 */
1473 # fe_add(v,v,h->Z); /* v = dy^2+1 */
1474 $u = self::fe_sq($h->Y);
1475 /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
1476 $v = self::fe_mul($u, $d);
1477 $u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */
1478 $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */
1479
1480 # fe_sq(v3,v);
1481 # fe_mul(v3,v3,v); /* v3 = v^3 */
1482 # fe_sq(h->X,v3);
1483 # fe_mul(h->X,h->X,v);
1484 # fe_mul(h->X,h->X,u); /* x = uv^7 */
1485 $v3 = self::fe_sq($v);
1486 $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
1487 $h->X = self::fe_sq($v3);
1488 $h->X = self::fe_mul($h->X, $v);
1489 $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */
1490
1491 # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
1492 # fe_mul(h->X,h->X,v3);
1493 # fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
1494 $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
1495 $h->X = self::fe_mul($h->X, $v3);
1496 $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */
1497
1498 # fe_sq(vxx,h->X);
1499 # fe_mul(vxx,vxx,v);
1500 # fe_sub(check,vxx,u); /* vx^2-u */
1501 $vxx = self::fe_sq($h->X);
1502 $vxx = self::fe_mul($vxx, $v);
1503 $check = self::fe_sub($vxx, $u); /* vx^2 - u */
1504
1505 # if (fe_isnonzero(check)) {
1506 # fe_add(check,vxx,u); /* vx^2+u */
1507 # if (fe_isnonzero(check)) {
1508 # return -1;
1509 # }
1510 # fe_mul(h->X,h->X,sqrtm1);
1511 # }
1512 if (self::fe_isnonzero($check)) {
1513 $check = self::fe_add($vxx, $u); /* vx^2 + u */
1514 if (self::fe_isnonzero($check)) {
1515 throw new RangeException('Internal check failed.');
1516 }
1517 $h->X = self::fe_mul(
1518 $h->X,
1519 ParagonIE_Sodium_Core32_Curve25519_Fe::fromIntArray(self::$sqrtm1)
1520 );
1521 }
1522
1523 # if (fe_isnegative(h->X) == (s[31] >> 7)) {
1524 # fe_neg(h->X,h->X);
1525 # }
1526 $i = self::chrToInt($s[31]);
1527 if (self::fe_isnegative($h->X) === ($i >> 7)) {
1528 $h->X = self::fe_neg($h->X);
1529 }
1530
1531 # fe_mul(h->T,h->X,h->Y);
1532 $h->T = self::fe_mul($h->X, $h->Y);
1533 return $h;
1534 }
1535
1536 /**
1537 * @internal You should not use this directly from another application
1538 *
1539 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
1540 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1541 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1542 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1543 * @throws SodiumException
1544 * @throws TypeError
1545 */
1546 public static function ge_madd(
1547 ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
1548 ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1549 ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1550 ) {
1551 $r = clone $R;
1552 $r->X = self::fe_add($p->Y, $p->X);
1553 $r->Y = self::fe_sub($p->Y, $p->X);
1554 $r->Z = self::fe_mul($r->X, $q->yplusx);
1555 $r->Y = self::fe_mul($r->Y, $q->yminusx);
1556 $r->T = self::fe_mul($q->xy2d, $p->T);
1557 $t0 = self::fe_add(clone $p->Z, clone $p->Z);
1558 $r->X = self::fe_sub($r->Z, $r->Y);
1559 $r->Y = self::fe_add($r->Z, $r->Y);
1560 $r->Z = self::fe_add($t0, $r->T);
1561 $r->T = self::fe_sub($t0, $r->T);
1562
1563 return $r;
1564 }
1565
1566 /**
1567 * @internal You should not use this directly from another application
1568 *
1569 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
1570 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1571 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1572 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1573 * @throws SodiumException
1574 * @throws TypeError
1575 */
1576 public static function ge_msub(
1577 ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
1578 ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1579 ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1580 ) {
1581 $r = clone $R;
1582
1583 $r->X = self::fe_add($p->Y, $p->X);
1584 $r->Y = self::fe_sub($p->Y, $p->X);
1585 $r->Z = self::fe_mul($r->X, $q->yminusx);
1586 $r->Y = self::fe_mul($r->Y, $q->yplusx);
1587 $r->T = self::fe_mul($q->xy2d, $p->T);
1588 $t0 = self::fe_add($p->Z, $p->Z);
1589 $r->X = self::fe_sub($r->Z, $r->Y);
1590 $r->Y = self::fe_add($r->Z, $r->Y);
1591 $r->Z = self::fe_sub($t0, $r->T);
1592 $r->T = self::fe_add($t0, $r->T);
1593
1594 return $r;
1595 }
1596
1597 /**
1598 * @internal You should not use this directly from another application
1599 *
1600 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
1601 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
1602 * @throws SodiumException
1603 * @throws TypeError
1604 */
1605 public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
1606 {
1607 $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P2();
1608 $r->X = self::fe_mul($p->X, $p->T);
1609 $r->Y = self::fe_mul($p->Y, $p->Z);
1610 $r->Z = self::fe_mul($p->Z, $p->T);
1611 return $r;
1612 }
1613
1614 /**
1615 * @internal You should not use this directly from another application
1616 *
1617 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
1618 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
1619 * @throws SodiumException
1620 * @throws TypeError
1621 */
1622 public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
1623 {
1624 $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3();
1625 $r->X = self::fe_mul($p->X, $p->T);
1626 $r->Y = self::fe_mul($p->Y, $p->Z);
1627 $r->Z = self::fe_mul($p->Z, $p->T);
1628 $r->T = self::fe_mul($p->X, $p->Y);
1629 return $r;
1630 }
1631
1632 /**
1633 * @internal You should not use this directly from another application
1634 *
1635 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
1636 * @throws SodiumException
1637 * @throws TypeError
1638 */
1639 public static function ge_p2_0()
1640 {
1641 return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
1642 self::fe_0(),
1643 self::fe_1(),
1644 self::fe_1()
1645 );
1646 }
1647
1648 /**
1649 * @internal You should not use this directly from another application
1650 *
1651 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p
1652 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1653 * @throws SodiumException
1654 * @throws TypeError
1655 */
1656 public static function ge_p2_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p)
1657 {
1658 $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
1659
1660 $r->X = self::fe_sq($p->X);
1661 $r->Z = self::fe_sq($p->Y);
1662 $r->T = self::fe_sq2($p->Z);
1663 $r->Y = self::fe_add($p->X, $p->Y);
1664 $t0 = self::fe_sq($r->Y);
1665 $r->Y = self::fe_add($r->Z, $r->X);
1666 $r->Z = self::fe_sub($r->Z, $r->X);
1667 $r->X = self::fe_sub($t0, $r->Y);
1668 $r->T = self::fe_sub($r->T, $r->Z);
1669
1670 return $r;
1671 }
1672
1673 /**
1674 * @internal You should not use this directly from another application
1675 *
1676 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
1677 * @throws SodiumException
1678 * @throws TypeError
1679 */
1680 public static function ge_p3_0()
1681 {
1682 return new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
1683 self::fe_0(),
1684 self::fe_1(),
1685 self::fe_1(),
1686 self::fe_0()
1687 );
1688 }
1689
1690 /**
1691 * @internal You should not use this directly from another application
1692 *
1693 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1694 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
1695 * @throws SodiumException
1696 * @throws TypeError
1697 */
1698 public static function ge_p3_to_cached(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
1699 {
1700 static $d2 = null;
1701 if ($d2 === null) {
1702 $d2 = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1703 array(
1704 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[0]),
1705 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[1]),
1706 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[2]),
1707 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[3]),
1708 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[4]),
1709 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[5]),
1710 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[6]),
1711 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[7]),
1712 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[8]),
1713 ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[9])
1714 )
1715 );
1716 }
1717 /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d2 */
1718 $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached();
1719 $r->YplusX = self::fe_add($p->Y, $p->X);
1720 $r->YminusX = self::fe_sub($p->Y, $p->X);
1721 $r->Z = self::fe_copy($p->Z);
1722 $r->T2d = self::fe_mul($p->T, $d2);
1723 return $r;
1724 }
1725
1726 /**
1727 * @internal You should not use this directly from another application
1728 *
1729 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1730 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
1731 */
1732 public static function ge_p3_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
1733 {
1734 return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
1735 $p->X,
1736 $p->Y,
1737 $p->Z
1738 );
1739 }
1740
1741 /**
1742 * @internal You should not use this directly from another application
1743 *
1744 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h
1745 * @return string
1746 * @throws SodiumException
1747 * @throws TypeError
1748 */
1749 public static function ge_p3_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h)
1750 {
1751 $recip = self::fe_invert($h->Z);
1752 $x = self::fe_mul($h->X, $recip);
1753 $y = self::fe_mul($h->Y, $recip);
1754 $s = self::fe_tobytes($y);
1755 $s[31] = self::intToChr(
1756 self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
1757 );
1758 return $s;
1759 }
1760
1761 /**
1762 * @internal You should not use this directly from another application
1763 *
1764 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1765 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1766 * @throws SodiumException
1767 * @throws TypeError
1768 */
1769 public static function ge_p3_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
1770 {
1771 $q = self::ge_p3_to_p2($p);
1772 return self::ge_p2_dbl($q);
1773 }
1774
1775 /**
1776 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
1777 * @throws SodiumException
1778 * @throws TypeError
1779 */
1780 public static function ge_precomp_0()
1781 {
1782 return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1783 self::fe_1(),
1784 self::fe_1(),
1785 self::fe_0()
1786 );
1787 }
1788
1789 /**
1790 * @internal You should not use this directly from another application
1791 *
1792 * @param int $b
1793 * @param int $c
1794 * @return int
1795 * @psalm-suppress MixedReturnStatement
1796 */
1797 public static function equal($b, $c)
1798 {
1799 $b0 = $b & 0xffff;
1800 $b1 = ($b >> 16) & 0xffff;
1801 $c0 = $c & 0xffff;
1802 $c1 = ($c >> 16) & 0xffff;
1803
1804 $d0 = (($b0 ^ $c0) - 1) >> 31;
1805 $d1 = (($b1 ^ $c1) - 1) >> 31;
1806 return ($d0 & $d1) & 1;
1807 }
1808
1809 /**
1810 * @internal You should not use this directly from another application
1811 *
1812 * @param string|int $char
1813 * @return int (1 = yes, 0 = no)
1814 * @throws SodiumException
1815 * @throws TypeError
1816 */
1817 public static function negative($char)
1818 {
1819 if (is_int($char)) {
1820 return $char < 0 ? 1 : 0;
1821 }
1822 /** @var string $char */
1823 $x = self::chrToInt(self::substr($char, 0, 1));
1824 return (int) ($x >> 31);
1825 }
1826
1827 /**
1828 * Conditional move
1829 *
1830 * @internal You should not use this directly from another application
1831 *
1832 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t
1833 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u
1834 * @param int $b
1835 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
1836 * @throws SodiumException
1837 * @throws TypeError
1838 */
1839 public static function cmov(
1840 ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t,
1841 ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u,
1842 $b
1843 ) {
1844 if (!is_int($b)) {
1845 throw new InvalidArgumentException('Expected an integer.');
1846 }
1847 return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1848 self::fe_cmov($t->yplusx, $u->yplusx, $b),
1849 self::fe_cmov($t->yminusx, $u->yminusx, $b),
1850 self::fe_cmov($t->xy2d, $u->xy2d, $b)
1851 );
1852 }
1853
1854 /**
1855 * @internal You should not use this directly from another application
1856 *
1857 * @param int $pos
1858 * @param int $b
1859 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
1860 * @throws SodiumException
1861 * @throws TypeError
1862 * @psalm-suppress MixedArrayAccess
1863 * @psalm-suppress MixedArrayOffset
1864 * @psalm-suppress MixedArgument
1865 */
1866 public static function ge_select($pos = 0, $b = 0)
1867 {
1868 static $base = null;
1869 if ($base === null) {
1870 $base = array();
1871 foreach (self::$base as $i => $bas) {
1872 for ($j = 0; $j < 8; ++$j) {
1873 $base[$i][$j] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1874 ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1875 array(
1876 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][0]),
1877 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][1]),
1878 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][2]),
1879 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][3]),
1880 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][4]),
1881 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][5]),
1882 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][6]),
1883 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][7]),
1884 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][8]),
1885 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][9])
1886 )
1887 ),
1888 ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1889 array(
1890 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][0]),
1891 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][1]),
1892 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][2]),
1893 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][3]),
1894 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][4]),
1895 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][5]),
1896 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][6]),
1897 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][7]),
1898 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][8]),
1899 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][9])
1900 )
1901 ),
1902 ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1903 array(
1904 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][0]),
1905 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][1]),
1906 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][2]),
1907 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][3]),
1908 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][4]),
1909 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][5]),
1910 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][6]),
1911 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][7]),
1912 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][8]),
1913 ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][9])
1914 )
1915 )
1916 );
1917 }
1918 }
1919 }
1920 if (!is_int($pos)) {
1921 throw new InvalidArgumentException('Position must be an integer');
1922 }
1923 if ($pos < 0 || $pos > 31) {
1924 throw new RangeException('Position is out of range [0, 31]');
1925 }
1926
1927 $bnegative = self::negative($b);
1928 $babs = $b - (((-$bnegative) & $b) << 1);
1929
1930 $t = self::ge_precomp_0();
1931 for ($i = 0; $i < 8; ++$i) {
1932 $t = self::cmov(
1933 $t,
1934 $base[$pos][$i],
1935 -self::equal($babs, $i + 1)
1936 );
1937 }
1938 $minusT = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1939 self::fe_copy($t->yminusx),
1940 self::fe_copy($t->yplusx),
1941 self::fe_neg($t->xy2d)
1942 );
1943 return self::cmov($t, $minusT, -$bnegative);
1944 }
1945
1946 /**
1947 * Subtract two group elements.
1948 *
1949 * r = p - q
1950 *
1951 * @internal You should not use this directly from another application
1952 *
1953 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1954 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1955 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1956 * @throws SodiumException
1957 * @throws TypeError
1958 */
1959 public static function ge_sub(
1960 ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1961 ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1962 ) {
1963 $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
1964
1965 $r->X = self::fe_add($p->Y, $p->X);
1966 $r->Y = self::fe_sub($p->Y, $p->X);
1967 $r->Z = self::fe_mul($r->X, $q->YminusX);
1968 $r->Y = self::fe_mul($r->Y, $q->YplusX);
1969 $r->T = self::fe_mul($q->T2d, $p->T);
1970 $r->X = self::fe_mul($p->Z, $q->Z);
1971 $t0 = self::fe_add($r->X, $r->X);
1972 $r->X = self::fe_sub($r->Z, $r->Y);
1973 $r->Y = self::fe_add($r->Z, $r->Y);
1974 $r->Z = self::fe_sub($t0, $r->T);
1975 $r->T = self::fe_add($t0, $r->T);
1976
1977 return $r;
1978 }
1979
1980 /**
1981 * Convert a group element to a byte string.
1982 *
1983 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h
1984 * @return string
1985 * @throws SodiumException
1986 * @throws TypeError
1987 */
1988 public static function ge_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h)
1989 {
1990 $recip = self::fe_invert($h->Z);
1991 $x = self::fe_mul($h->X, $recip);
1992 $y = self::fe_mul($h->Y, $recip);
1993 $s = self::fe_tobytes($y);
1994 $s[31] = self::intToChr(
1995 self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
1996 );
1997 return $s;
1998 }
1999
2000 /**
2001 * @internal You should not use this directly from another application
2002 *
2003 * @param string $a
2004 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
2005 * @param string $b
2006 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
2007 * @throws SodiumException
2008 * @throws TypeError
2009 * @psalm-suppress MixedArrayAccess
2010 */
2011 public static function ge_double_scalarmult_vartime(
2012 $a,
2013 ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A,
2014 $b
2015 ) {
2016 /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */
2017 $Ai = array();
2018
2019 static $Bi = array();
2020 /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */
2021 if (!$Bi) {
2022 for ($i = 0; $i < 8; ++$i) {
2023 $Bi[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
2024 ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
2025 array(
2026 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][0]),
2027 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][1]),
2028 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][2]),
2029 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][3]),
2030 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][4]),
2031 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][5]),
2032 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][6]),
2033 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][7]),
2034 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][8]),
2035 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][9])
2036 )
2037 ),
2038 ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
2039 array(
2040 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][0]),
2041 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][1]),
2042 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][2]),
2043 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][3]),
2044 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][4]),
2045 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][5]),
2046 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][6]),
2047 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][7]),
2048 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][8]),
2049 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][9])
2050 )
2051 ),
2052 ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
2053 array(
2054 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][0]),
2055 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][1]),
2056 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][2]),
2057 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][3]),
2058 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][4]),
2059 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][5]),
2060 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][6]),
2061 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][7]),
2062 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][8]),
2063 ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][9])
2064 )
2065 )
2066 );
2067 }
2068 }
2069
2070 for ($i = 0; $i < 8; ++$i) {
2071 $Ai[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached(
2072 self::fe_0(),
2073 self::fe_0(),
2074 self::fe_0(),
2075 self::fe_0()
2076 );
2077 }
2078 /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */
2079
2080 # slide(aslide,a);
2081 # slide(bslide,b);
2082 /** @var array<int, int> $aslide */
2083 $aslide = self::slide($a);
2084 /** @var array<int, int> $bslide */
2085 $bslide = self::slide($b);
2086
2087 # ge_p3_to_cached(&Ai[0],A);
2088 # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
2089 $Ai[0] = self::ge_p3_to_cached($A);
2090 $t = self::ge_p3_dbl($A);
2091 $A2 = self::ge_p1p1_to_p3($t);
2092
2093 # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
2094 # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
2095 # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
2096 # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
2097 # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
2098 # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
2099 # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
2100 for ($i = 0; $i < 7; ++$i) {
2101 $t = self::ge_add($A2, $Ai[$i]);
2102 $u = self::ge_p1p1_to_p3($t);
2103 $Ai[$i + 1] = self::ge_p3_to_cached($u);
2104 }
2105
2106 # ge_p2_0(r);
2107 $r = self::ge_p2_0();
2108
2109 # for (i = 255;i >= 0;--i) {
2110 # if (aslide[i] || bslide[i]) break;
2111 # }
2112 $i = 255;
2113 for (; $i >= 0; --$i) {
2114 if ($aslide[$i] || $bslide[$i]) {
2115 break;
2116 }
2117 }
2118
2119 # for (;i >= 0;--i) {
2120 for (; $i >= 0; --$i) {
2121 # ge_p2_dbl(&t,r);
2122 $t = self::ge_p2_dbl($r);
2123
2124 # if (aslide[i] > 0) {
2125 if ($aslide[$i] > 0) {
2126 # ge_p1p1_to_p3(&u,&t);
2127 # ge_add(&t,&u,&Ai[aslide[i]/2]);
2128 $u = self::ge_p1p1_to_p3($t);
2129 $t = self::ge_add(
2130 $u,
2131 $Ai[(int) floor($aslide[$i] / 2)]
2132 );
2133 # } else if (aslide[i] < 0) {
2134 } elseif ($aslide[$i] < 0) {
2135 # ge_p1p1_to_p3(&u,&t);
2136 # ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
2137 $u = self::ge_p1p1_to_p3($t);
2138 $t = self::ge_sub(
2139 $u,
2140 $Ai[(int) floor(-$aslide[$i] / 2)]
2141 );
2142 }
2143 /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */
2144
2145 # if (bslide[i] > 0) {
2146 if ($bslide[$i] > 0) {
2147 # ge_p1p1_to_p3(&u,&t);
2148 # ge_madd(&t,&u,&Bi[bslide[i]/2]);
2149 $u = self::ge_p1p1_to_p3($t);
2150 /** @var int $index */
2151 $index = (int) floor($bslide[$i] / 2);
2152 /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */
2153 $thisB = $Bi[$index];
2154 $t = self::ge_madd($t, $u, $thisB);
2155 # } else if (bslide[i] < 0) {
2156 } elseif ($bslide[$i] < 0) {
2157 # ge_p1p1_to_p3(&u,&t);
2158 # ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
2159 $u = self::ge_p1p1_to_p3($t);
2160
2161 /** @var int $index */
2162 $index = (int) floor(-$bslide[$i] / 2);
2163
2164 /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */
2165 $thisB = $Bi[$index];
2166 $t = self::ge_msub($t, $u, $thisB);
2167 }
2168 # ge_p1p1_to_p2(r,&t);
2169 $r = self::ge_p1p1_to_p2($t);
2170 }
2171 return $r;
2172 }
2173
2174 /**
2175 * @internal You should not use this directly from another application
2176 *
2177 * @param string $a
2178 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
2179 * @psalm-suppress MixedAssignment
2180 * @psalm-suppress MixedOperand
2181 * @throws SodiumException
2182 * @throws TypeError
2183 */
2184 public static function ge_scalarmult_base($a)
2185 {
2186 /** @var array<int, int> $e */
2187 $e = array();
2188 $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
2189
2190 for ($i = 0; $i < 32; ++$i) {
2191 /** @var int $dbl */
2192 $dbl = (int) $i << 1;
2193 $e[$dbl] = (int) self::chrToInt($a[$i]) & 15;
2194 $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15;
2195 }
2196
2197 /** @var int $carry */
2198 $carry = 0;
2199 for ($i = 0; $i < 63; ++$i) {
2200 $e[$i] += $carry;
2201 $carry = $e[$i] + 8;
2202 $carry >>= 4;
2203 $e[$i] -= $carry << 4;
2204 }
2205
2206 /** @var array<int, int> $e */
2207 $e[63] += (int) $carry;
2208
2209 $h = self::ge_p3_0();
2210
2211 for ($i = 1; $i < 64; $i += 2) {
2212 $t = self::ge_select((int) floor($i / 2), (int) $e[$i]);
2213 $r = self::ge_madd($r, $h, $t);
2214 $h = self::ge_p1p1_to_p3($r);
2215 }
2216
2217 $r = self::ge_p3_dbl($h);
2218
2219 $s = self::ge_p1p1_to_p2($r);
2220 $r = self::ge_p2_dbl($s);
2221 $s = self::ge_p1p1_to_p2($r);
2222 $r = self::ge_p2_dbl($s);
2223 $s = self::ge_p1p1_to_p2($r);
2224 $r = self::ge_p2_dbl($s);
2225
2226 $h = self::ge_p1p1_to_p3($r);
2227
2228 for ($i = 0; $i < 64; $i += 2) {
2229 $t = self::ge_select($i >> 1, (int) $e[$i]);
2230 $r = self::ge_madd($r, $h, $t);
2231 $h = self::ge_p1p1_to_p3($r);
2232 }
2233 return $h;
2234 }
2235
2236 /**
2237 * Calculates (ab + c) mod l
2238 * where l = 2^252 + 27742317777372353535851937790883648493
2239 *
2240 * @internal You should not use this directly from another application
2241 *
2242 * @param string $a
2243 * @param string $b
2244 * @param string $c
2245 * @return string
2246 * @throws SodiumException
2247 * @throws TypeError
2248 */
2249 public static function sc_muladd($a, $b, $c)
2250 {
2251 $a0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 0, 3)));
2252 $a1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5));
2253 $a2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2));
2254 $a3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7));
2255 $a4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4));
2256 $a5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1));
2257 $a6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6));
2258 $a7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3));
2259 $a8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 21, 3)));
2260 $a9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5));
2261 $a10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2));
2262 $a11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($a, 28, 4)) >> 7));
2263 $b0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 0, 3)));
2264 $b1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5));
2265 $b2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2));
2266 $b3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7));
2267 $b4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4));
2268 $b5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1));
2269 $b6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6));
2270 $b7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3));
2271 $b8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 21, 3)));
2272 $b9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5));
2273 $b10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2));
2274 $b11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($b, 28, 4)) >> 7));
2275 $c0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 0, 3)));
2276 $c1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5));
2277 $c2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2));
2278 $c3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7));
2279 $c4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4));
2280 $c5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1));
2281 $c6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6));
2282 $c7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3));
2283 $c8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 21, 3)));
2284 $c9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5));
2285 $c10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2));
2286 $c11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($c, 28, 4)) >> 7));
2287
2288 /* Can't really avoid the pyramid here: */
2289 /**
2290 * @var ParagonIE_Sodium_Core32_Int64 $s0
2291 * @var ParagonIE_Sodium_Core32_Int64 $s1
2292 * @var ParagonIE_Sodium_Core32_Int64 $s2
2293 * @var ParagonIE_Sodium_Core32_Int64 $s3
2294 * @var ParagonIE_Sodium_Core32_Int64 $s4
2295 * @var ParagonIE_Sodium_Core32_Int64 $s5
2296 * @var ParagonIE_Sodium_Core32_Int64 $s6
2297 * @var ParagonIE_Sodium_Core32_Int64 $s7
2298 * @var ParagonIE_Sodium_Core32_Int64 $s8
2299 * @var ParagonIE_Sodium_Core32_Int64 $s9
2300 * @var ParagonIE_Sodium_Core32_Int64 $s10
2301 * @var ParagonIE_Sodium_Core32_Int64 $s11
2302 * @var ParagonIE_Sodium_Core32_Int64 $s12
2303 * @var ParagonIE_Sodium_Core32_Int64 $s13
2304 * @var ParagonIE_Sodium_Core32_Int64 $s14
2305 * @var ParagonIE_Sodium_Core32_Int64 $s15
2306 * @var ParagonIE_Sodium_Core32_Int64 $s16
2307 * @var ParagonIE_Sodium_Core32_Int64 $s17
2308 * @var ParagonIE_Sodium_Core32_Int64 $s18
2309 * @var ParagonIE_Sodium_Core32_Int64 $s19
2310 * @var ParagonIE_Sodium_Core32_Int64 $s20
2311 * @var ParagonIE_Sodium_Core32_Int64 $s21
2312 * @var ParagonIE_Sodium_Core32_Int64 $s22
2313 * @var ParagonIE_Sodium_Core32_Int64 $s23
2314 */
2315
2316 $s0 = $c0->addInt64($a0->mulInt64($b0, 24));
2317 $s1 = $c1->addInt64($a0->mulInt64($b1, 24))->addInt64($a1->mulInt64($b0, 24));
2318 $s2 = $c2->addInt64($a0->mulInt64($b2, 24))->addInt64($a1->mulInt64($b1, 24))->addInt64($a2->mulInt64($b0, 24));
2319 $s3 = $c3->addInt64($a0->mulInt64($b3, 24))->addInt64($a1->mulInt64($b2, 24))->addInt64($a2->mulInt64($b1, 24))
2320 ->addInt64($a3->mulInt64($b0, 24));
2321 $s4 = $c4->addInt64($a0->mulInt64($b4, 24))->addInt64($a1->mulInt64($b3, 24))->addInt64($a2->mulInt64($b2, 24))
2322 ->addInt64($a3->mulInt64($b1, 24))->addInt64($a4->mulInt64($b0, 24));
2323 $s5 = $c5->addInt64($a0->mulInt64($b5, 24))->addInt64($a1->mulInt64($b4, 24))->addInt64($a2->mulInt64($b3, 24))
2324 ->addInt64($a3->mulInt64($b2, 24))->addInt64($a4->mulInt64($b1, 24))->addInt64($a5->mulInt64($b0, 24));
2325 $s6 = $c6->addInt64($a0->mulInt64($b6, 24))->addInt64($a1->mulInt64($b5, 24))->addInt64($a2->mulInt64($b4, 24))
2326 ->addInt64($a3->mulInt64($b3, 24))->addInt64($a4->mulInt64($b2, 24))->addInt64($a5->mulInt64($b1, 24))
2327 ->addInt64($a6->mulInt64($b0, 24));
2328 $s7 = $c7->addInt64($a0->mulInt64($b7, 24))->addInt64($a1->mulInt64($b6, 24))->addInt64($a2->mulInt64($b5, 24))
2329 ->addInt64($a3->mulInt64($b4, 24))->addInt64($a4->mulInt64($b3, 24))->addInt64($a5->mulInt64($b2, 24))
2330 ->addInt64($a6->mulInt64($b1, 24))->addInt64($a7->mulInt64($b0, 24));
2331 $s8 = $c8->addInt64($a0->mulInt64($b8, 24))->addInt64($a1->mulInt64($b7, 24))->addInt64($a2->mulInt64($b6, 24))
2332 ->addInt64($a3->mulInt64($b5, 24))->addInt64($a4->mulInt64($b4, 24))->addInt64($a5->mulInt64($b3, 24))
2333 ->addInt64($a6->mulInt64($b2, 24))->addInt64($a7->mulInt64($b1, 24))->addInt64($a8->mulInt64($b0, 24));
2334 $s9 = $c9->addInt64($a0->mulInt64($b9, 24))->addInt64($a1->mulInt64($b8, 24))->addInt64($a2->mulInt64($b7, 24))
2335 ->addInt64($a3->mulInt64($b6, 24))->addInt64($a4->mulInt64($b5, 24))->addInt64($a5->mulInt64($b4, 24))
2336 ->addInt64($a6->mulInt64($b3, 24))->addInt64($a7->mulInt64($b2, 24))->addInt64($a8->mulInt64($b1, 24))
2337 ->addInt64($a9->mulInt64($b0, 24));
2338 $s10 = $c10->addInt64($a0->mulInt64($b10, 24))->addInt64($a1->mulInt64($b9, 24))->addInt64($a2->mulInt64($b8, 24))
2339 ->addInt64($a3->mulInt64($b7, 24))->addInt64($a4->mulInt64($b6, 24))->addInt64($a5->mulInt64($b5, 24))
2340 ->addInt64($a6->mulInt64($b4, 24))->addInt64($a7->mulInt64($b3, 24))->addInt64($a8->mulInt64($b2, 24))
2341 ->addInt64($a9->mulInt64($b1, 24))->addInt64($a10->mulInt64($b0, 24));
2342 $s11 = $c11->addInt64($a0->mulInt64($b11, 24))->addInt64($a1->mulInt64($b10, 24))->addInt64($a2->mulInt64($b9, 24))
2343 ->addInt64($a3->mulInt64($b8, 24))->addInt64($a4->mulInt64($b7, 24))->addInt64($a5->mulInt64($b6, 24))
2344 ->addInt64($a6->mulInt64($b5, 24))->addInt64($a7->mulInt64($b4, 24))->addInt64($a8->mulInt64($b3, 24))
2345 ->addInt64($a9->mulInt64($b2, 24))->addInt64($a10->mulInt64($b1, 24))->addInt64($a11->mulInt64($b0, 24));
2346 $s12 = $a1->mulInt64($b11, 24)->addInt64($a2->mulInt64($b10, 24))->addInt64($a3->mulInt64($b9, 24))
2347 ->addInt64($a4->mulInt64($b8, 24))->addInt64($a5->mulInt64($b7, 24))->addInt64($a6->mulInt64($b6, 24))
2348 ->addInt64($a7->mulInt64($b5, 24))->addInt64($a8->mulInt64($b4, 24))->addInt64($a9->mulInt64($b3, 24))
2349 ->addInt64($a10->mulInt64($b2, 24))->addInt64($a11->mulInt64($b1, 24));
2350 $s13 = $a2->mulInt64($b11, 24)->addInt64($a3->mulInt64($b10, 24))->addInt64($a4->mulInt64($b9, 24))
2351 ->addInt64($a5->mulInt64($b8, 24))->addInt64($a6->mulInt64($b7, 24))->addInt64($a7->mulInt64($b6, 24))
2352 ->addInt64($a8->mulInt64($b5, 24))->addInt64($a9->mulInt64($b4, 24))->addInt64($a10->mulInt64($b3, 24))
2353 ->addInt64($a11->mulInt64($b2, 24));
2354 $s14 = $a3->mulInt64($b11, 24)->addInt64($a4->mulInt64($b10, 24))->addInt64($a5->mulInt64($b9, 24))
2355 ->addInt64($a6->mulInt64($b8, 24))->addInt64($a7->mulInt64($b7, 24))->addInt64($a8->mulInt64($b6, 24))
2356 ->addInt64($a9->mulInt64($b5, 24))->addInt64($a10->mulInt64($b4, 24))->addInt64($a11->mulInt64($b3, 24));
2357 $s15 = $a4->mulInt64($b11, 24)->addInt64($a5->mulInt64($b10, 24))->addInt64($a6->mulInt64($b9, 24))
2358 ->addInt64($a7->mulInt64($b8, 24))->addInt64($a8->mulInt64($b7, 24))->addInt64($a9->mulInt64($b6, 24))
2359 ->addInt64($a10->mulInt64($b5, 24))->addInt64($a11->mulInt64($b4, 24));
2360 $s16 = $a5->mulInt64($b11, 24)->addInt64($a6->mulInt64($b10, 24))->addInt64($a7->mulInt64($b9, 24))
2361 ->addInt64($a8->mulInt64($b8, 24))->addInt64($a9->mulInt64($b7, 24))->addInt64($a10->mulInt64($b6, 24))
2362 ->addInt64($a11->mulInt64($b5, 24));
2363 $s17 = $a6->mulInt64($b11, 24)->addInt64($a7->mulInt64($b10, 24))->addInt64($a8->mulInt64($b9, 24))
2364 ->addInt64($a9->mulInt64($b8, 24))->addInt64($a10->mulInt64($b7, 24))->addInt64($a11->mulInt64($b6, 24));
2365 $s18 = $a7->mulInt64($b11, 24)->addInt64($a8->mulInt64($b10, 24))->addInt64($a9->mulInt64($b9, 24))
2366 ->addInt64($a10->mulInt64($b8, 24))->addInt64($a11->mulInt64($b7, 24));
2367 $s19 = $a8->mulInt64($b11, 24)->addInt64($a9->mulInt64($b10, 24))->addInt64($a10->mulInt64($b9, 24))
2368 ->addInt64($a11->mulInt64($b8, 24));
2369 $s20 = $a9->mulInt64($b11, 24)->addInt64($a10->mulInt64($b10, 24))->addInt64($a11->mulInt64($b9, 24));
2370 $s21 = $a10->mulInt64($b11, 24)->addInt64($a11->mulInt64($b10, 24));
2371 $s22 = $a11->mulInt64($b11, 24);
2372 $s23 = new ParagonIE_Sodium_Core32_Int64();
2373
2374 $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
2375 $s1 = $s1->addInt64($carry0);
2376 $s0 = $s0->subInt64($carry0->shiftLeft(21));
2377 $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
2378 $s3 = $s3->addInt64($carry2);
2379 $s2 = $s2->subInt64($carry2->shiftLeft(21));
2380 $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
2381 $s5 = $s5->addInt64($carry4);
2382 $s4 = $s4->subInt64($carry4->shiftLeft(21));
2383 $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2384 $s7 = $s7->addInt64($carry6);
2385 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2386 $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2387 $s9 = $s9->addInt64($carry8);
2388 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2389 $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2390 $s11 = $s11->addInt64($carry10);
2391 $s10 = $s10->subInt64($carry10->shiftLeft(21));
2392 $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
2393 $s13 = $s13->addInt64($carry12);
2394 $s12 = $s12->subInt64($carry12->shiftLeft(21));
2395 $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
2396 $s15 = $s15->addInt64($carry14);
2397 $s14 = $s14->subInt64($carry14->shiftLeft(21));
2398 $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
2399 $s17 = $s17->addInt64($carry16);
2400 $s16 = $s16->subInt64($carry16->shiftLeft(21));
2401 $carry18 = $s18->addInt(1 << 20)->shiftRight(21);
2402 $s19 = $s19->addInt64($carry18);
2403 $s18 = $s18->subInt64($carry18->shiftLeft(21));
2404 $carry20 = $s20->addInt(1 << 20)->shiftRight(21);
2405 $s21 = $s21->addInt64($carry20);
2406 $s20 = $s20->subInt64($carry20->shiftLeft(21));
2407 $carry22 = $s22->addInt(1 << 20)->shiftRight(21);
2408 $s23 = $s23->addInt64($carry22);
2409 $s22 = $s22->subInt64($carry22->shiftLeft(21));
2410
2411 $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
2412 $s2 = $s2->addInt64($carry1);
2413 $s1 = $s1->subInt64($carry1->shiftLeft(21));
2414 $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
2415 $s4 = $s4->addInt64($carry3);
2416 $s3 = $s3->subInt64($carry3->shiftLeft(21));
2417 $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
2418 $s6 = $s6->addInt64($carry5);
2419 $s5 = $s5->subInt64($carry5->shiftLeft(21));
2420 $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2421 $s8 = $s8->addInt64($carry7);
2422 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2423 $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2424 $s10 = $s10->addInt64($carry9);
2425 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2426 $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2427 $s12 = $s12->addInt64($carry11);
2428 $s11 = $s11->subInt64($carry11->shiftLeft(21));
2429 $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
2430 $s14 = $s14->addInt64($carry13);
2431 $s13 = $s13->subInt64($carry13->shiftLeft(21));
2432 $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
2433 $s16 = $s16->addInt64($carry15);
2434 $s15 = $s15->subInt64($carry15->shiftLeft(21));
2435 $carry17 = $s17->addInt(1 << 20)->shiftRight(21);
2436 $s18 = $s18->addInt64($carry17);
2437 $s17 = $s17->subInt64($carry17->shiftLeft(21));
2438 $carry19 = $s19->addInt(1 << 20)->shiftRight(21);
2439 $s20 = $s20->addInt64($carry19);
2440 $s19 = $s19->subInt64($carry19->shiftLeft(21));
2441 $carry21 = $s21->addInt(1 << 20)->shiftRight(21);
2442 $s22 = $s22->addInt64($carry21);
2443 $s21 = $s21->subInt64($carry21->shiftLeft(21));
2444
2445 $s11 = $s11->addInt64($s23->mulInt(666643, 20));
2446 $s12 = $s12->addInt64($s23->mulInt(470296, 19));
2447 $s13 = $s13->addInt64($s23->mulInt(654183, 20));
2448 $s14 = $s14->subInt64($s23->mulInt(997805, 20));
2449 $s15 = $s15->addInt64($s23->mulInt(136657, 18));
2450 $s16 = $s16->subInt64($s23->mulInt(683901, 20));
2451
2452 $s10 = $s10->addInt64($s22->mulInt(666643, 20));
2453 $s11 = $s11->addInt64($s22->mulInt(470296, 19));
2454 $s12 = $s12->addInt64($s22->mulInt(654183, 20));
2455 $s13 = $s13->subInt64($s22->mulInt(997805, 20));
2456 $s14 = $s14->addInt64($s22->mulInt(136657, 18));
2457 $s15 = $s15->subInt64($s22->mulInt(683901, 20));
2458
2459 $s9 = $s9->addInt64($s21->mulInt(666643, 20));
2460 $s10 = $s10->addInt64($s21->mulInt(470296, 19));
2461 $s11 = $s11->addInt64($s21->mulInt(654183, 20));
2462 $s12 = $s12->subInt64($s21->mulInt(997805, 20));
2463 $s13 = $s13->addInt64($s21->mulInt(136657, 18));
2464 $s14 = $s14->subInt64($s21->mulInt(683901, 20));
2465
2466 $s8 = $s8->addInt64($s20->mulInt(666643, 20));
2467 $s9 = $s9->addInt64($s20->mulInt(470296, 19));
2468 $s10 = $s10->addInt64($s20->mulInt(654183, 20));
2469 $s11 = $s11->subInt64($s20->mulInt(997805, 20));
2470 $s12 = $s12->addInt64($s20->mulInt(136657, 18));
2471 $s13 = $s13->subInt64($s20->mulInt(683901, 20));
2472
2473 $s7 = $s7->addInt64($s19->mulInt(666643, 20));
2474 $s8 = $s8->addInt64($s19->mulInt(470296, 19));
2475 $s9 = $s9->addInt64($s19->mulInt(654183, 20));
2476 $s10 = $s10->subInt64($s19->mulInt(997805, 20));
2477 $s11 = $s11->addInt64($s19->mulInt(136657, 18));
2478 $s12 = $s12->subInt64($s19->mulInt(683901, 20));
2479
2480 $s6 = $s6->addInt64($s18->mulInt(666643, 20));
2481 $s7 = $s7->addInt64($s18->mulInt(470296, 19));
2482 $s8 = $s8->addInt64($s18->mulInt(654183, 20));
2483 $s9 = $s9->subInt64($s18->mulInt(997805, 20));
2484 $s10 = $s10->addInt64($s18->mulInt(136657, 18));
2485 $s11 = $s11->subInt64($s18->mulInt(683901, 20));
2486
2487 $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2488 $s7 = $s7->addInt64($carry6);
2489 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2490 $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2491 $s9 = $s9->addInt64($carry8);
2492 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2493 $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2494 $s11 = $s11->addInt64($carry10);
2495 $s10 = $s10->subInt64($carry10->shiftLeft(21));
2496 $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
2497 $s13 = $s13->addInt64($carry12);
2498 $s12 = $s12->subInt64($carry12->shiftLeft(21));
2499 $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
2500 $s15 = $s15->addInt64($carry14);
2501 $s14 = $s14->subInt64($carry14->shiftLeft(21));
2502 $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
2503 $s17 = $s17->addInt64($carry16);
2504 $s16 = $s16->subInt64($carry16->shiftLeft(21));
2505
2506 $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2507 $s8 = $s8->addInt64($carry7);
2508 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2509 $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2510 $s10 = $s10->addInt64($carry9);
2511 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2512 $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2513 $s12 = $s12->addInt64($carry11);
2514 $s11 = $s11->subInt64($carry11->shiftLeft(21));
2515 $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
2516 $s14 = $s14->addInt64($carry13);
2517 $s13 = $s13->subInt64($carry13->shiftLeft(21));
2518 $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
2519 $s16 = $s16->addInt64($carry15);
2520 $s15 = $s15->subInt64($carry15->shiftLeft(21));
2521
2522 $s5 = $s5->addInt64($s17->mulInt(666643, 20));
2523 $s6 = $s6->addInt64($s17->mulInt(470296, 19));
2524 $s7 = $s7->addInt64($s17->mulInt(654183, 20));
2525 $s8 = $s8->subInt64($s17->mulInt(997805, 20));
2526 $s9 = $s9->addInt64($s17->mulInt(136657, 18));
2527 $s10 = $s10->subInt64($s17->mulInt(683901, 20));
2528
2529 $s4 = $s4->addInt64($s16->mulInt(666643, 20));
2530 $s5 = $s5->addInt64($s16->mulInt(470296, 19));
2531 $s6 = $s6->addInt64($s16->mulInt(654183, 20));
2532 $s7 = $s7->subInt64($s16->mulInt(997805, 20));
2533 $s8 = $s8->addInt64($s16->mulInt(136657, 18));
2534 $s9 = $s9->subInt64($s16->mulInt(683901, 20));
2535
2536 $s3 = $s3->addInt64($s15->mulInt(666643, 20));
2537 $s4 = $s4->addInt64($s15->mulInt(470296, 19));
2538 $s5 = $s5->addInt64($s15->mulInt(654183, 20));
2539 $s6 = $s6->subInt64($s15->mulInt(997805, 20));
2540 $s7 = $s7->addInt64($s15->mulInt(136657, 18));
2541 $s8 = $s8->subInt64($s15->mulInt(683901, 20));
2542
2543 $s2 = $s2->addInt64($s14->mulInt(666643, 20));
2544 $s3 = $s3->addInt64($s14->mulInt(470296, 19));
2545 $s4 = $s4->addInt64($s14->mulInt(654183, 20));
2546 $s5 = $s5->subInt64($s14->mulInt(997805, 20));
2547 $s6 = $s6->addInt64($s14->mulInt(136657, 18));
2548 $s7 = $s7->subInt64($s14->mulInt(683901, 20));
2549
2550 $s1 = $s1->addInt64($s13->mulInt(666643, 20));
2551 $s2 = $s2->addInt64($s13->mulInt(470296, 19));
2552 $s3 = $s3->addInt64($s13->mulInt(654183, 20));
2553 $s4 = $s4->subInt64($s13->mulInt(997805, 20));
2554 $s5 = $s5->addInt64($s13->mulInt(136657, 18));
2555 $s6 = $s6->subInt64($s13->mulInt(683901, 20));
2556
2557 $s0 = $s0->addInt64($s12->mulInt(666643, 20));
2558 $s1 = $s1->addInt64($s12->mulInt(470296, 19));
2559 $s2 = $s2->addInt64($s12->mulInt(654183, 20));
2560 $s3 = $s3->subInt64($s12->mulInt(997805, 20));
2561 $s4 = $s4->addInt64($s12->mulInt(136657, 18));
2562 $s5 = $s5->subInt64($s12->mulInt(683901, 20));
2563 $s12 = new ParagonIE_Sodium_Core32_Int64();
2564
2565 $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
2566 $s1 = $s1->addInt64($carry0);
2567 $s0 = $s0->subInt64($carry0->shiftLeft(21));
2568 $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
2569 $s3 = $s3->addInt64($carry2);
2570 $s2 = $s2->subInt64($carry2->shiftLeft(21));
2571 $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
2572 $s5 = $s5->addInt64($carry4);
2573 $s4 = $s4->subInt64($carry4->shiftLeft(21));
2574 $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2575 $s7 = $s7->addInt64($carry6);
2576 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2577 $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2578 $s9 = $s9->addInt64($carry8);
2579 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2580 $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2581 $s11 = $s11->addInt64($carry10);
2582 $s10 = $s10->subInt64($carry10->shiftLeft(21));
2583
2584 $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
2585 $s2 = $s2->addInt64($carry1);
2586 $s1 = $s1->subInt64($carry1->shiftLeft(21));
2587 $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
2588 $s4 = $s4->addInt64($carry3);
2589 $s3 = $s3->subInt64($carry3->shiftLeft(21));
2590 $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
2591 $s6 = $s6->addInt64($carry5);
2592 $s5 = $s5->subInt64($carry5->shiftLeft(21));
2593 $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2594 $s8 = $s8->addInt64($carry7);
2595 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2596 $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2597 $s10 = $s10->addInt64($carry9);
2598 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2599 $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2600 $s12 = $s12->addInt64($carry11);
2601 $s11 = $s11->subInt64($carry11->shiftLeft(21));
2602
2603 $s0 = $s0->addInt64($s12->mulInt(666643, 20));
2604 $s1 = $s1->addInt64($s12->mulInt(470296, 19));
2605 $s2 = $s2->addInt64($s12->mulInt(654183, 20));
2606 $s3 = $s3->subInt64($s12->mulInt(997805, 20));
2607 $s4 = $s4->addInt64($s12->mulInt(136657, 18));
2608 $s5 = $s5->subInt64($s12->mulInt(683901, 20));
2609 $s12 = new ParagonIE_Sodium_Core32_Int64();
2610
2611 $carry0 = $s0->shiftRight(21);
2612 $s1 = $s1->addInt64($carry0);
2613 $s0 = $s0->subInt64($carry0->shiftLeft(21));
2614 $carry1 = $s1->shiftRight(21);
2615 $s2 = $s2->addInt64($carry1);
2616 $s1 = $s1->subInt64($carry1->shiftLeft(21));
2617 $carry2 = $s2->shiftRight(21);
2618 $s3 = $s3->addInt64($carry2);
2619 $s2 = $s2->subInt64($carry2->shiftLeft(21));
2620 $carry3 = $s3->shiftRight(21);
2621 $s4 = $s4->addInt64($carry3);
2622 $s3 = $s3->subInt64($carry3->shiftLeft(21));
2623 $carry4 = $s4->shiftRight(21);
2624 $s5 = $s5->addInt64($carry4);
2625 $s4 = $s4->subInt64($carry4->shiftLeft(21));
2626 $carry5 = $s5->shiftRight(21);
2627 $s6 = $s6->addInt64($carry5);
2628 $s5 = $s5->subInt64($carry5->shiftLeft(21));
2629 $carry6 = $s6->shiftRight(21);
2630 $s7 = $s7->addInt64($carry6);
2631 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2632 $carry7 = $s7->shiftRight(21);
2633 $s8 = $s8->addInt64($carry7);
2634 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2635 $carry8 = $s8->shiftRight(21);
2636 $s9 = $s9->addInt64($carry8);
2637 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2638 $carry9 = $s9->shiftRight(21);
2639 $s10 = $s10->addInt64($carry9);
2640 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2641 $carry10 = $s10->shiftRight(21);
2642 $s11 = $s11->addInt64($carry10);
2643 $s10 = $s10->subInt64($carry10->shiftLeft(21));
2644 $carry11 = $s11->shiftRight(21);
2645 $s12 = $s12->addInt64($carry11);
2646 $s11 = $s11->subInt64($carry11->shiftLeft(21));
2647
2648 $s0 = $s0->addInt64($s12->mulInt(666643, 20));
2649 $s1 = $s1->addInt64($s12->mulInt(470296, 19));
2650 $s2 = $s2->addInt64($s12->mulInt(654183, 20));
2651 $s3 = $s3->subInt64($s12->mulInt(997805, 20));
2652 $s4 = $s4->addInt64($s12->mulInt(136657, 18));
2653 $s5 = $s5->subInt64($s12->mulInt(683901, 20));
2654
2655 $carry0 = $s0->shiftRight(21);
2656 $s1 = $s1->addInt64($carry0);
2657 $s0 = $s0->subInt64($carry0->shiftLeft(21));
2658 $carry1 = $s1->shiftRight(21);
2659 $s2 = $s2->addInt64($carry1);
2660 $s1 = $s1->subInt64($carry1->shiftLeft(21));
2661 $carry2 = $s2->shiftRight(21);
2662 $s3 = $s3->addInt64($carry2);
2663 $s2 = $s2->subInt64($carry2->shiftLeft(21));
2664 $carry3 = $s3->shiftRight(21);
2665 $s4 = $s4->addInt64($carry3);
2666 $s3 = $s3->subInt64($carry3->shiftLeft(21));
2667 $carry4 = $s4->shiftRight(21);
2668 $s5 = $s5->addInt64($carry4);
2669 $s4 = $s4->subInt64($carry4->shiftLeft(21));
2670 $carry5 = $s5->shiftRight(21);
2671 $s6 = $s6->addInt64($carry5);
2672 $s5 = $s5->subInt64($carry5->shiftLeft(21));
2673 $carry6 = $s6->shiftRight(21);
2674 $s7 = $s7->addInt64($carry6);
2675 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2676 $carry7 = $s7->shiftRight(21);
2677 $s8 = $s8->addInt64($carry7);
2678 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2679 $carry8 = $s10->shiftRight(21);
2680 $s9 = $s9->addInt64($carry8);
2681 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2682 $carry9 = $s9->shiftRight(21);
2683 $s10 = $s10->addInt64($carry9);
2684 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2685 $carry10 = $s10->shiftRight(21);
2686 $s11 = $s11->addInt64($carry10);
2687 $s10 = $s10->subInt64($carry10->shiftLeft(21));
2688
2689 $S0 = $s0->toInt();
2690 $S1 = $s1->toInt();
2691 $S2 = $s2->toInt();
2692 $S3 = $s3->toInt();
2693 $S4 = $s4->toInt();
2694 $S5 = $s5->toInt();
2695 $S6 = $s6->toInt();
2696 $S7 = $s7->toInt();
2697 $S8 = $s8->toInt();
2698 $S9 = $s9->toInt();
2699 $S10 = $s10->toInt();
2700 $S11 = $s11->toInt();
2701
2702 /**
2703 * @var array<int, int>
2704 */
2705 $arr = array(
2706 (int) (0xff & ($S0 >> 0)),
2707 (int) (0xff & ($S0 >> 8)),
2708 (int) (0xff & (($S0 >> 16) | ($S1 << 5))),
2709 (int) (0xff & ($S1 >> 3)),
2710 (int) (0xff & ($S1 >> 11)),
2711 (int) (0xff & (($S1 >> 19) | ($S2 << 2))),
2712 (int) (0xff & ($S2 >> 6)),
2713 (int) (0xff & (($S2 >> 14) | ($S3 << 7))),
2714 (int) (0xff & ($S3 >> 1)),
2715 (int) (0xff & ($S3 >> 9)),
2716 (int) (0xff & (($S3 >> 17) | ($S4 << 4))),
2717 (int) (0xff & ($S4 >> 4)),
2718 (int) (0xff & ($S4 >> 12)),
2719 (int) (0xff & (($S4 >> 20) | ($S5 << 1))),
2720 (int) (0xff & ($S5 >> 7)),
2721 (int) (0xff & (($S5 >> 15) | ($S6 << 6))),
2722 (int) (0xff & ($S6 >> 2)),
2723 (int) (0xff & ($S6 >> 10)),
2724 (int) (0xff & (($S6 >> 18) | ($S7 << 3))),
2725 (int) (0xff & ($S7 >> 5)),
2726 (int) (0xff & ($S7 >> 13)),
2727 (int) (0xff & ($S8 >> 0)),
2728 (int) (0xff & ($S8 >> 8)),
2729 (int) (0xff & (($S8 >> 16) | ($S9 << 5))),
2730 (int) (0xff & ($S9 >> 3)),
2731 (int) (0xff & ($S9 >> 11)),
2732 (int) (0xff & (($S9 >> 19) | ($S10 << 2))),
2733 (int) (0xff & ($S10 >> 6)),
2734 (int) (0xff & (($S10 >> 14) | ($S11 << 7))),
2735 (int) (0xff & ($S11 >> 1)),
2736 (int) (0xff & ($S11 >> 9)),
2737 (int) (0xff & ($S11 >> 17))
2738 );
2739 return self::intArrayToString($arr);
2740 }
2741
2742 /**
2743 * @internal You should not use this directly from another application
2744 *
2745 * @param string $s
2746 * @return string
2747 * @throws SodiumException
2748 * @throws TypeError
2749 */
2750 public static function sc_reduce($s)
2751 {
2752 /**
2753 * @var ParagonIE_Sodium_Core32_Int64 $s0
2754 * @var ParagonIE_Sodium_Core32_Int64 $s1
2755 * @var ParagonIE_Sodium_Core32_Int64 $s2
2756 * @var ParagonIE_Sodium_Core32_Int64 $s3
2757 * @var ParagonIE_Sodium_Core32_Int64 $s4
2758 * @var ParagonIE_Sodium_Core32_Int64 $s5
2759 * @var ParagonIE_Sodium_Core32_Int64 $s6
2760 * @var ParagonIE_Sodium_Core32_Int64 $s7
2761 * @var ParagonIE_Sodium_Core32_Int64 $s8
2762 * @var ParagonIE_Sodium_Core32_Int64 $s9
2763 * @var ParagonIE_Sodium_Core32_Int64 $s10
2764 * @var ParagonIE_Sodium_Core32_Int64 $s11
2765 * @var ParagonIE_Sodium_Core32_Int64 $s12
2766 * @var ParagonIE_Sodium_Core32_Int64 $s13
2767 * @var ParagonIE_Sodium_Core32_Int64 $s14
2768 * @var ParagonIE_Sodium_Core32_Int64 $s15
2769 * @var ParagonIE_Sodium_Core32_Int64 $s16
2770 * @var ParagonIE_Sodium_Core32_Int64 $s17
2771 * @var ParagonIE_Sodium_Core32_Int64 $s18
2772 * @var ParagonIE_Sodium_Core32_Int64 $s19
2773 * @var ParagonIE_Sodium_Core32_Int64 $s20
2774 * @var ParagonIE_Sodium_Core32_Int64 $s21
2775 * @var ParagonIE_Sodium_Core32_Int64 $s22
2776 * @var ParagonIE_Sodium_Core32_Int64 $s23
2777 */
2778 $s0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 0, 3)));
2779 $s1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5));
2780 $s2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2));
2781 $s3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7));
2782 $s4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4));
2783 $s5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1));
2784 $s6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6));
2785 $s7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3));
2786 $s8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 21, 3)));
2787 $s9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5));
2788 $s10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2));
2789 $s11 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7));
2790 $s12 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4));
2791 $s13 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1));
2792 $s14 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6));
2793 $s15 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3));
2794 $s16 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 42, 3)));
2795 $s17 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5));
2796 $s18 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2));
2797 $s19 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7));
2798 $s20 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4));
2799 $s21 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1));
2800 $s22 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6));
2801 $s23 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3));
2802
2803 $s11 = $s11->addInt64($s23->mulInt(666643, 20));
2804 $s12 = $s12->addInt64($s23->mulInt(470296, 19));
2805 $s13 = $s13->addInt64($s23->mulInt(654183, 20));
2806 $s14 = $s14->subInt64($s23->mulInt(997805, 20));
2807 $s15 = $s15->addInt64($s23->mulInt(136657, 18));
2808 $s16 = $s16->subInt64($s23->mulInt(683901, 20));
2809
2810 $s10 = $s10->addInt64($s22->mulInt(666643, 20));
2811 $s11 = $s11->addInt64($s22->mulInt(470296, 19));
2812 $s12 = $s12->addInt64($s22->mulInt(654183, 20));
2813 $s13 = $s13->subInt64($s22->mulInt(997805, 20));
2814 $s14 = $s14->addInt64($s22->mulInt(136657, 18));
2815 $s15 = $s15->subInt64($s22->mulInt(683901, 20));
2816
2817 $s9 = $s9->addInt64($s21->mulInt(666643, 20));
2818 $s10 = $s10->addInt64($s21->mulInt(470296, 19));
2819 $s11 = $s11->addInt64($s21->mulInt(654183, 20));
2820 $s12 = $s12->subInt64($s21->mulInt(997805, 20));
2821 $s13 = $s13->addInt64($s21->mulInt(136657, 18));
2822 $s14 = $s14->subInt64($s21->mulInt(683901, 20));
2823
2824 $s8 = $s8->addInt64($s20->mulInt(666643, 20));
2825 $s9 = $s9->addInt64($s20->mulInt(470296, 19));
2826 $s10 = $s10->addInt64($s20->mulInt(654183, 20));
2827 $s11 = $s11->subInt64($s20->mulInt(997805, 20));
2828 $s12 = $s12->addInt64($s20->mulInt(136657, 18));
2829 $s13 = $s13->subInt64($s20->mulInt(683901, 20));
2830
2831 $s7 = $s7->addInt64($s19->mulInt(666643, 20));
2832 $s8 = $s8->addInt64($s19->mulInt(470296, 19));
2833 $s9 = $s9->addInt64($s19->mulInt(654183, 20));
2834 $s10 = $s10->subInt64($s19->mulInt(997805, 20));
2835 $s11 = $s11->addInt64($s19->mulInt(136657, 18));
2836 $s12 = $s12->subInt64($s19->mulInt(683901, 20));
2837
2838 $s6 = $s6->addInt64($s18->mulInt(666643, 20));
2839 $s7 = $s7->addInt64($s18->mulInt(470296, 19));
2840 $s8 = $s8->addInt64($s18->mulInt(654183, 20));
2841 $s9 = $s9->subInt64($s18->mulInt(997805, 20));
2842 $s10 = $s10->addInt64($s18->mulInt(136657, 18));
2843 $s11 = $s11->subInt64($s18->mulInt(683901, 20));
2844
2845 $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2846 $s7 = $s7->addInt64($carry6);
2847 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2848 $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2849 $s9 = $s9->addInt64($carry8);
2850 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2851 $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2852 $s11 = $s11->addInt64($carry10);
2853 $s10 = $s10->subInt64($carry10->shiftLeft(21));
2854 $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
2855 $s13 = $s13->addInt64($carry12);
2856 $s12 = $s12->subInt64($carry12->shiftLeft(21));
2857 $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
2858 $s15 = $s15->addInt64($carry14);
2859 $s14 = $s14->subInt64($carry14->shiftLeft(21));
2860 $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
2861 $s17 = $s17->addInt64($carry16);
2862 $s16 = $s16->subInt64($carry16->shiftLeft(21));
2863
2864 $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2865 $s8 = $s8->addInt64($carry7);
2866 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2867 $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2868 $s10 = $s10->addInt64($carry9);
2869 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2870 $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2871 $s12 = $s12->addInt64($carry11);
2872 $s11 = $s11->subInt64($carry11->shiftLeft(21));
2873 $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
2874 $s14 = $s14->addInt64($carry13);
2875 $s13 = $s13->subInt64($carry13->shiftLeft(21));
2876 $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
2877 $s16 = $s16->addInt64($carry15);
2878 $s15 = $s15->subInt64($carry15->shiftLeft(21));
2879
2880 $s5 = $s5->addInt64($s17->mulInt(666643, 20));
2881 $s6 = $s6->addInt64($s17->mulInt(470296, 19));
2882 $s7 = $s7->addInt64($s17->mulInt(654183, 20));
2883 $s8 = $s8->subInt64($s17->mulInt(997805, 20));
2884 $s9 = $s9->addInt64($s17->mulInt(136657, 18));
2885 $s10 = $s10->subInt64($s17->mulInt(683901, 20));
2886
2887 $s4 = $s4->addInt64($s16->mulInt(666643, 20));
2888 $s5 = $s5->addInt64($s16->mulInt(470296, 19));
2889 $s6 = $s6->addInt64($s16->mulInt(654183, 20));
2890 $s7 = $s7->subInt64($s16->mulInt(997805, 20));
2891 $s8 = $s8->addInt64($s16->mulInt(136657, 18));
2892 $s9 = $s9->subInt64($s16->mulInt(683901, 20));
2893
2894 $s3 = $s3->addInt64($s15->mulInt(666643, 20));
2895 $s4 = $s4->addInt64($s15->mulInt(470296, 19));
2896 $s5 = $s5->addInt64($s15->mulInt(654183, 20));
2897 $s6 = $s6->subInt64($s15->mulInt(997805, 20));
2898 $s7 = $s7->addInt64($s15->mulInt(136657, 18));
2899 $s8 = $s8->subInt64($s15->mulInt(683901, 20));
2900
2901 $s2 = $s2->addInt64($s14->mulInt(666643, 20));
2902 $s3 = $s3->addInt64($s14->mulInt(470296, 19));
2903 $s4 = $s4->addInt64($s14->mulInt(654183, 20));
2904 $s5 = $s5->subInt64($s14->mulInt(997805, 20));
2905 $s6 = $s6->addInt64($s14->mulInt(136657, 18));
2906 $s7 = $s7->subInt64($s14->mulInt(683901, 20));
2907
2908 $s1 = $s1->addInt64($s13->mulInt(666643, 20));
2909 $s2 = $s2->addInt64($s13->mulInt(470296, 19));
2910 $s3 = $s3->addInt64($s13->mulInt(654183, 20));
2911 $s4 = $s4->subInt64($s13->mulInt(997805, 20));
2912 $s5 = $s5->addInt64($s13->mulInt(136657, 18));
2913 $s6 = $s6->subInt64($s13->mulInt(683901, 20));
2914
2915 $s0 = $s0->addInt64($s12->mulInt(666643, 20));
2916 $s1 = $s1->addInt64($s12->mulInt(470296, 19));
2917 $s2 = $s2->addInt64($s12->mulInt(654183, 20));
2918 $s3 = $s3->subInt64($s12->mulInt(997805, 20));
2919 $s4 = $s4->addInt64($s12->mulInt(136657, 18));
2920 $s5 = $s5->subInt64($s12->mulInt(683901, 20));
2921 $s12 = new ParagonIE_Sodium_Core32_Int64();
2922
2923 $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
2924 $s1 = $s1->addInt64($carry0);
2925 $s0 = $s0->subInt64($carry0->shiftLeft(21));
2926 $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
2927 $s3 = $s3->addInt64($carry2);
2928 $s2 = $s2->subInt64($carry2->shiftLeft(21));
2929 $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
2930 $s5 = $s5->addInt64($carry4);
2931 $s4 = $s4->subInt64($carry4->shiftLeft(21));
2932 $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2933 $s7 = $s7->addInt64($carry6);
2934 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2935 $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2936 $s9 = $s9->addInt64($carry8);
2937 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2938 $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2939 $s11 = $s11->addInt64($carry10);
2940 $s10 = $s10->subInt64($carry10->shiftLeft(21));
2941 $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
2942 $s2 = $s2->addInt64($carry1);
2943 $s1 = $s1->subInt64($carry1->shiftLeft(21));
2944 $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
2945 $s4 = $s4->addInt64($carry3);
2946 $s3 = $s3->subInt64($carry3->shiftLeft(21));
2947 $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
2948 $s6 = $s6->addInt64($carry5);
2949 $s5 = $s5->subInt64($carry5->shiftLeft(21));
2950 $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2951 $s8 = $s8->addInt64($carry7);
2952 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2953 $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2954 $s10 = $s10->addInt64($carry9);
2955 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2956 $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2957 $s12 = $s12->addInt64($carry11);
2958 $s11 = $s11->subInt64($carry11->shiftLeft(21));
2959
2960 $s0 = $s0->addInt64($s12->mulInt(666643, 20));
2961 $s1 = $s1->addInt64($s12->mulInt(470296, 19));
2962 $s2 = $s2->addInt64($s12->mulInt(654183, 20));
2963 $s3 = $s3->subInt64($s12->mulInt(997805, 20));
2964 $s4 = $s4->addInt64($s12->mulInt(136657, 18));
2965 $s5 = $s5->subInt64($s12->mulInt(683901, 20));
2966 $s12 = new ParagonIE_Sodium_Core32_Int64();
2967
2968 $carry0 = $s0->shiftRight(21);
2969 $s1 = $s1->addInt64($carry0);
2970 $s0 = $s0->subInt64($carry0->shiftLeft(21));
2971 $carry1 = $s1->shiftRight(21);
2972 $s2 = $s2->addInt64($carry1);
2973 $s1 = $s1->subInt64($carry1->shiftLeft(21));
2974 $carry2 = $s2->shiftRight(21);
2975 $s3 = $s3->addInt64($carry2);
2976 $s2 = $s2->subInt64($carry2->shiftLeft(21));
2977 $carry3 = $s3->shiftRight(21);
2978 $s4 = $s4->addInt64($carry3);
2979 $s3 = $s3->subInt64($carry3->shiftLeft(21));
2980 $carry4 = $s4->shiftRight(21);
2981 $s5 = $s5->addInt64($carry4);
2982 $s4 = $s4->subInt64($carry4->shiftLeft(21));
2983 $carry5 = $s5->shiftRight(21);
2984 $s6 = $s6->addInt64($carry5);
2985 $s5 = $s5->subInt64($carry5->shiftLeft(21));
2986 $carry6 = $s6->shiftRight(21);
2987 $s7 = $s7->addInt64($carry6);
2988 $s6 = $s6->subInt64($carry6->shiftLeft(21));
2989 $carry7 = $s7->shiftRight(21);
2990 $s8 = $s8->addInt64($carry7);
2991 $s7 = $s7->subInt64($carry7->shiftLeft(21));
2992 $carry8 = $s8->shiftRight(21);
2993 $s9 = $s9->addInt64($carry8);
2994 $s8 = $s8->subInt64($carry8->shiftLeft(21));
2995 $carry9 = $s9->shiftRight(21);
2996 $s10 = $s10->addInt64($carry9);
2997 $s9 = $s9->subInt64($carry9->shiftLeft(21));
2998 $carry10 = $s10->shiftRight(21);
2999 $s11 = $s11->addInt64($carry10);
3000 $s10 = $s10->subInt64($carry10->shiftLeft(21));
3001 $carry11 = $s11->shiftRight(21);
3002 $s12 = $s12->addInt64($carry11);
3003 $s11 = $s11->subInt64($carry11->shiftLeft(21));
3004
3005 $s0 = $s0->addInt64($s12->mulInt(666643, 20));
3006 $s1 = $s1->addInt64($s12->mulInt(470296, 19));
3007 $s2 = $s2->addInt64($s12->mulInt(654183, 20));
3008 $s3 = $s3->subInt64($s12->mulInt(997805, 20));
3009 $s4 = $s4->addInt64($s12->mulInt(136657, 18));
3010 $s5 = $s5->subInt64($s12->mulInt(683901, 20));
3011
3012 $carry0 = $s0->shiftRight(21);
3013 $s1 = $s1->addInt64($carry0);
3014 $s0 = $s0->subInt64($carry0->shiftLeft(21));
3015 $carry1 = $s1->shiftRight(21);
3016 $s2 = $s2->addInt64($carry1);
3017 $s1 = $s1->subInt64($carry1->shiftLeft(21));
3018 $carry2 = $s2->shiftRight(21);
3019 $s3 = $s3->addInt64($carry2);
3020 $s2 = $s2->subInt64($carry2->shiftLeft(21));
3021 $carry3 = $s3->shiftRight(21);
3022 $s4 = $s4->addInt64($carry3);
3023 $s3 = $s3->subInt64($carry3->shiftLeft(21));
3024 $carry4 = $s4->shiftRight(21);
3025 $s5 = $s5->addInt64($carry4);
3026 $s4 = $s4->subInt64($carry4->shiftLeft(21));
3027 $carry5 = $s5->shiftRight(21);
3028 $s6 = $s6->addInt64($carry5);
3029 $s5 = $s5->subInt64($carry5->shiftLeft(21));
3030 $carry6 = $s6->shiftRight(21);
3031 $s7 = $s7->addInt64($carry6);
3032 $s6 = $s6->subInt64($carry6->shiftLeft(21));
3033 $carry7 = $s7->shiftRight(21);
3034 $s8 = $s8->addInt64($carry7);
3035 $s7 = $s7->subInt64($carry7->shiftLeft(21));
3036 $carry8 = $s8->shiftRight(21);
3037 $s9 = $s9->addInt64($carry8);
3038 $s8 = $s8->subInt64($carry8->shiftLeft(21));
3039 $carry9 = $s9->shiftRight(21);
3040 $s10 = $s10->addInt64($carry9);
3041 $s9 = $s9->subInt64($carry9->shiftLeft(21));
3042 $carry10 = $s10->shiftRight(21);
3043 $s11 = $s11->addInt64($carry10);
3044 $s10 = $s10->subInt64($carry10->shiftLeft(21));
3045
3046 $S0 = $s0->toInt32()->toInt();
3047 $S1 = $s1->toInt32()->toInt();
3048 $S2 = $s2->toInt32()->toInt();
3049 $S3 = $s3->toInt32()->toInt();
3050 $S4 = $s4->toInt32()->toInt();
3051 $S5 = $s5->toInt32()->toInt();
3052 $S6 = $s6->toInt32()->toInt();
3053 $S7 = $s7->toInt32()->toInt();
3054 $S8 = $s8->toInt32()->toInt();
3055 $S9 = $s9->toInt32()->toInt();
3056 $S10 = $s10->toInt32()->toInt();
3057 $S11 = $s11->toInt32()->toInt();
3058
3059 /**
3060 * @var array<int, int>
3061 */
3062 $arr = array(
3063 (int) ($S0 >> 0),
3064 (int) ($S0 >> 8),
3065 (int) (($S0 >> 16) | ($S1 << 5)),
3066 (int) ($S1 >> 3),
3067 (int) ($S1 >> 11),
3068 (int) (($S1 >> 19) | ($S2 << 2)),
3069 (int) ($S2 >> 6),
3070 (int) (($S2 >> 14) | ($S3 << 7)),
3071 (int) ($S3 >> 1),
3072 (int) ($S3 >> 9),
3073 (int) (($S3 >> 17) | ($S4 << 4)),
3074 (int) ($S4 >> 4),
3075 (int) ($S4 >> 12),
3076 (int) (($S4 >> 20) | ($S5 << 1)),
3077 (int) ($S5 >> 7),
3078 (int) (($S5 >> 15) | ($S6 << 6)),
3079 (int) ($S6 >> 2),
3080 (int) ($S6 >> 10),
3081 (int) (($S6 >> 18) | ($S7 << 3)),
3082 (int) ($S7 >> 5),
3083 (int) ($S7 >> 13),
3084 (int) ($S8 >> 0),
3085 (int) ($S8 >> 8),
3086 (int) (($S8 >> 16) | ($S9 << 5)),
3087 (int) ($S9 >> 3),
3088 (int) ($S9 >> 11),
3089 (int) (($S9 >> 19) | ($S10 << 2)),
3090 (int) ($S10 >> 6),
3091 (int) (($S10 >> 14) | ($S11 << 7)),
3092 (int) ($S11 >> 1),
3093 (int) ($S11 >> 9),
3094 (int) $S11 >> 17
3095 );
3096 return self::intArrayToString($arr);
3097 }
3098
3099 /**
3100 * multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493
3101 *
3102 * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
3103 * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
3104 * @throws SodiumException
3105 * @throws TypeError
3106 */
3107 public static function ge_mul_l(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A)
3108 {
3109 $aslide = array(
3110 13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0,
3111 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0,
3112 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0,
3113 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1,
3114 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
3115 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0,
3116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
3122 );
3123
3124 /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai size 8 */
3125 $Ai = array();
3126
3127 # ge_p3_to_cached(&Ai[0], A);
3128 $Ai[0] = self::ge_p3_to_cached($A);
3129 # ge_p3_dbl(&t, A);
3130 $t = self::ge_p3_dbl($A);
3131 # ge_p1p1_to_p3(&A2, &t);
3132 $A2 = self::ge_p1p1_to_p3($t);
3133
3134 for ($i = 1; $i < 8; ++$i) {
3135 # ge_add(&t, &A2, &Ai[0]);
3136 $t = self::ge_add($A2, $Ai[$i - 1]);
3137 # ge_p1p1_to_p3(&u, &t);
3138 $u = self::ge_p1p1_to_p3($t);
3139 # ge_p3_to_cached(&Ai[i], &u);
3140 $Ai[$i] = self::ge_p3_to_cached($u);
3141 }
3142
3143 $r = self::ge_p3_0();
3144 for ($i = 252; $i >= 0; --$i) {
3145 $t = self::ge_p3_dbl($r);
3146 if ($aslide[$i] > 0) {
3147 # ge_p1p1_to_p3(&u, &t);
3148 $u = self::ge_p1p1_to_p3($t);
3149 # ge_add(&t, &u, &Ai[aslide[i] / 2]);
3150 $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]);
3151 } elseif ($aslide[$i] < 0) {
3152 # ge_p1p1_to_p3(&u, &t);
3153 $u = self::ge_p1p1_to_p3($t);
3154 # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
3155 $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]);
3156 }
3157 }
3158 # ge_p1p1_to_p3(r, &t);
3159 return self::ge_p1p1_to_p3($t);
3160 }
3161}
3162