run:R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
3.58 KB
2026-03-11 16:18:52
R W Run
3.51 KB
2026-03-11 16:18:52
R W Run
15.51 KB
2026-03-11 16:18:52
R W Run
23.63 KB
2026-03-11 16:18:52
R W Run
12.59 KB
2026-03-11 16:18:52
R W Run
140.27 KB
2026-03-11 16:18:52
R W Run
18.05 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:52
R W Run
3.59 KB
2026-03-11 16:18:52
R W Run
1.54 KB
2026-03-11 16:18:52
R W Run
21.37 KB
2026-03-11 16:18:52
R W Run
8.04 KB
2026-03-11 16:18:52
R W Run
8.04 KB
2026-03-11 16:18:52
R W Run
28.23 KB
2026-03-11 16:18:52
R W Run
8.22 KB
2026-03-11 16:18:52
R W Run
3.24 KB
2026-03-11 16:18:52
R W Run
1.34 KB
2026-03-11 16:18:52
R W Run
error_log
📄Curve25519.php
1<?php
2
3if (class_exists('ParagonIE_Sodium_Core_Curve25519', false)) {
4 return;
5}
6
7/**
8 * Class ParagonIE_Sodium_Core_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_Core_Curve25519 extends ParagonIE_Sodium_Core_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_Core_Curve25519_Fe
24 */
25 public static function fe_0()
26 {
27 return new ParagonIE_Sodium_Core_Curve25519_Fe();
28 }
29
30 /**
31 * Get a field element of size 10 with a value of 1
32 *
33 * @internal You should not use this directly from another application
34 *
35 * @return ParagonIE_Sodium_Core_Curve25519_Fe
36 */
37 public static function fe_1()
38 {
39 $fe = new ParagonIE_Sodium_Core_Curve25519_Fe();
40 $fe->e0 = 1;
41 return $fe;
42 }
43
44 /**
45 * Add two field elements.
46 *
47 * @internal You should not use this directly from another application
48 *
49 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
50 * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
51 * @return ParagonIE_Sodium_Core_Curve25519_Fe
52 * @psalm-suppress MixedAssignment
53 * @psalm-suppress MixedOperand
54 */
55 public static function fe_add(
56 ParagonIE_Sodium_Core_Curve25519_Fe $f,
57 ParagonIE_Sodium_Core_Curve25519_Fe $g
58 ) {
59 return new ParagonIE_Sodium_Core_Curve25519_Fe(
60 (int)($f->e0 + $g->e0),
61 (int)($f->e1 + $g->e1),
62 (int)($f->e2 + $g->e2),
63 (int)($f->e3 + $g->e3),
64 (int)($f->e4 + $g->e4),
65 (int)($f->e5 + $g->e5),
66 (int)($f->e6 + $g->e6),
67 (int)($f->e7 + $g->e7),
68 (int)($f->e8 + $g->e8),
69 (int)($f->e9 + $g->e9)
70 );
71 }
72
73 /**
74 * Constant-time conditional move.
75 *
76 * @internal You should not use this directly from another application
77 *
78 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
79 * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
80 * @param int $b
81 * @return ParagonIE_Sodium_Core_Curve25519_Fe
82 * @psalm-suppress MixedAssignment
83 */
84 public static function fe_cmov(
85 ParagonIE_Sodium_Core_Curve25519_Fe $f,
86 ParagonIE_Sodium_Core_Curve25519_Fe $g,
87 $b = 0
88 ) {
89 $h = new ParagonIE_Sodium_Core_Curve25519_Fe();
90 $b *= -1;
91 $x = (($f->e0 ^ $g->e0) & $b); $h->e0 = $f->e0 ^ $x;
92 $x = (($f->e1 ^ $g->e1) & $b); $h->e1 = $f->e1 ^ $x;
93 $x = (($f->e2 ^ $g->e2) & $b); $h->e2 = $f->e2 ^ $x;
94 $x = (($f->e3 ^ $g->e3) & $b); $h->e3 = $f->e3 ^ $x;
95 $x = (($f->e4 ^ $g->e4) & $b); $h->e4 = $f->e4 ^ $x;
96 $x = (($f->e5 ^ $g->e5) & $b); $h->e5 = $f->e5 ^ $x;
97 $x = (($f->e6 ^ $g->e6) & $b); $h->e6 = $f->e6 ^ $x;
98 $x = (($f->e7 ^ $g->e7) & $b); $h->e7 = $f->e7 ^ $x;
99 $x = (($f->e8 ^ $g->e8) & $b); $h->e8 = $f->e8 ^ $x;
100 $x = (($f->e9 ^ $g->e9) & $b); $h->e9 = $f->e9 ^ $x;
101 return $h;
102 }
103
104 /**
105 * Create a copy of a field element.
106 *
107 * @internal You should not use this directly from another application
108 *
109 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
110 * @return ParagonIE_Sodium_Core_Curve25519_Fe
111 */
112 public static function fe_copy(ParagonIE_Sodium_Core_Curve25519_Fe $f)
113 {
114 return clone $f;
115 }
116
117 /**
118 * Give: 32-byte string.
119 * Receive: A field element object to use for internal calculations.
120 *
121 * @internal You should not use this directly from another application
122 *
123 * @param string $s
124 * @return ParagonIE_Sodium_Core_Curve25519_Fe
125 * @throws RangeException
126 * @throws TypeError
127 */
128 public static function fe_frombytes($s)
129 {
130 if (self::strlen($s) !== 32) {
131 throw new RangeException('Expected a 32-byte string.');
132 }
133 $h0 = self::load_4($s);
134 $h1 = self::load_3(self::substr($s, 4, 3)) << 6;
135 $h2 = self::load_3(self::substr($s, 7, 3)) << 5;
136 $h3 = self::load_3(self::substr($s, 10, 3)) << 3;
137 $h4 = self::load_3(self::substr($s, 13, 3)) << 2;
138 $h5 = self::load_4(self::substr($s, 16, 4));
139 $h6 = self::load_3(self::substr($s, 20, 3)) << 7;
140 $h7 = self::load_3(self::substr($s, 23, 3)) << 5;
141 $h8 = self::load_3(self::substr($s, 26, 3)) << 4;
142 $h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2;
143
144 $carry9 = ($h9 + (1 << 24)) >> 25;
145 $h0 += self::mul($carry9, 19, 5);
146 $h9 -= $carry9 << 25;
147 $carry1 = ($h1 + (1 << 24)) >> 25;
148 $h2 += $carry1;
149 $h1 -= $carry1 << 25;
150 $carry3 = ($h3 + (1 << 24)) >> 25;
151 $h4 += $carry3;
152 $h3 -= $carry3 << 25;
153 $carry5 = ($h5 + (1 << 24)) >> 25;
154 $h6 += $carry5;
155 $h5 -= $carry5 << 25;
156 $carry7 = ($h7 + (1 << 24)) >> 25;
157 $h8 += $carry7;
158 $h7 -= $carry7 << 25;
159
160 $carry0 = ($h0 + (1 << 25)) >> 26;
161 $h1 += $carry0;
162 $h0 -= $carry0 << 26;
163 $carry2 = ($h2 + (1 << 25)) >> 26;
164 $h3 += $carry2;
165 $h2 -= $carry2 << 26;
166 $carry4 = ($h4 + (1 << 25)) >> 26;
167 $h5 += $carry4;
168 $h4 -= $carry4 << 26;
169 $carry6 = ($h6 + (1 << 25)) >> 26;
170 $h7 += $carry6;
171 $h6 -= $carry6 << 26;
172 $carry8 = ($h8 + (1 << 25)) >> 26;
173 $h9 += $carry8;
174 $h8 -= $carry8 << 26;
175
176 return new ParagonIE_Sodium_Core_Curve25519_Fe(
177 (int) $h0,
178 (int) $h1,
179 (int) $h2,
180 (int) $h3,
181 (int) $h4,
182 (int) $h5,
183 (int) $h6,
184 (int) $h7,
185 (int) $h8,
186 (int) $h9
187 );
188 }
189
190 /**
191 * Convert a field element to a byte string.
192 *
193 * @internal You should not use this directly from another application
194 *
195 * @param ParagonIE_Sodium_Core_Curve25519_Fe $h
196 * @return string
197 */
198 public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe $h)
199 {
200 $h0 = (int) $h->e0;
201 $h1 = (int) $h->e1;
202 $h2 = (int) $h->e2;
203 $h3 = (int) $h->e3;
204 $h4 = (int) $h->e4;
205 $h5 = (int) $h->e5;
206 $h6 = (int) $h->e6;
207 $h7 = (int) $h->e7;
208 $h8 = (int) $h->e8;
209 $h9 = (int) $h->e9;
210
211 $q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25;
212 $q = ($h0 + $q) >> 26;
213 $q = ($h1 + $q) >> 25;
214 $q = ($h2 + $q) >> 26;
215 $q = ($h3 + $q) >> 25;
216 $q = ($h4 + $q) >> 26;
217 $q = ($h5 + $q) >> 25;
218 $q = ($h6 + $q) >> 26;
219 $q = ($h7 + $q) >> 25;
220 $q = ($h8 + $q) >> 26;
221 $q = ($h9 + $q) >> 25;
222
223 $h0 += self::mul($q, 19, 5);
224
225 $carry0 = $h0 >> 26;
226 $h1 += $carry0;
227 $h0 -= $carry0 << 26;
228 $carry1 = $h1 >> 25;
229 $h2 += $carry1;
230 $h1 -= $carry1 << 25;
231 $carry2 = $h2 >> 26;
232 $h3 += $carry2;
233 $h2 -= $carry2 << 26;
234 $carry3 = $h3 >> 25;
235 $h4 += $carry3;
236 $h3 -= $carry3 << 25;
237 $carry4 = $h4 >> 26;
238 $h5 += $carry4;
239 $h4 -= $carry4 << 26;
240 $carry5 = $h5 >> 25;
241 $h6 += $carry5;
242 $h5 -= $carry5 << 25;
243 $carry6 = $h6 >> 26;
244 $h7 += $carry6;
245 $h6 -= $carry6 << 26;
246 $carry7 = $h7 >> 25;
247 $h8 += $carry7;
248 $h7 -= $carry7 << 25;
249 $carry8 = $h8 >> 26;
250 $h9 += $carry8;
251 $h8 -= $carry8 << 26;
252 $carry9 = $h9 >> 25;
253 $h9 -= $carry9 << 25;
254
255 /**
256 * @var array<int, int>
257 */
258 $s = array(
259 (int) (($h0 >> 0) & 0xff),
260 (int) (($h0 >> 8) & 0xff),
261 (int) (($h0 >> 16) & 0xff),
262 (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
263 (int) (($h1 >> 6) & 0xff),
264 (int) (($h1 >> 14) & 0xff),
265 (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
266 (int) (($h2 >> 5) & 0xff),
267 (int) (($h2 >> 13) & 0xff),
268 (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
269 (int) (($h3 >> 3) & 0xff),
270 (int) (($h3 >> 11) & 0xff),
271 (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
272 (int) (($h4 >> 2) & 0xff),
273 (int) (($h4 >> 10) & 0xff),
274 (int) (($h4 >> 18) & 0xff),
275 (int) (($h5 >> 0) & 0xff),
276 (int) (($h5 >> 8) & 0xff),
277 (int) (($h5 >> 16) & 0xff),
278 (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
279 (int) (($h6 >> 7) & 0xff),
280 (int) (($h6 >> 15) & 0xff),
281 (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
282 (int) (($h7 >> 5) & 0xff),
283 (int) (($h7 >> 13) & 0xff),
284 (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
285 (int) (($h8 >> 4) & 0xff),
286 (int) (($h8 >> 12) & 0xff),
287 (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
288 (int) (($h9 >> 2) & 0xff),
289 (int) (($h9 >> 10) & 0xff),
290 (int) (($h9 >> 18) & 0xff)
291 );
292 return self::intArrayToString($s);
293 }
294
295 /**
296 * Is a field element negative? (1 = yes, 0 = no. Used in calculations.)
297 *
298 * @internal You should not use this directly from another application
299 *
300 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
301 * @return int
302 * @throws SodiumException
303 * @throws TypeError
304 */
305 public static function fe_isnegative(ParagonIE_Sodium_Core_Curve25519_Fe $f)
306 {
307 $str = self::fe_tobytes($f);
308 return (int) (self::chrToInt($str[0]) & 1);
309 }
310
311 /**
312 * Returns 0 if this field element results in all NUL bytes.
313 *
314 * @internal You should not use this directly from another application
315 *
316 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
317 * @return bool
318 * @throws SodiumException
319 * @throws TypeError
320 */
321 public static function fe_isnonzero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
322 {
323 static $zero;
324 if ($zero === null) {
325 $zero = str_repeat("\x00", 32);
326 }
327 /** @var string $zero */
328 /** @var string $str */
329 $str = self::fe_tobytes($f);
330 return !self::verify_32($str, (string) $zero);
331 }
332
333 /**
334 * Multiply two field elements
335 *
336 * h = f * g
337 *
338 * @internal You should not use this directly from another application
339 *
340 * @security Is multiplication a source of timing leaks? If so, can we do
341 * anything to prevent that from happening?
342 *
343 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
344 * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
345 * @return ParagonIE_Sodium_Core_Curve25519_Fe
346 */
347 public static function fe_mul(
348 ParagonIE_Sodium_Core_Curve25519_Fe $f,
349 ParagonIE_Sodium_Core_Curve25519_Fe $g
350 ) {
351 // Ensure limbs aren't oversized.
352 $f = self::fe_normalize($f);
353 $g = self::fe_normalize($g);
354 $f0 = $f->e0;
355 $f1 = $f->e1;
356 $f2 = $f->e2;
357 $f3 = $f->e3;
358 $f4 = $f->e4;
359 $f5 = $f->e5;
360 $f6 = $f->e6;
361 $f7 = $f->e7;
362 $f8 = $f->e8;
363 $f9 = $f->e9;
364 $g0 = $g->e0;
365 $g1 = $g->e1;
366 $g2 = $g->e2;
367 $g3 = $g->e3;
368 $g4 = $g->e4;
369 $g5 = $g->e5;
370 $g6 = $g->e6;
371 $g7 = $g->e7;
372 $g8 = $g->e8;
373 $g9 = $g->e9;
374 $g1_19 = self::mul($g1, 19, 5);
375 $g2_19 = self::mul($g2, 19, 5);
376 $g3_19 = self::mul($g3, 19, 5);
377 $g4_19 = self::mul($g4, 19, 5);
378 $g5_19 = self::mul($g5, 19, 5);
379 $g6_19 = self::mul($g6, 19, 5);
380 $g7_19 = self::mul($g7, 19, 5);
381 $g8_19 = self::mul($g8, 19, 5);
382 $g9_19 = self::mul($g9, 19, 5);
383 $f1_2 = $f1 << 1;
384 $f3_2 = $f3 << 1;
385 $f5_2 = $f5 << 1;
386 $f7_2 = $f7 << 1;
387 $f9_2 = $f9 << 1;
388 $f0g0 = self::mul($f0, $g0, 26);
389 $f0g1 = self::mul($f0, $g1, 25);
390 $f0g2 = self::mul($f0, $g2, 26);
391 $f0g3 = self::mul($f0, $g3, 25);
392 $f0g4 = self::mul($f0, $g4, 26);
393 $f0g5 = self::mul($f0, $g5, 25);
394 $f0g6 = self::mul($f0, $g6, 26);
395 $f0g7 = self::mul($f0, $g7, 25);
396 $f0g8 = self::mul($f0, $g8, 26);
397 $f0g9 = self::mul($f0, $g9, 26);
398 $f1g0 = self::mul($f1, $g0, 26);
399 $f1g1_2 = self::mul($f1_2, $g1, 25);
400 $f1g2 = self::mul($f1, $g2, 26);
401 $f1g3_2 = self::mul($f1_2, $g3, 25);
402 $f1g4 = self::mul($f1, $g4, 26);
403 $f1g5_2 = self::mul($f1_2, $g5, 25);
404 $f1g6 = self::mul($f1, $g6, 26);
405 $f1g7_2 = self::mul($f1_2, $g7, 25);
406 $f1g8 = self::mul($f1, $g8, 26);
407 $f1g9_38 = self::mul($g9_19, $f1_2, 26);
408 $f2g0 = self::mul($f2, $g0, 26);
409 $f2g1 = self::mul($f2, $g1, 25);
410 $f2g2 = self::mul($f2, $g2, 26);
411 $f2g3 = self::mul($f2, $g3, 25);
412 $f2g4 = self::mul($f2, $g4, 26);
413 $f2g5 = self::mul($f2, $g5, 25);
414 $f2g6 = self::mul($f2, $g6, 26);
415 $f2g7 = self::mul($f2, $g7, 25);
416 $f2g8_19 = self::mul($g8_19, $f2, 26);
417 $f2g9_19 = self::mul($g9_19, $f2, 26);
418 $f3g0 = self::mul($f3, $g0, 26);
419 $f3g1_2 = self::mul($f3_2, $g1, 25);
420 $f3g2 = self::mul($f3, $g2, 26);
421 $f3g3_2 = self::mul($f3_2, $g3, 25);
422 $f3g4 = self::mul($f3, $g4, 26);
423 $f3g5_2 = self::mul($f3_2, $g5, 25);
424 $f3g6 = self::mul($f3, $g6, 26);
425 $f3g7_38 = self::mul($g7_19, $f3_2, 26);
426 $f3g8_19 = self::mul($g8_19, $f3, 25);
427 $f3g9_38 = self::mul($g9_19, $f3_2, 26);
428 $f4g0 = self::mul($f4, $g0, 26);
429 $f4g1 = self::mul($f4, $g1, 25);
430 $f4g2 = self::mul($f4, $g2, 26);
431 $f4g3 = self::mul($f4, $g3, 25);
432 $f4g4 = self::mul($f4, $g4, 26);
433 $f4g5 = self::mul($f4, $g5, 25);
434 $f4g6_19 = self::mul($g6_19, $f4, 26);
435 $f4g7_19 = self::mul($g7_19, $f4, 26);
436 $f4g8_19 = self::mul($g8_19, $f4, 26);
437 $f4g9_19 = self::mul($g9_19, $f4, 26);
438 $f5g0 = self::mul($f5, $g0, 26);
439 $f5g1_2 = self::mul($f5_2, $g1, 25);
440 $f5g2 = self::mul($f5, $g2, 26);
441 $f5g3_2 = self::mul($f5_2, $g3, 25);
442 $f5g4 = self::mul($f5, $g4, 26);
443 $f5g5_38 = self::mul($g5_19, $f5_2, 26);
444 $f5g6_19 = self::mul($g6_19, $f5, 25);
445 $f5g7_38 = self::mul($g7_19, $f5_2, 26);
446 $f5g8_19 = self::mul($g8_19, $f5, 25);
447 $f5g9_38 = self::mul($g9_19, $f5_2, 26);
448 $f6g0 = self::mul($f6, $g0, 26);
449 $f6g1 = self::mul($f6, $g1, 25);
450 $f6g2 = self::mul($f6, $g2, 26);
451 $f6g3 = self::mul($f6, $g3, 25);
452 $f6g4_19 = self::mul($g4_19, $f6, 26);
453 $f6g5_19 = self::mul($g5_19, $f6, 26);
454 $f6g6_19 = self::mul($g6_19, $f6, 26);
455 $f6g7_19 = self::mul($g7_19, $f6, 26);
456 $f6g8_19 = self::mul($g8_19, $f6, 26);
457 $f6g9_19 = self::mul($g9_19, $f6, 26);
458 $f7g0 = self::mul($f7, $g0, 26);
459 $f7g1_2 = self::mul($f7_2, $g1, 25);
460 $f7g2 = self::mul($f7, $g2, 26);
461 $f7g3_38 = self::mul($g3_19, $f7_2, 26);
462 $f7g4_19 = self::mul($g4_19, $f7, 26);
463 $f7g5_38 = self::mul($g5_19, $f7_2, 26);
464 $f7g6_19 = self::mul($g6_19, $f7, 25);
465 $f7g7_38 = self::mul($g7_19, $f7_2, 26);
466 $f7g8_19 = self::mul($g8_19, $f7, 25);
467 $f7g9_38 = self::mul($g9_19,$f7_2, 26);
468 $f8g0 = self::mul($f8, $g0, 26);
469 $f8g1 = self::mul($f8, $g1, 25);
470 $f8g2_19 = self::mul($g2_19, $f8, 26);
471 $f8g3_19 = self::mul($g3_19, $f8, 26);
472 $f8g4_19 = self::mul($g4_19, $f8, 26);
473 $f8g5_19 = self::mul($g5_19, $f8, 26);
474 $f8g6_19 = self::mul($g6_19, $f8, 26);
475 $f8g7_19 = self::mul($g7_19, $f8, 26);
476 $f8g8_19 = self::mul($g8_19, $f8, 26);
477 $f8g9_19 = self::mul($g9_19, $f8, 26);
478 $f9g0 = self::mul($f9, $g0, 26);
479 $f9g1_38 = self::mul($g1_19, $f9_2, 26);
480 $f9g2_19 = self::mul($g2_19, $f9, 25);
481 $f9g3_38 = self::mul($g3_19, $f9_2, 26);
482 $f9g4_19 = self::mul($g4_19, $f9, 25);
483 $f9g5_38 = self::mul($g5_19, $f9_2, 26);
484 $f9g6_19 = self::mul($g6_19, $f9, 25);
485 $f9g7_38 = self::mul($g7_19, $f9_2, 26);
486 $f9g8_19 = self::mul($g8_19, $f9, 25);
487 $f9g9_38 = self::mul($g9_19, $f9_2, 26);
488
489 $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
490 $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
491 $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
492 $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
493 $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
494 $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
495 $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38;
496 $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19;
497 $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38;
498 $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ;
499
500 $carry0 = ($h0 + (1 << 25)) >> 26;
501 $h1 += $carry0;
502 $h0 -= $carry0 << 26;
503 $carry4 = ($h4 + (1 << 25)) >> 26;
504 $h5 += $carry4;
505 $h4 -= $carry4 << 26;
506
507 $carry1 = ($h1 + (1 << 24)) >> 25;
508 $h2 += $carry1;
509 $h1 -= $carry1 << 25;
510 $carry5 = ($h5 + (1 << 24)) >> 25;
511 $h6 += $carry5;
512 $h5 -= $carry5 << 25;
513
514 $carry2 = ($h2 + (1 << 25)) >> 26;
515 $h3 += $carry2;
516 $h2 -= $carry2 << 26;
517 $carry6 = ($h6 + (1 << 25)) >> 26;
518 $h7 += $carry6;
519 $h6 -= $carry6 << 26;
520
521 $carry3 = ($h3 + (1 << 24)) >> 25;
522 $h4 += $carry3;
523 $h3 -= $carry3 << 25;
524 $carry7 = ($h7 + (1 << 24)) >> 25;
525 $h8 += $carry7;
526 $h7 -= $carry7 << 25;
527
528 $carry4 = ($h4 + (1 << 25)) >> 26;
529 $h5 += $carry4;
530 $h4 -= $carry4 << 26;
531 $carry8 = ($h8 + (1 << 25)) >> 26;
532 $h9 += $carry8;
533 $h8 -= $carry8 << 26;
534
535 $carry9 = ($h9 + (1 << 24)) >> 25;
536 $h0 += self::mul($carry9, 19, 5);
537 $h9 -= $carry9 << 25;
538
539 $carry0 = ($h0 + (1 << 25)) >> 26;
540 $h1 += $carry0;
541 $h0 -= $carry0 << 26;
542
543 return self::fe_normalize(
544 new ParagonIE_Sodium_Core_Curve25519_Fe(
545 (int) $h0,
546 (int) $h1,
547 (int) $h2,
548 (int) $h3,
549 (int) $h4,
550 (int) $h5,
551 (int) $h6,
552 (int) $h7,
553 (int) $h8,
554 (int) $h9
555 )
556 );
557 }
558
559 /**
560 * Get the negative values for each piece of the field element.
561 *
562 * h = -f
563 *
564 * @internal You should not use this directly from another application
565 *
566 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
567 * @return ParagonIE_Sodium_Core_Curve25519_Fe
568 * @psalm-suppress MixedAssignment
569 */
570 public static function fe_neg(ParagonIE_Sodium_Core_Curve25519_Fe $f)
571 {
572 return self::fe_normalize(
573 new ParagonIE_Sodium_Core_Curve25519_Fe(
574 -$f->e0,
575 -$f->e1,
576 -$f->e2,
577 -$f->e3,
578 -$f->e4,
579 -$f->e5,
580 -$f->e6,
581 -$f->e7,
582 -$f->e8,
583 -$f->e9
584 )
585 );
586 }
587
588 /**
589 * Square a field element
590 *
591 * h = f * f
592 *
593 * @internal You should not use this directly from another application
594 *
595 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
596 * @return ParagonIE_Sodium_Core_Curve25519_Fe
597 */
598 public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f)
599 {
600 $f = self::fe_normalize($f);
601 $f0 = (int) $f->e0;
602 $f1 = (int) $f->e1;
603 $f2 = (int) $f->e2;
604 $f3 = (int) $f->e3;
605 $f4 = (int) $f->e4;
606 $f5 = (int) $f->e5;
607 $f6 = (int) $f->e6;
608 $f7 = (int) $f->e7;
609 $f8 = (int) $f->e8;
610 $f9 = (int) $f->e9;
611
612 $f0_2 = $f0 << 1;
613 $f1_2 = $f1 << 1;
614 $f2_2 = $f2 << 1;
615 $f3_2 = $f3 << 1;
616 $f4_2 = $f4 << 1;
617 $f5_2 = $f5 << 1;
618 $f6_2 = $f6 << 1;
619 $f7_2 = $f7 << 1;
620 $f5_38 = self::mul($f5, 38, 6);
621 $f6_19 = self::mul($f6, 19, 5);
622 $f7_38 = self::mul($f7, 38, 6);
623 $f8_19 = self::mul($f8, 19, 5);
624 $f9_38 = self::mul($f9, 38, 6);
625 $f0f0 = self::mul($f0, $f0, 26);
626 $f0f1_2 = self::mul($f0_2, $f1, 26);
627 $f0f2_2 = self::mul($f0_2, $f2, 26);
628 $f0f3_2 = self::mul($f0_2, $f3, 26);
629 $f0f4_2 = self::mul($f0_2, $f4, 26);
630 $f0f5_2 = self::mul($f0_2, $f5, 26);
631 $f0f6_2 = self::mul($f0_2, $f6, 26);
632 $f0f7_2 = self::mul($f0_2, $f7, 26);
633 $f0f8_2 = self::mul($f0_2, $f8, 26);
634 $f0f9_2 = self::mul($f0_2, $f9, 26);
635 $f1f1_2 = self::mul($f1_2, $f1, 26);
636 $f1f2_2 = self::mul($f1_2, $f2, 26);
637 $f1f3_4 = self::mul($f1_2, $f3_2, 26);
638 $f1f4_2 = self::mul($f1_2, $f4, 26);
639 $f1f5_4 = self::mul($f1_2, $f5_2, 26);
640 $f1f6_2 = self::mul($f1_2, $f6, 26);
641 $f1f7_4 = self::mul($f1_2, $f7_2, 26);
642 $f1f8_2 = self::mul($f1_2, $f8, 26);
643 $f1f9_76 = self::mul($f9_38, $f1_2, 27);
644 $f2f2 = self::mul($f2, $f2, 27);
645 $f2f3_2 = self::mul($f2_2, $f3, 27);
646 $f2f4_2 = self::mul($f2_2, $f4, 27);
647 $f2f5_2 = self::mul($f2_2, $f5, 27);
648 $f2f6_2 = self::mul($f2_2, $f6, 27);
649 $f2f7_2 = self::mul($f2_2, $f7, 27);
650 $f2f8_38 = self::mul($f8_19, $f2_2, 27);
651 $f2f9_38 = self::mul($f9_38, $f2, 26);
652 $f3f3_2 = self::mul($f3_2, $f3, 26);
653 $f3f4_2 = self::mul($f3_2, $f4, 26);
654 $f3f5_4 = self::mul($f3_2, $f5_2, 26);
655 $f3f6_2 = self::mul($f3_2, $f6, 26);
656 $f3f7_76 = self::mul($f7_38, $f3_2, 26);
657 $f3f8_38 = self::mul($f8_19, $f3_2, 26);
658 $f3f9_76 = self::mul($f9_38, $f3_2, 26);
659 $f4f4 = self::mul($f4, $f4, 26);
660 $f4f5_2 = self::mul($f4_2, $f5, 26);
661 $f4f6_38 = self::mul($f6_19, $f4_2, 27);
662 $f4f7_38 = self::mul($f7_38, $f4, 26);
663 $f4f8_38 = self::mul($f8_19, $f4_2, 27);
664 $f4f9_38 = self::mul($f9_38, $f4, 26);
665 $f5f5_38 = self::mul($f5_38, $f5, 26);
666 $f5f6_38 = self::mul($f6_19, $f5_2, 26);
667 $f5f7_76 = self::mul($f7_38, $f5_2, 26);
668 $f5f8_38 = self::mul($f8_19, $f5_2, 26);
669 $f5f9_76 = self::mul($f9_38, $f5_2, 26);
670 $f6f6_19 = self::mul($f6_19, $f6, 26);
671 $f6f7_38 = self::mul($f7_38, $f6, 26);
672 $f6f8_38 = self::mul($f8_19, $f6_2, 27);
673 $f6f9_38 = self::mul($f9_38, $f6, 26);
674 $f7f7_38 = self::mul($f7_38, $f7, 26);
675 $f7f8_38 = self::mul($f8_19, $f7_2, 26);
676 $f7f9_76 = self::mul($f9_38, $f7_2, 26);
677 $f8f8_19 = self::mul($f8_19, $f8, 26);
678 $f8f9_38 = self::mul($f9_38, $f8, 26);
679 $f9f9_38 = self::mul($f9_38, $f9, 26);
680 $h0 = $f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38;
681 $h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38;
682 $h2 = $f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19;
683 $h3 = $f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38;
684 $h4 = $f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38;
685 $h5 = $f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38;
686 $h6 = $f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19;
687 $h7 = $f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38;
688 $h8 = $f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38;
689 $h9 = $f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2;
690
691 $carry0 = ($h0 + (1 << 25)) >> 26;
692 $h1 += $carry0;
693 $h0 -= $carry0 << 26;
694 $carry4 = ($h4 + (1 << 25)) >> 26;
695 $h5 += $carry4;
696 $h4 -= $carry4 << 26;
697
698 $carry1 = ($h1 + (1 << 24)) >> 25;
699 $h2 += $carry1;
700 $h1 -= $carry1 << 25;
701 $carry5 = ($h5 + (1 << 24)) >> 25;
702 $h6 += $carry5;
703 $h5 -= $carry5 << 25;
704
705 $carry2 = ($h2 + (1 << 25)) >> 26;
706 $h3 += $carry2;
707 $h2 -= $carry2 << 26;
708 $carry6 = ($h6 + (1 << 25)) >> 26;
709 $h7 += $carry6;
710 $h6 -= $carry6 << 26;
711
712 $carry3 = ($h3 + (1 << 24)) >> 25;
713 $h4 += $carry3;
714 $h3 -= $carry3 << 25;
715 $carry7 = ($h7 + (1 << 24)) >> 25;
716 $h8 += $carry7;
717 $h7 -= $carry7 << 25;
718
719 $carry4 = ($h4 + (1 << 25)) >> 26;
720 $h5 += $carry4;
721 $h4 -= $carry4 << 26;
722 $carry8 = ($h8 + (1 << 25)) >> 26;
723 $h9 += $carry8;
724 $h8 -= $carry8 << 26;
725
726 $carry9 = ($h9 + (1 << 24)) >> 25;
727 $h0 += self::mul($carry9, 19, 5);
728 $h9 -= $carry9 << 25;
729
730 $carry0 = ($h0 + (1 << 25)) >> 26;
731 $h1 += $carry0;
732 $h0 -= $carry0 << 26;
733
734 return self::fe_normalize(
735 new ParagonIE_Sodium_Core_Curve25519_Fe(
736 (int) $h0,
737 (int) $h1,
738 (int) $h2,
739 (int) $h3,
740 (int) $h4,
741 (int) $h5,
742 (int) $h6,
743 (int) $h7,
744 (int) $h8,
745 (int) $h9
746 )
747 );
748 }
749
750
751 /**
752 * Square and double a field element
753 *
754 * h = 2 * f * f
755 *
756 * @internal You should not use this directly from another application
757 *
758 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
759 * @return ParagonIE_Sodium_Core_Curve25519_Fe
760 */
761 public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f)
762 {
763 $f = self::fe_normalize($f);
764 $f0 = (int) $f->e0;
765 $f1 = (int) $f->e1;
766 $f2 = (int) $f->e2;
767 $f3 = (int) $f->e3;
768 $f4 = (int) $f->e4;
769 $f5 = (int) $f->e5;
770 $f6 = (int) $f->e6;
771 $f7 = (int) $f->e7;
772 $f8 = (int) $f->e8;
773 $f9 = (int) $f->e9;
774
775 $f0_2 = $f0 << 1;
776 $f1_2 = $f1 << 1;
777 $f2_2 = $f2 << 1;
778 $f3_2 = $f3 << 1;
779 $f4_2 = $f4 << 1;
780 $f5_2 = $f5 << 1;
781 $f6_2 = $f6 << 1;
782 $f7_2 = $f7 << 1;
783 $f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */
784 $f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */
785 $f7_38 = self::mul($f7, 38, 6); /* 1.959375*2^30 */
786 $f8_19 = self::mul($f8, 19, 5); /* 1.959375*2^30 */
787 $f9_38 = self::mul($f9, 38, 6); /* 1.959375*2^30 */
788 $f0f0 = self::mul($f0, $f0, 24);
789 $f0f1_2 = self::mul($f0_2, $f1, 24);
790 $f0f2_2 = self::mul($f0_2, $f2, 24);
791 $f0f3_2 = self::mul($f0_2, $f3, 24);
792 $f0f4_2 = self::mul($f0_2, $f4, 24);
793 $f0f5_2 = self::mul($f0_2, $f5, 24);
794 $f0f6_2 = self::mul($f0_2, $f6, 24);
795 $f0f7_2 = self::mul($f0_2, $f7, 24);
796 $f0f8_2 = self::mul($f0_2, $f8, 24);
797 $f0f9_2 = self::mul($f0_2, $f9, 24);
798 $f1f1_2 = self::mul($f1_2, $f1, 24);
799 $f1f2_2 = self::mul($f1_2, $f2, 24);
800 $f1f3_4 = self::mul($f1_2, $f3_2, 24);
801 $f1f4_2 = self::mul($f1_2, $f4, 24);
802 $f1f5_4 = self::mul($f1_2, $f5_2, 24);
803 $f1f6_2 = self::mul($f1_2, $f6, 24);
804 $f1f7_4 = self::mul($f1_2, $f7_2, 24);
805 $f1f8_2 = self::mul($f1_2, $f8, 24);
806 $f1f9_76 = self::mul($f9_38, $f1_2, 24);
807 $f2f2 = self::mul($f2, $f2, 24);
808 $f2f3_2 = self::mul($f2_2, $f3, 24);
809 $f2f4_2 = self::mul($f2_2, $f4, 24);
810 $f2f5_2 = self::mul($f2_2, $f5, 24);
811 $f2f6_2 = self::mul($f2_2, $f6, 24);
812 $f2f7_2 = self::mul($f2_2, $f7, 24);
813 $f2f8_38 = self::mul($f8_19, $f2_2, 25);
814 $f2f9_38 = self::mul($f9_38, $f2, 24);
815 $f3f3_2 = self::mul($f3_2, $f3, 24);
816 $f3f4_2 = self::mul($f3_2, $f4, 24);
817 $f3f5_4 = self::mul($f3_2, $f5_2, 24);
818 $f3f6_2 = self::mul($f3_2, $f6, 24);
819 $f3f7_76 = self::mul($f7_38, $f3_2, 24);
820 $f3f8_38 = self::mul($f8_19, $f3_2, 24);
821 $f3f9_76 = self::mul($f9_38, $f3_2, 24);
822 $f4f4 = self::mul($f4, $f4, 24);
823 $f4f5_2 = self::mul($f4_2, $f5, 24);
824 $f4f6_38 = self::mul($f6_19, $f4_2, 25);
825 $f4f7_38 = self::mul($f7_38, $f4, 24);
826 $f4f8_38 = self::mul($f8_19, $f4_2, 25);
827 $f4f9_38 = self::mul($f9_38, $f4, 24);
828 $f5f5_38 = self::mul($f5_38, $f5, 24);
829 $f5f6_38 = self::mul($f6_19, $f5_2, 24);
830 $f5f7_76 = self::mul($f7_38, $f5_2, 24);
831 $f5f8_38 = self::mul($f8_19, $f5_2, 24);
832 $f5f9_76 = self::mul($f9_38, $f5_2, 24);
833 $f6f6_19 = self::mul($f6_19, $f6, 24);
834 $f6f7_38 = self::mul($f7_38, $f6, 24);
835 $f6f8_38 = self::mul($f8_19, $f6_2, 25);
836 $f6f9_38 = self::mul($f9_38, $f6, 24);
837 $f7f7_38 = self::mul($f7_38, $f7, 24);
838 $f7f8_38 = self::mul($f8_19, $f7_2, 24);
839 $f7f9_76 = self::mul($f9_38, $f7_2, 24);
840 $f8f8_19 = self::mul($f8_19, $f8, 24);
841 $f8f9_38 = self::mul($f9_38, $f8, 24);
842 $f9f9_38 = self::mul($f9_38, $f9, 24);
843
844 $h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38) << 1;
845 $h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38) << 1;
846 $h2 = (int) ($f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19) << 1;
847 $h3 = (int) ($f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38) << 1;
848 $h4 = (int) ($f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38) << 1;
849 $h5 = (int) ($f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38) << 1;
850 $h6 = (int) ($f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19) << 1;
851 $h7 = (int) ($f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38) << 1;
852 $h8 = (int) ($f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38) << 1;
853 $h9 = (int) ($f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2) << 1;
854
855 $carry0 = ($h0 + (1 << 25)) >> 26;
856 $h1 += $carry0;
857 $h0 -= $carry0 << 26;
858 $carry4 = ($h4 + (1 << 25)) >> 26;
859 $h5 += $carry4;
860 $h4 -= $carry4 << 26;
861
862 $carry1 = ($h1 + (1 << 24)) >> 25;
863 $h2 += $carry1;
864 $h1 -= $carry1 << 25;
865 $carry5 = ($h5 + (1 << 24)) >> 25;
866 $h6 += $carry5;
867 $h5 -= $carry5 << 25;
868
869 $carry2 = ($h2 + (1 << 25)) >> 26;
870 $h3 += $carry2;
871 $h2 -= $carry2 << 26;
872 $carry6 = ($h6 + (1 << 25)) >> 26;
873 $h7 += $carry6;
874 $h6 -= $carry6 << 26;
875
876 $carry3 = ($h3 + (1 << 24)) >> 25;
877 $h4 += $carry3;
878 $h3 -= $carry3 << 25;
879 $carry7 = ($h7 + (1 << 24)) >> 25;
880 $h8 += $carry7;
881 $h7 -= $carry7 << 25;
882
883 $carry4 = ($h4 + (1 << 25)) >> 26;
884 $h5 += $carry4;
885 $h4 -= $carry4 << 26;
886 $carry8 = ($h8 + (1 << 25)) >> 26;
887 $h9 += $carry8;
888 $h8 -= $carry8 << 26;
889
890 $carry9 = ($h9 + (1 << 24)) >> 25;
891 $h0 += self::mul($carry9, 19, 5);
892 $h9 -= $carry9 << 25;
893
894 $carry0 = ($h0 + (1 << 25)) >> 26;
895 $h1 += $carry0;
896 $h0 -= $carry0 << 26;
897
898 return self::fe_normalize(
899 new ParagonIE_Sodium_Core_Curve25519_Fe(
900 (int) $h0,
901 (int) $h1,
902 (int) $h2,
903 (int) $h3,
904 (int) $h4,
905 (int) $h5,
906 (int) $h6,
907 (int) $h7,
908 (int) $h8,
909 (int) $h9
910 )
911 );
912 }
913
914 /**
915 * @internal You should not use this directly from another application
916 *
917 * @param ParagonIE_Sodium_Core_Curve25519_Fe $Z
918 * @return ParagonIE_Sodium_Core_Curve25519_Fe
919 */
920 public static function fe_invert(ParagonIE_Sodium_Core_Curve25519_Fe $Z)
921 {
922 $z = clone $Z;
923 $t0 = self::fe_sq($z);
924 $t1 = self::fe_sq($t0);
925 $t1 = self::fe_sq($t1);
926 $t1 = self::fe_mul($z, $t1);
927 $t0 = self::fe_mul($t0, $t1);
928 $t2 = self::fe_sq($t0);
929 $t1 = self::fe_mul($t1, $t2);
930 $t2 = self::fe_sq($t1);
931 for ($i = 1; $i < 5; ++$i) {
932 $t2 = self::fe_sq($t2);
933 }
934 $t1 = self::fe_mul($t2, $t1);
935 $t2 = self::fe_sq($t1);
936 for ($i = 1; $i < 10; ++$i) {
937 $t2 = self::fe_sq($t2);
938 }
939 $t2 = self::fe_mul($t2, $t1);
940 $t3 = self::fe_sq($t2);
941 for ($i = 1; $i < 20; ++$i) {
942 $t3 = self::fe_sq($t3);
943 }
944 $t2 = self::fe_mul($t3, $t2);
945 $t2 = self::fe_sq($t2);
946 for ($i = 1; $i < 10; ++$i) {
947 $t2 = self::fe_sq($t2);
948 }
949 $t1 = self::fe_mul($t2, $t1);
950 $t2 = self::fe_sq($t1);
951 for ($i = 1; $i < 50; ++$i) {
952 $t2 = self::fe_sq($t2);
953 }
954 $t2 = self::fe_mul($t2, $t1);
955 $t3 = self::fe_sq($t2);
956 for ($i = 1; $i < 100; ++$i) {
957 $t3 = self::fe_sq($t3);
958 }
959 $t2 = self::fe_mul($t3, $t2);
960 $t2 = self::fe_sq($t2);
961 for ($i = 1; $i < 50; ++$i) {
962 $t2 = self::fe_sq($t2);
963 }
964 $t1 = self::fe_mul($t2, $t1);
965 $t1 = self::fe_sq($t1);
966 for ($i = 1; $i < 5; ++$i) {
967 $t1 = self::fe_sq($t1);
968 }
969 return self::fe_mul($t1, $t0);
970 }
971
972 /**
973 * @internal You should not use this directly from another application
974 *
975 * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
976 *
977 * @param ParagonIE_Sodium_Core_Curve25519_Fe $z
978 * @return ParagonIE_Sodium_Core_Curve25519_Fe
979 */
980 public static function fe_pow22523(ParagonIE_Sodium_Core_Curve25519_Fe $z)
981 {
982 $z = self::fe_normalize($z);
983 # fe_sq(t0, z);
984 # fe_sq(t1, t0);
985 # fe_sq(t1, t1);
986 # fe_mul(t1, z, t1);
987 # fe_mul(t0, t0, t1);
988 # fe_sq(t0, t0);
989 # fe_mul(t0, t1, t0);
990 # fe_sq(t1, t0);
991 $t0 = self::fe_sq($z);
992 $t1 = self::fe_sq($t0);
993 $t1 = self::fe_sq($t1);
994 $t1 = self::fe_mul($z, $t1);
995 $t0 = self::fe_mul($t0, $t1);
996 $t0 = self::fe_sq($t0);
997 $t0 = self::fe_mul($t1, $t0);
998 $t1 = self::fe_sq($t0);
999
1000 # for (i = 1; i < 5; ++i) {
1001 # fe_sq(t1, t1);
1002 # }
1003 for ($i = 1; $i < 5; ++$i) {
1004 $t1 = self::fe_sq($t1);
1005 }
1006
1007 # fe_mul(t0, t1, t0);
1008 # fe_sq(t1, t0);
1009 $t0 = self::fe_mul($t1, $t0);
1010 $t1 = self::fe_sq($t0);
1011
1012 # for (i = 1; i < 10; ++i) {
1013 # fe_sq(t1, t1);
1014 # }
1015 for ($i = 1; $i < 10; ++$i) {
1016 $t1 = self::fe_sq($t1);
1017 }
1018
1019 # fe_mul(t1, t1, t0);
1020 # fe_sq(t2, t1);
1021 $t1 = self::fe_mul($t1, $t0);
1022 $t2 = self::fe_sq($t1);
1023
1024 # for (i = 1; i < 20; ++i) {
1025 # fe_sq(t2, t2);
1026 # }
1027 for ($i = 1; $i < 20; ++$i) {
1028 $t2 = self::fe_sq($t2);
1029 }
1030
1031 # fe_mul(t1, t2, t1);
1032 # fe_sq(t1, t1);
1033 $t1 = self::fe_mul($t2, $t1);
1034 $t1 = self::fe_sq($t1);
1035
1036 # for (i = 1; i < 10; ++i) {
1037 # fe_sq(t1, t1);
1038 # }
1039 for ($i = 1; $i < 10; ++$i) {
1040 $t1 = self::fe_sq($t1);
1041 }
1042
1043 # fe_mul(t0, t1, t0);
1044 # fe_sq(t1, t0);
1045 $t0 = self::fe_mul($t1, $t0);
1046 $t1 = self::fe_sq($t0);
1047
1048 # for (i = 1; i < 50; ++i) {
1049 # fe_sq(t1, t1);
1050 # }
1051 for ($i = 1; $i < 50; ++$i) {
1052 $t1 = self::fe_sq($t1);
1053 }
1054
1055 # fe_mul(t1, t1, t0);
1056 # fe_sq(t2, t1);
1057 $t1 = self::fe_mul($t1, $t0);
1058 $t2 = self::fe_sq($t1);
1059
1060 # for (i = 1; i < 100; ++i) {
1061 # fe_sq(t2, t2);
1062 # }
1063 for ($i = 1; $i < 100; ++$i) {
1064 $t2 = self::fe_sq($t2);
1065 }
1066
1067 # fe_mul(t1, t2, t1);
1068 # fe_sq(t1, t1);
1069 $t1 = self::fe_mul($t2, $t1);
1070 $t1 = self::fe_sq($t1);
1071
1072 # for (i = 1; i < 50; ++i) {
1073 # fe_sq(t1, t1);
1074 # }
1075 for ($i = 1; $i < 50; ++$i) {
1076 $t1 = self::fe_sq($t1);
1077 }
1078
1079 # fe_mul(t0, t1, t0);
1080 # fe_sq(t0, t0);
1081 # fe_sq(t0, t0);
1082 # fe_mul(out, t0, z);
1083 $t0 = self::fe_mul($t1, $t0);
1084 $t0 = self::fe_sq($t0);
1085 $t0 = self::fe_sq($t0);
1086 return self::fe_mul($t0, $z);
1087 }
1088
1089 /**
1090 * Subtract two field elements.
1091 *
1092 * h = f - g
1093 *
1094 * Preconditions:
1095 * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
1096 * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
1097 *
1098 * Postconditions:
1099 * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
1100 *
1101 * @internal You should not use this directly from another application
1102 *
1103 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
1104 * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
1105 * @return ParagonIE_Sodium_Core_Curve25519_Fe
1106 * @psalm-suppress MixedOperand
1107 */
1108 public static function fe_sub(ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g)
1109 {
1110 return self::fe_normalize(
1111 new ParagonIE_Sodium_Core_Curve25519_Fe(
1112 (int) ($f->e0 - $g->e0),
1113 (int) ($f->e1 - $g->e1),
1114 (int) ($f->e2 - $g->e2),
1115 (int) ($f->e3 - $g->e3),
1116 (int) ($f->e4 - $g->e4),
1117 (int) ($f->e5 - $g->e5),
1118 (int) ($f->e6 - $g->e6),
1119 (int) ($f->e7 - $g->e7),
1120 (int) ($f->e8 - $g->e8),
1121 (int) ($f->e9 - $g->e9)
1122 )
1123 );
1124 }
1125
1126 /**
1127 * Add two group elements.
1128 *
1129 * r = p + q
1130 *
1131 * @internal You should not use this directly from another application
1132 *
1133 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1134 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
1135 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
1136 */
1137 public static function ge_add(
1138 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
1139 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
1140 ) {
1141 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
1142 $r->X = self::fe_add($p->Y, $p->X);
1143 $r->Y = self::fe_sub($p->Y, $p->X);
1144 $r->Z = self::fe_mul($r->X, $q->YplusX);
1145 $r->Y = self::fe_mul($r->Y, $q->YminusX);
1146 $r->T = self::fe_mul($q->T2d, $p->T);
1147 $r->X = self::fe_mul($p->Z, $q->Z);
1148 $t0 = self::fe_add($r->X, $r->X);
1149 $r->X = self::fe_sub($r->Z, $r->Y);
1150 $r->Y = self::fe_add($r->Z, $r->Y);
1151 $r->Z = self::fe_add($t0, $r->T);
1152 $r->T = self::fe_sub($t0, $r->T);
1153 return $r;
1154 }
1155
1156 /**
1157 * @internal You should not use this directly from another application
1158 *
1159 * @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
1160 * @param string $a
1161 * @return array<int, mixed>
1162 * @throws SodiumException
1163 * @throws TypeError
1164 */
1165 public static function slide($a)
1166 {
1167 if (self::strlen($a) < 256) {
1168 if (self::strlen($a) < 16) {
1169 $a = str_pad($a, 256, '0', STR_PAD_RIGHT);
1170 }
1171 }
1172 /** @var array<int, int> $r */
1173 $r = array();
1174
1175 /** @var int $i */
1176 for ($i = 0; $i < 256; ++$i) {
1177 $r[$i] = (int) (
1178 1 & (
1179 self::chrToInt($a[(int) ($i >> 3)])
1180 >>
1181 ($i & 7)
1182 )
1183 );
1184 }
1185
1186 for ($i = 0;$i < 256;++$i) {
1187 if ($r[$i]) {
1188 for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
1189 if ($r[$i + $b]) {
1190 if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
1191 $r[$i] += $r[$i + $b] << $b;
1192 $r[$i + $b] = 0;
1193 } elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) {
1194 $r[$i] -= $r[$i + $b] << $b;
1195 for ($k = $i + $b; $k < 256; ++$k) {
1196 if (!$r[$k]) {
1197 $r[$k] = 1;
1198 break;
1199 }
1200 $r[$k] = 0;
1201 }
1202 } else {
1203 break;
1204 }
1205 }
1206 }
1207 }
1208 }
1209 return $r;
1210 }
1211
1212 /**
1213 * @internal You should not use this directly from another application
1214 *
1215 * @param string $s
1216 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
1217 * @throws SodiumException
1218 * @throws TypeError
1219 */
1220 public static function ge_frombytes_negate_vartime($s)
1221 {
1222 static $d = null;
1223 if (!$d) {
1224 $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
1225 }
1226
1227 # fe_frombytes(h->Y,s);
1228 # fe_1(h->Z);
1229 $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
1230 self::fe_0(),
1231 self::fe_frombytes($s),
1232 self::fe_1()
1233 );
1234
1235 # fe_sq(u,h->Y);
1236 # fe_mul(v,u,d);
1237 # fe_sub(u,u,h->Z); /* u = y^2-1 */
1238 # fe_add(v,v,h->Z); /* v = dy^2+1 */
1239 $u = self::fe_sq($h->Y);
1240 /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d */
1241 $v = self::fe_mul($u, $d);
1242 $u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */
1243 $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */
1244
1245 # fe_sq(v3,v);
1246 # fe_mul(v3,v3,v); /* v3 = v^3 */
1247 # fe_sq(h->X,v3);
1248 # fe_mul(h->X,h->X,v);
1249 # fe_mul(h->X,h->X,u); /* x = uv^7 */
1250 $v3 = self::fe_sq($v);
1251 $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
1252 $h->X = self::fe_sq($v3);
1253 $h->X = self::fe_mul($h->X, $v);
1254 $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */
1255
1256 # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
1257 # fe_mul(h->X,h->X,v3);
1258 # fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
1259 $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
1260 $h->X = self::fe_mul($h->X, $v3);
1261 $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */
1262
1263 # fe_sq(vxx,h->X);
1264 # fe_mul(vxx,vxx,v);
1265 # fe_sub(check,vxx,u); /* vx^2-u */
1266 $vxx = self::fe_sq($h->X);
1267 $vxx = self::fe_mul($vxx, $v);
1268 $check = self::fe_sub($vxx, $u); /* vx^2 - u */
1269
1270 # if (fe_isnonzero(check)) {
1271 # fe_add(check,vxx,u); /* vx^2+u */
1272 # if (fe_isnonzero(check)) {
1273 # return -1;
1274 # }
1275 # fe_mul(h->X,h->X,sqrtm1);
1276 # }
1277 if (self::fe_isnonzero($check)) {
1278 $check = self::fe_add($vxx, $u); /* vx^2 + u */
1279 if (self::fe_isnonzero($check)) {
1280 throw new RangeException('Internal check failed.');
1281 }
1282 $h->X = self::fe_mul(
1283 $h->X,
1284 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1)
1285 );
1286 }
1287
1288 # if (fe_isnegative(h->X) == (s[31] >> 7)) {
1289 # fe_neg(h->X,h->X);
1290 # }
1291 $i = self::chrToInt($s[31]);
1292 if (self::fe_isnegative($h->X) === ($i >> 7)) {
1293 $h->X = self::fe_neg($h->X);
1294 }
1295
1296 # fe_mul(h->T,h->X,h->Y);
1297 $h->T = self::fe_mul($h->X, $h->Y);
1298 return $h;
1299 }
1300
1301 /**
1302 * @internal You should not use this directly from another application
1303 *
1304 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
1305 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1306 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
1307 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
1308 */
1309 public static function ge_madd(
1310 ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
1311 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
1312 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
1313 ) {
1314 $r = clone $R;
1315 $r->X = self::fe_add($p->Y, $p->X);
1316 $r->Y = self::fe_sub($p->Y, $p->X);
1317 $r->Z = self::fe_mul($r->X, $q->yplusx);
1318 $r->Y = self::fe_mul($r->Y, $q->yminusx);
1319 $r->T = self::fe_mul($q->xy2d, $p->T);
1320 $t0 = self::fe_add(clone $p->Z, clone $p->Z);
1321 $r->X = self::fe_sub($r->Z, $r->Y);
1322 $r->Y = self::fe_add($r->Z, $r->Y);
1323 $r->Z = self::fe_add($t0, $r->T);
1324 $r->T = self::fe_sub($t0, $r->T);
1325
1326 return $r;
1327 }
1328
1329 /**
1330 * @internal You should not use this directly from another application
1331 *
1332 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
1333 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1334 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
1335 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
1336 */
1337 public static function ge_msub(
1338 ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
1339 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
1340 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
1341 ) {
1342 $r = clone $R;
1343
1344 $r->X = self::fe_add($p->Y, $p->X);
1345 $r->Y = self::fe_sub($p->Y, $p->X);
1346 $r->Z = self::fe_mul($r->X, $q->yminusx);
1347 $r->Y = self::fe_mul($r->Y, $q->yplusx);
1348 $r->T = self::fe_mul($q->xy2d, $p->T);
1349 $t0 = self::fe_add($p->Z, $p->Z);
1350 $r->X = self::fe_sub($r->Z, $r->Y);
1351 $r->Y = self::fe_add($r->Z, $r->Y);
1352 $r->Z = self::fe_sub($t0, $r->T);
1353 $r->T = self::fe_add($t0, $r->T);
1354
1355 return $r;
1356 }
1357
1358 /**
1359 * @internal You should not use this directly from another application
1360 *
1361 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p
1362 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
1363 */
1364 public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p)
1365 {
1366 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P2();
1367 $r->X = self::fe_mul($p->X, $p->T);
1368 $r->Y = self::fe_mul($p->Y, $p->Z);
1369 $r->Z = self::fe_mul($p->Z, $p->T);
1370 return $r;
1371 }
1372
1373 /**
1374 * @internal You should not use this directly from another application
1375 *
1376 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p
1377 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
1378 */
1379 public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p)
1380 {
1381 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();
1382 $r->X = self::fe_mul($p->X, $p->T);
1383 $r->Y = self::fe_mul($p->Y, $p->Z);
1384 $r->Z = self::fe_mul($p->Z, $p->T);
1385 $r->T = self::fe_mul($p->X, $p->Y);
1386 return $r;
1387 }
1388
1389 /**
1390 * @internal You should not use this directly from another application
1391 *
1392 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
1393 */
1394 public static function ge_p2_0()
1395 {
1396 return new ParagonIE_Sodium_Core_Curve25519_Ge_P2(
1397 self::fe_0(),
1398 self::fe_1(),
1399 self::fe_1()
1400 );
1401 }
1402
1403 /**
1404 * @internal You should not use this directly from another application
1405 *
1406 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p
1407 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
1408 */
1409 public static function ge_p2_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p)
1410 {
1411 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
1412
1413 $r->X = self::fe_sq($p->X);
1414 $r->Z = self::fe_sq($p->Y);
1415 $r->T = self::fe_sq2($p->Z);
1416 $r->Y = self::fe_add($p->X, $p->Y);
1417 $t0 = self::fe_sq($r->Y);
1418 $r->Y = self::fe_add($r->Z, $r->X);
1419 $r->Z = self::fe_sub($r->Z, $r->X);
1420 $r->X = self::fe_sub($t0, $r->Y);
1421 $r->T = self::fe_sub($r->T, $r->Z);
1422
1423 return $r;
1424 }
1425
1426 /**
1427 * @internal You should not use this directly from another application
1428 *
1429 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
1430 */
1431 public static function ge_p3_0()
1432 {
1433 return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
1434 self::fe_0(),
1435 self::fe_1(),
1436 self::fe_1(),
1437 self::fe_0()
1438 );
1439 }
1440
1441 /**
1442 * @internal You should not use this directly from another application
1443 *
1444 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1445 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached
1446 */
1447 public static function ge_p3_to_cached(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
1448 {
1449 static $d2 = null;
1450 if ($d2 === null) {
1451 $d2 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d2);
1452 }
1453 /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d2 */
1454 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached();
1455 $r->YplusX = self::fe_add($p->Y, $p->X);
1456 $r->YminusX = self::fe_sub($p->Y, $p->X);
1457 $r->Z = self::fe_copy($p->Z);
1458 $r->T2d = self::fe_mul($p->T, $d2);
1459 return $r;
1460 }
1461
1462 /**
1463 * @internal You should not use this directly from another application
1464 *
1465 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1466 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
1467 */
1468 public static function ge_p3_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
1469 {
1470 return new ParagonIE_Sodium_Core_Curve25519_Ge_P2(
1471 self::fe_copy($p->X),
1472 self::fe_copy($p->Y),
1473 self::fe_copy($p->Z)
1474 );
1475 }
1476
1477 /**
1478 * @internal You should not use this directly from another application
1479 *
1480 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
1481 * @return string
1482 * @throws SodiumException
1483 * @throws TypeError
1484 */
1485 public static function ge_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
1486 {
1487 $recip = self::fe_invert($h->Z);
1488 $x = self::fe_mul($h->X, $recip);
1489 $y = self::fe_mul($h->Y, $recip);
1490 $s = self::fe_tobytes($y);
1491 $s[31] = self::intToChr(
1492 self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
1493 );
1494 return $s;
1495 }
1496
1497 /**
1498 * @internal You should not use this directly from another application
1499 *
1500 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1501 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
1502 */
1503 public static function ge_p3_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
1504 {
1505 $q = self::ge_p3_to_p2($p);
1506 return self::ge_p2_dbl($q);
1507 }
1508
1509 /**
1510 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
1511 */
1512 public static function ge_precomp_0()
1513 {
1514 return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
1515 self::fe_1(),
1516 self::fe_1(),
1517 self::fe_0()
1518 );
1519 }
1520
1521 /**
1522 * @internal You should not use this directly from another application
1523 *
1524 * @param int $b
1525 * @param int $c
1526 * @return int
1527 */
1528 public static function equal($b, $c)
1529 {
1530 return (int) ((($b ^ $c) - 1) >> 31) & 1;
1531 }
1532
1533 /**
1534 * @internal You should not use this directly from another application
1535 *
1536 * @param int|string $char
1537 * @return int (1 = yes, 0 = no)
1538 * @throws SodiumException
1539 * @throws TypeError
1540 */
1541 public static function negative($char)
1542 {
1543 if (is_int($char)) {
1544 return ($char >> 63) & 1;
1545 }
1546 $x = self::chrToInt(self::substr($char, 0, 1));
1547 return (int) ($x >> 63);
1548 }
1549
1550 /**
1551 * Conditional move
1552 *
1553 * @internal You should not use this directly from another application
1554 *
1555 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t
1556 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u
1557 * @param int $b
1558 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
1559 */
1560 public static function cmov(
1561 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t,
1562 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u,
1563 $b
1564 ) {
1565 if (!is_int($b)) {
1566 throw new InvalidArgumentException('Expected an integer.');
1567 }
1568 return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
1569 self::fe_cmov($t->yplusx, $u->yplusx, $b),
1570 self::fe_cmov($t->yminusx, $u->yminusx, $b),
1571 self::fe_cmov($t->xy2d, $u->xy2d, $b)
1572 );
1573 }
1574
1575 /**
1576 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t
1577 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u
1578 * @param int $b
1579 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached
1580 */
1581 public static function ge_cmov_cached(
1582 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t,
1583 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u,
1584 $b
1585 ) {
1586 $b &= 1;
1587 $ret = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached();
1588 $ret->YplusX = self::fe_cmov($t->YplusX, $u->YplusX, $b);
1589 $ret->YminusX = self::fe_cmov($t->YminusX, $u->YminusX, $b);
1590 $ret->Z = self::fe_cmov($t->Z, $u->Z, $b);
1591 $ret->T2d = self::fe_cmov($t->T2d, $u->T2d, $b);
1592 return $ret;
1593 }
1594
1595 /**
1596 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $cached
1597 * @param int $b
1598 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached
1599 * @throws SodiumException
1600 */
1601 public static function ge_cmov8_cached(array $cached, $b)
1602 {
1603 // const unsigned char bnegative = negative(b);
1604 // const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1));
1605 $bnegative = self::negative($b);
1606 $babs = $b - (((-$bnegative) & $b) << 1);
1607
1608 // ge25519_cached_0(t);
1609 $t = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(
1610 self::fe_1(),
1611 self::fe_1(),
1612 self::fe_1(),
1613 self::fe_0()
1614 );
1615
1616 // ge25519_cmov_cached(t, &cached[0], equal(babs, 1));
1617 // ge25519_cmov_cached(t, &cached[1], equal(babs, 2));
1618 // ge25519_cmov_cached(t, &cached[2], equal(babs, 3));
1619 // ge25519_cmov_cached(t, &cached[3], equal(babs, 4));
1620 // ge25519_cmov_cached(t, &cached[4], equal(babs, 5));
1621 // ge25519_cmov_cached(t, &cached[5], equal(babs, 6));
1622 // ge25519_cmov_cached(t, &cached[6], equal(babs, 7));
1623 // ge25519_cmov_cached(t, &cached[7], equal(babs, 8));
1624 for ($x = 0; $x < 8; ++$x) {
1625 $t = self::ge_cmov_cached($t, $cached[$x], self::equal($babs, $x + 1));
1626 }
1627
1628 // fe25519_copy(minust.YplusX, t->YminusX);
1629 // fe25519_copy(minust.YminusX, t->YplusX);
1630 // fe25519_copy(minust.Z, t->Z);
1631 // fe25519_neg(minust.T2d, t->T2d);
1632 $minust = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(
1633 self::fe_copy($t->YminusX),
1634 self::fe_copy($t->YplusX),
1635 self::fe_copy($t->Z),
1636 self::fe_neg($t->T2d)
1637 );
1638 return self::ge_cmov_cached($t, $minust, $bnegative);
1639 }
1640
1641 /**
1642 * @internal You should not use this directly from another application
1643 *
1644 * @param int $pos
1645 * @param int $b
1646 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
1647 * @throws SodiumException
1648 * @throws TypeError
1649 * @psalm-suppress MixedArgument
1650 * @psalm-suppress MixedArrayAccess
1651 * @psalm-suppress MixedArrayOffset
1652 */
1653 public static function ge_select($pos = 0, $b = 0)
1654 {
1655 static $base = null;
1656 if ($base === null) {
1657 $base = array();
1658 /** @var int $i */
1659 foreach (self::$base as $i => $bas) {
1660 for ($j = 0; $j < 8; ++$j) {
1661 $base[$i][$j] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
1662 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][0]),
1663 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][1]),
1664 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][2])
1665 );
1666 }
1667 }
1668 }
1669 /** @var array<int, array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp>> $base */
1670 if (!is_int($pos)) {
1671 throw new InvalidArgumentException('Position must be an integer');
1672 }
1673 if ($pos < 0 || $pos > 31) {
1674 throw new RangeException('Position is out of range [0, 31]');
1675 }
1676
1677 $bnegative = self::negative($b);
1678 $babs = $b - (((-$bnegative) & $b) << 1);
1679
1680 $t = self::ge_precomp_0();
1681 for ($i = 0; $i < 8; ++$i) {
1682 $t = self::cmov(
1683 $t,
1684 $base[$pos][$i],
1685 self::equal($babs, $i + 1)
1686 );
1687 }
1688 $minusT = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
1689 self::fe_copy($t->yminusx),
1690 self::fe_copy($t->yplusx),
1691 self::fe_neg($t->xy2d)
1692 );
1693 return self::cmov($t, $minusT, $bnegative);
1694 }
1695
1696 /**
1697 * Subtract two group elements.
1698 *
1699 * r = p - q
1700 *
1701 * @internal You should not use this directly from another application
1702 *
1703 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1704 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
1705 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
1706 */
1707 public static function ge_sub(
1708 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
1709 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
1710 ) {
1711 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
1712
1713 $r->X = self::fe_add($p->Y, $p->X);
1714 $r->Y = self::fe_sub($p->Y, $p->X);
1715 $r->Z = self::fe_mul($r->X, $q->YminusX);
1716 $r->Y = self::fe_mul($r->Y, $q->YplusX);
1717 $r->T = self::fe_mul($q->T2d, $p->T);
1718 $r->X = self::fe_mul($p->Z, $q->Z);
1719 $t0 = self::fe_add($r->X, $r->X);
1720 $r->X = self::fe_sub($r->Z, $r->Y);
1721 $r->Y = self::fe_add($r->Z, $r->Y);
1722 $r->Z = self::fe_sub($t0, $r->T);
1723 $r->T = self::fe_add($t0, $r->T);
1724
1725 return $r;
1726 }
1727
1728 /**
1729 * Convert a group element to a byte string.
1730 *
1731 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h
1732 * @return string
1733 * @throws SodiumException
1734 * @throws TypeError
1735 */
1736 public static function ge_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h)
1737 {
1738 $recip = self::fe_invert($h->Z);
1739 $x = self::fe_mul($h->X, $recip);
1740 $y = self::fe_mul($h->Y, $recip);
1741 $s = self::fe_tobytes($y);
1742 $s[31] = self::intToChr(
1743 self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
1744 );
1745 return $s;
1746 }
1747
1748 /**
1749 * @internal You should not use this directly from another application
1750 *
1751 * @param string $a
1752 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A
1753 * @param string $b
1754 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
1755 * @throws SodiumException
1756 * @throws TypeError
1757 * @psalm-suppress MixedArgument
1758 * @psalm-suppress MixedArrayAccess
1759 */
1760 public static function ge_double_scalarmult_vartime(
1761 $a,
1762 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A,
1763 $b
1764 ) {
1765 /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai */
1766 $Ai = array();
1767
1768 /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp> $Bi */
1769 static $Bi = array();
1770 if (!$Bi) {
1771 for ($i = 0; $i < 8; ++$i) {
1772 $Bi[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
1773 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][0]),
1774 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][1]),
1775 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][2])
1776 );
1777 }
1778 }
1779 for ($i = 0; $i < 8; ++$i) {
1780 $Ai[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(
1781 self::fe_0(),
1782 self::fe_0(),
1783 self::fe_0(),
1784 self::fe_0()
1785 );
1786 }
1787
1788 # slide(aslide,a);
1789 # slide(bslide,b);
1790 /** @var array<int, int> $aslide */
1791 $aslide = self::slide($a);
1792 /** @var array<int, int> $bslide */
1793 $bslide = self::slide($b);
1794
1795 # ge_p3_to_cached(&Ai[0],A);
1796 # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
1797 $Ai[0] = self::ge_p3_to_cached($A);
1798 $t = self::ge_p3_dbl($A);
1799 $A2 = self::ge_p1p1_to_p3($t);
1800
1801 # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
1802 # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
1803 # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
1804 # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
1805 # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
1806 # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
1807 # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
1808 for ($i = 0; $i < 7; ++$i) {
1809 $t = self::ge_add($A2, $Ai[$i]);
1810 $u = self::ge_p1p1_to_p3($t);
1811 $Ai[$i + 1] = self::ge_p3_to_cached($u);
1812 }
1813
1814 # ge_p2_0(r);
1815 $r = self::ge_p2_0();
1816
1817 # for (i = 255;i >= 0;--i) {
1818 # if (aslide[i] || bslide[i]) break;
1819 # }
1820 $i = 255;
1821 for (; $i >= 0; --$i) {
1822 if ($aslide[$i] || $bslide[$i]) {
1823 break;
1824 }
1825 }
1826
1827 # for (;i >= 0;--i) {
1828 for (; $i >= 0; --$i) {
1829 # ge_p2_dbl(&t,r);
1830 $t = self::ge_p2_dbl($r);
1831
1832 # if (aslide[i] > 0) {
1833 if ($aslide[$i] > 0) {
1834 # ge_p1p1_to_p3(&u,&t);
1835 # ge_add(&t,&u,&Ai[aslide[i]/2]);
1836 $u = self::ge_p1p1_to_p3($t);
1837 $t = self::ge_add(
1838 $u,
1839 $Ai[(int) floor($aslide[$i] / 2)]
1840 );
1841 # } else if (aslide[i] < 0) {
1842 } elseif ($aslide[$i] < 0) {
1843 # ge_p1p1_to_p3(&u,&t);
1844 # ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
1845 $u = self::ge_p1p1_to_p3($t);
1846 $t = self::ge_sub(
1847 $u,
1848 $Ai[(int) floor(-$aslide[$i] / 2)]
1849 );
1850 }
1851
1852 # if (bslide[i] > 0) {
1853 if ($bslide[$i] > 0) {
1854 /** @var int $index */
1855 $index = (int) floor($bslide[$i] / 2);
1856 # ge_p1p1_to_p3(&u,&t);
1857 # ge_madd(&t,&u,&Bi[bslide[i]/2]);
1858 $u = self::ge_p1p1_to_p3($t);
1859 $t = self::ge_madd($t, $u, $Bi[$index]);
1860 # } else if (bslide[i] < 0) {
1861 } elseif ($bslide[$i] < 0) {
1862 /** @var int $index */
1863 $index = (int) floor(-$bslide[$i] / 2);
1864 # ge_p1p1_to_p3(&u,&t);
1865 # ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
1866 $u = self::ge_p1p1_to_p3($t);
1867 $t = self::ge_msub($t, $u, $Bi[$index]);
1868 }
1869 # ge_p1p1_to_p2(r,&t);
1870 $r = self::ge_p1p1_to_p2($t);
1871 }
1872 return $r;
1873 }
1874
1875 /**
1876 * @internal You should not use this directly from another application
1877 *
1878 * @param string $a
1879 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
1880 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
1881 * @throws SodiumException
1882 * @throws TypeError
1883 * @psalm-suppress MixedAssignment
1884 * @psalm-suppress MixedOperand
1885 */
1886 public static function ge_scalarmult($a, $p)
1887 {
1888 $e = array_fill(0, 64, 0);
1889
1890 /** @var ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $pi */
1891 $pi = array();
1892
1893 // ge25519_p3_to_cached(&pi[1 - 1], p); /* p */
1894 $pi[0] = self::ge_p3_to_cached($p);
1895
1896 // ge25519_p3_dbl(&t2, p);
1897 // ge25519_p1p1_to_p3(&p2, &t2);
1898 // ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */
1899 $t2 = self::ge_p3_dbl($p);
1900 $p2 = self::ge_p1p1_to_p3($t2);
1901 $pi[1] = self::ge_p3_to_cached($p2);
1902
1903 // ge25519_add_cached(&t3, p, &pi[2 - 1]);
1904 // ge25519_p1p1_to_p3(&p3, &t3);
1905 // ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */
1906 $t3 = self::ge_add($p, $pi[1]);
1907 $p3 = self::ge_p1p1_to_p3($t3);
1908 $pi[2] = self::ge_p3_to_cached($p3);
1909
1910 // ge25519_p3_dbl(&t4, &p2);
1911 // ge25519_p1p1_to_p3(&p4, &t4);
1912 // ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */
1913 $t4 = self::ge_p3_dbl($p2);
1914 $p4 = self::ge_p1p1_to_p3($t4);
1915 $pi[3] = self::ge_p3_to_cached($p4);
1916
1917 // ge25519_add_cached(&t5, p, &pi[4 - 1]);
1918 // ge25519_p1p1_to_p3(&p5, &t5);
1919 // ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */
1920 $t5 = self::ge_add($p, $pi[3]);
1921 $p5 = self::ge_p1p1_to_p3($t5);
1922 $pi[4] = self::ge_p3_to_cached($p5);
1923
1924 // ge25519_p3_dbl(&t6, &p3);
1925 // ge25519_p1p1_to_p3(&p6, &t6);
1926 // ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */
1927 $t6 = self::ge_p3_dbl($p3);
1928 $p6 = self::ge_p1p1_to_p3($t6);
1929 $pi[5] = self::ge_p3_to_cached($p6);
1930
1931 // ge25519_add_cached(&t7, p, &pi[6 - 1]);
1932 // ge25519_p1p1_to_p3(&p7, &t7);
1933 // ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */
1934 $t7 = self::ge_add($p, $pi[5]);
1935 $p7 = self::ge_p1p1_to_p3($t7);
1936 $pi[6] = self::ge_p3_to_cached($p7);
1937
1938 // ge25519_p3_dbl(&t8, &p4);
1939 // ge25519_p1p1_to_p3(&p8, &t8);
1940 // ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */
1941 $t8 = self::ge_p3_dbl($p4);
1942 $p8 = self::ge_p1p1_to_p3($t8);
1943 $pi[7] = self::ge_p3_to_cached($p8);
1944
1945
1946 // for (i = 0; i < 32; ++i) {
1947 // e[2 * i + 0] = (a[i] >> 0) & 15;
1948 // e[2 * i + 1] = (a[i] >> 4) & 15;
1949 // }
1950 for ($i = 0; $i < 32; ++$i) {
1951 $e[($i << 1) ] = self::chrToInt($a[$i]) & 15;
1952 $e[($i << 1) + 1] = (self::chrToInt($a[$i]) >> 4) & 15;
1953 }
1954 // /* each e[i] is between 0 and 15 */
1955 // /* e[63] is between 0 and 7 */
1956
1957 // carry = 0;
1958 // for (i = 0; i < 63; ++i) {
1959 // e[i] += carry;
1960 // carry = e[i] + 8;
1961 // carry >>= 4;
1962 // e[i] -= carry * ((signed char) 1 << 4);
1963 // }
1964 $carry = 0;
1965 for ($i = 0; $i < 63; ++$i) {
1966 $e[$i] += $carry;
1967 $carry = $e[$i] + 8;
1968 $carry >>= 4;
1969 $e[$i] -= $carry << 4;
1970 }
1971 // e[63] += carry;
1972 // /* each e[i] is between -8 and 8 */
1973 $e[63] += $carry;
1974
1975 // ge25519_p3_0(h);
1976 $h = self::ge_p3_0();
1977
1978 // for (i = 63; i != 0; i--) {
1979 for ($i = 63; $i != 0; --$i) {
1980 // ge25519_cmov8_cached(&t, pi, e[i]);
1981 $t = self::ge_cmov8_cached($pi, $e[$i]);
1982 // ge25519_add_cached(&r, h, &t);
1983 $r = self::ge_add($h, $t);
1984
1985 // ge25519_p1p1_to_p2(&s, &r);
1986 // ge25519_p2_dbl(&r, &s);
1987 // ge25519_p1p1_to_p2(&s, &r);
1988 // ge25519_p2_dbl(&r, &s);
1989 // ge25519_p1p1_to_p2(&s, &r);
1990 // ge25519_p2_dbl(&r, &s);
1991 // ge25519_p1p1_to_p2(&s, &r);
1992 // ge25519_p2_dbl(&r, &s);
1993 $s = self::ge_p1p1_to_p2($r);
1994 $r = self::ge_p2_dbl($s);
1995 $s = self::ge_p1p1_to_p2($r);
1996 $r = self::ge_p2_dbl($s);
1997 $s = self::ge_p1p1_to_p2($r);
1998 $r = self::ge_p2_dbl($s);
1999 $s = self::ge_p1p1_to_p2($r);
2000 $r = self::ge_p2_dbl($s);
2001
2002 // ge25519_p1p1_to_p3(h, &r); /* *16 */
2003 $h = self::ge_p1p1_to_p3($r); /* *16 */
2004 }
2005
2006 // ge25519_cmov8_cached(&t, pi, e[i]);
2007 // ge25519_add_cached(&r, h, &t);
2008 // ge25519_p1p1_to_p3(h, &r);
2009 $t = self::ge_cmov8_cached($pi, $e[0]);
2010 $r = self::ge_add($h, $t);
2011 return self::ge_p1p1_to_p3($r);
2012 }
2013
2014 /**
2015 * @internal You should not use this directly from another application
2016 *
2017 * @param string $a
2018 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
2019 * @throws SodiumException
2020 * @throws TypeError
2021 * @psalm-suppress MixedAssignment
2022 * @psalm-suppress MixedOperand
2023 */
2024 public static function ge_scalarmult_base($a)
2025 {
2026 /** @var array<int, int> $e */
2027 $e = array();
2028 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
2029
2030 for ($i = 0; $i < 32; ++$i) {
2031 $dbl = (int) $i << 1;
2032 $e[$dbl] = (int) self::chrToInt($a[$i]) & 15;
2033 $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15;
2034 }
2035
2036 $carry = 0;
2037 for ($i = 0; $i < 63; ++$i) {
2038 $e[$i] += $carry;
2039 $carry = $e[$i] + 8;
2040 $carry >>= 4;
2041 $e[$i] -= $carry << 4;
2042 }
2043 $e[63] += (int) $carry;
2044
2045 $h = self::ge_p3_0();
2046
2047 for ($i = 1; $i < 64; $i += 2) {
2048 $t = self::ge_select((int) floor($i / 2), (int) $e[$i]);
2049 $r = self::ge_madd($r, $h, $t);
2050 $h = self::ge_p1p1_to_p3($r);
2051 }
2052
2053 $r = self::ge_p3_dbl($h);
2054
2055 $s = self::ge_p1p1_to_p2($r);
2056 $r = self::ge_p2_dbl($s);
2057 $s = self::ge_p1p1_to_p2($r);
2058 $r = self::ge_p2_dbl($s);
2059 $s = self::ge_p1p1_to_p2($r);
2060 $r = self::ge_p2_dbl($s);
2061
2062 $h = self::ge_p1p1_to_p3($r);
2063
2064 for ($i = 0; $i < 64; $i += 2) {
2065 $t = self::ge_select($i >> 1, (int) $e[$i]);
2066 $r = self::ge_madd($r, $h, $t);
2067 $h = self::ge_p1p1_to_p3($r);
2068 }
2069 return $h;
2070 }
2071
2072 /**
2073 * Calculates (ab + c) mod l
2074 * where l = 2^252 + 27742317777372353535851937790883648493
2075 *
2076 * @internal You should not use this directly from another application
2077 *
2078 * @param string $a
2079 * @param string $b
2080 * @param string $c
2081 * @return string
2082 * @throws TypeError
2083 */
2084 public static function sc_muladd($a, $b, $c)
2085 {
2086 $a0 = 2097151 & self::load_3(self::substr($a, 0, 3));
2087 $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5);
2088 $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2);
2089 $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7);
2090 $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4);
2091 $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1);
2092 $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6);
2093 $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3);
2094 $a8 = 2097151 & self::load_3(self::substr($a, 21, 3));
2095 $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5);
2096 $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2);
2097 $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7);
2098
2099 $b0 = 2097151 & self::load_3(self::substr($b, 0, 3));
2100 $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5);
2101 $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2);
2102 $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7);
2103 $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4);
2104 $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1);
2105 $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6);
2106 $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3);
2107 $b8 = 2097151 & self::load_3(self::substr($b, 21, 3));
2108 $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5);
2109 $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2);
2110 $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7);
2111
2112 $c0 = 2097151 & self::load_3(self::substr($c, 0, 3));
2113 $c1 = 2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5);
2114 $c2 = 2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2);
2115 $c3 = 2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7);
2116 $c4 = 2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4);
2117 $c5 = 2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1);
2118 $c6 = 2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6);
2119 $c7 = 2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3);
2120 $c8 = 2097151 & self::load_3(self::substr($c, 21, 3));
2121 $c9 = 2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5);
2122 $c10 = 2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2);
2123 $c11 = (self::load_4(self::substr($c, 28, 4)) >> 7);
2124
2125 /* Can't really avoid the pyramid here: */
2126 $s0 = $c0 + self::mul($a0, $b0, 24);
2127 $s1 = $c1 + self::mul($a0, $b1, 24) + self::mul($a1, $b0, 24);
2128 $s2 = $c2 + self::mul($a0, $b2, 24) + self::mul($a1, $b1, 24) + self::mul($a2, $b0, 24);
2129 $s3 = $c3 + self::mul($a0, $b3, 24) + self::mul($a1, $b2, 24) + self::mul($a2, $b1, 24) + self::mul($a3, $b0, 24);
2130 $s4 = $c4 + self::mul($a0, $b4, 24) + self::mul($a1, $b3, 24) + self::mul($a2, $b2, 24) + self::mul($a3, $b1, 24) +
2131 self::mul($a4, $b0, 24);
2132 $s5 = $c5 + self::mul($a0, $b5, 24) + self::mul($a1, $b4, 24) + self::mul($a2, $b3, 24) + self::mul($a3, $b2, 24) +
2133 self::mul($a4, $b1, 24) + self::mul($a5, $b0, 24);
2134 $s6 = $c6 + self::mul($a0, $b6, 24) + self::mul($a1, $b5, 24) + self::mul($a2, $b4, 24) + self::mul($a3, $b3, 24) +
2135 self::mul($a4, $b2, 24) + self::mul($a5, $b1, 24) + self::mul($a6, $b0, 24);
2136 $s7 = $c7 + self::mul($a0, $b7, 24) + self::mul($a1, $b6, 24) + self::mul($a2, $b5, 24) + self::mul($a3, $b4, 24) +
2137 self::mul($a4, $b3, 24) + self::mul($a5, $b2, 24) + self::mul($a6, $b1, 24) + self::mul($a7, $b0, 24);
2138 $s8 = $c8 + self::mul($a0, $b8, 24) + self::mul($a1, $b7, 24) + self::mul($a2, $b6, 24) + self::mul($a3, $b5, 24) +
2139 self::mul($a4, $b4, 24) + self::mul($a5, $b3, 24) + self::mul($a6, $b2, 24) + self::mul($a7, $b1, 24) +
2140 self::mul($a8, $b0, 24);
2141 $s9 = $c9 + self::mul($a0, $b9, 24) + self::mul($a1, $b8, 24) + self::mul($a2, $b7, 24) + self::mul($a3, $b6, 24) +
2142 self::mul($a4, $b5, 24) + self::mul($a5, $b4, 24) + self::mul($a6, $b3, 24) + self::mul($a7, $b2, 24) +
2143 self::mul($a8, $b1, 24) + self::mul($a9, $b0, 24);
2144 $s10 = $c10 + self::mul($a0, $b10, 24) + self::mul($a1, $b9, 24) + self::mul($a2, $b8, 24) + self::mul($a3, $b7, 24) +
2145 self::mul($a4, $b6, 24) + self::mul($a5, $b5, 24) + self::mul($a6, $b4, 24) + self::mul($a7, $b3, 24) +
2146 self::mul($a8, $b2, 24) + self::mul($a9, $b1, 24) + self::mul($a10, $b0, 24);
2147 $s11 = $c11 + self::mul($a0, $b11, 24) + self::mul($a1, $b10, 24) + self::mul($a2, $b9, 24) + self::mul($a3, $b8, 24) +
2148 self::mul($a4, $b7, 24) + self::mul($a5, $b6, 24) + self::mul($a6, $b5, 24) + self::mul($a7, $b4, 24) +
2149 self::mul($a8, $b3, 24) + self::mul($a9, $b2, 24) + self::mul($a10, $b1, 24) + self::mul($a11, $b0, 24);
2150 $s12 = self::mul($a1, $b11, 24) + self::mul($a2, $b10, 24) + self::mul($a3, $b9, 24) + self::mul($a4, $b8, 24) +
2151 self::mul($a5, $b7, 24) + self::mul($a6, $b6, 24) + self::mul($a7, $b5, 24) + self::mul($a8, $b4, 24) +
2152 self::mul($a9, $b3, 24) + self::mul($a10, $b2, 24) + self::mul($a11, $b1, 24);
2153 $s13 = self::mul($a2, $b11, 24) + self::mul($a3, $b10, 24) + self::mul($a4, $b9, 24) + self::mul($a5, $b8, 24) +
2154 self::mul($a6, $b7, 24) + self::mul($a7, $b6, 24) + self::mul($a8, $b5, 24) + self::mul($a9, $b4, 24) +
2155 self::mul($a10, $b3, 24) + self::mul($a11, $b2, 24);
2156 $s14 = self::mul($a3, $b11, 24) + self::mul($a4, $b10, 24) + self::mul($a5, $b9, 24) + self::mul($a6, $b8, 24) +
2157 self::mul($a7, $b7, 24) + self::mul($a8, $b6, 24) + self::mul($a9, $b5, 24) + self::mul($a10, $b4, 24) +
2158 self::mul($a11, $b3, 24);
2159 $s15 = self::mul($a4, $b11, 24) + self::mul($a5, $b10, 24) + self::mul($a6, $b9, 24) + self::mul($a7, $b8, 24) +
2160 self::mul($a8, $b7, 24) + self::mul($a9, $b6, 24) + self::mul($a10, $b5, 24) + self::mul($a11, $b4, 24);
2161 $s16 = self::mul($a5, $b11, 24) + self::mul($a6, $b10, 24) + self::mul($a7, $b9, 24) + self::mul($a8, $b8, 24) +
2162 self::mul($a9, $b7, 24) + self::mul($a10, $b6, 24) + self::mul($a11, $b5, 24);
2163 $s17 = self::mul($a6, $b11, 24) + self::mul($a7, $b10, 24) + self::mul($a8, $b9, 24) + self::mul($a9, $b8, 24) +
2164 self::mul($a10, $b7, 24) + self::mul($a11, $b6, 24);
2165 $s18 = self::mul($a7, $b11, 24) + self::mul($a8, $b10, 24) + self::mul($a9, $b9, 24) + self::mul($a10, $b8, 24) +
2166 self::mul($a11, $b7, 24);
2167 $s19 = self::mul($a8, $b11, 24) + self::mul($a9, $b10, 24) + self::mul($a10, $b9, 24) + self::mul($a11, $b8, 24);
2168 $s20 = self::mul($a9, $b11, 24) + self::mul($a10, $b10, 24) + self::mul($a11, $b9, 24);
2169 $s21 = self::mul($a10, $b11, 24) + self::mul($a11, $b10, 24);
2170 $s22 = self::mul($a11, $b11, 24);
2171 $s23 = 0;
2172
2173 $carry0 = ($s0 + (1 << 20)) >> 21;
2174 $s1 += $carry0;
2175 $s0 -= $carry0 << 21;
2176 $carry2 = ($s2 + (1 << 20)) >> 21;
2177 $s3 += $carry2;
2178 $s2 -= $carry2 << 21;
2179 $carry4 = ($s4 + (1 << 20)) >> 21;
2180 $s5 += $carry4;
2181 $s4 -= $carry4 << 21;
2182 $carry6 = ($s6 + (1 << 20)) >> 21;
2183 $s7 += $carry6;
2184 $s6 -= $carry6 << 21;
2185 $carry8 = ($s8 + (1 << 20)) >> 21;
2186 $s9 += $carry8;
2187 $s8 -= $carry8 << 21;
2188 $carry10 = ($s10 + (1 << 20)) >> 21;
2189 $s11 += $carry10;
2190 $s10 -= $carry10 << 21;
2191 $carry12 = ($s12 + (1 << 20)) >> 21;
2192 $s13 += $carry12;
2193 $s12 -= $carry12 << 21;
2194 $carry14 = ($s14 + (1 << 20)) >> 21;
2195 $s15 += $carry14;
2196 $s14 -= $carry14 << 21;
2197 $carry16 = ($s16 + (1 << 20)) >> 21;
2198 $s17 += $carry16;
2199 $s16 -= $carry16 << 21;
2200 $carry18 = ($s18 + (1 << 20)) >> 21;
2201 $s19 += $carry18;
2202 $s18 -= $carry18 << 21;
2203 $carry20 = ($s20 + (1 << 20)) >> 21;
2204 $s21 += $carry20;
2205 $s20 -= $carry20 << 21;
2206 $carry22 = ($s22 + (1 << 20)) >> 21;
2207 $s23 += $carry22;
2208 $s22 -= $carry22 << 21;
2209
2210 $carry1 = ($s1 + (1 << 20)) >> 21;
2211 $s2 += $carry1;
2212 $s1 -= $carry1 << 21;
2213 $carry3 = ($s3 + (1 << 20)) >> 21;
2214 $s4 += $carry3;
2215 $s3 -= $carry3 << 21;
2216 $carry5 = ($s5 + (1 << 20)) >> 21;
2217 $s6 += $carry5;
2218 $s5 -= $carry5 << 21;
2219 $carry7 = ($s7 + (1 << 20)) >> 21;
2220 $s8 += $carry7;
2221 $s7 -= $carry7 << 21;
2222 $carry9 = ($s9 + (1 << 20)) >> 21;
2223 $s10 += $carry9;
2224 $s9 -= $carry9 << 21;
2225 $carry11 = ($s11 + (1 << 20)) >> 21;
2226 $s12 += $carry11;
2227 $s11 -= $carry11 << 21;
2228 $carry13 = ($s13 + (1 << 20)) >> 21;
2229 $s14 += $carry13;
2230 $s13 -= $carry13 << 21;
2231 $carry15 = ($s15 + (1 << 20)) >> 21;
2232 $s16 += $carry15;
2233 $s15 -= $carry15 << 21;
2234 $carry17 = ($s17 + (1 << 20)) >> 21;
2235 $s18 += $carry17;
2236 $s17 -= $carry17 << 21;
2237 $carry19 = ($s19 + (1 << 20)) >> 21;
2238 $s20 += $carry19;
2239 $s19 -= $carry19 << 21;
2240 $carry21 = ($s21 + (1 << 20)) >> 21;
2241 $s22 += $carry21;
2242 $s21 -= $carry21 << 21;
2243
2244 $s11 += self::mul($s23, 666643, 20);
2245 $s12 += self::mul($s23, 470296, 19);
2246 $s13 += self::mul($s23, 654183, 20);
2247 $s14 -= self::mul($s23, 997805, 20);
2248 $s15 += self::mul($s23, 136657, 18);
2249 $s16 -= self::mul($s23, 683901, 20);
2250
2251 $s10 += self::mul($s22, 666643, 20);
2252 $s11 += self::mul($s22, 470296, 19);
2253 $s12 += self::mul($s22, 654183, 20);
2254 $s13 -= self::mul($s22, 997805, 20);
2255 $s14 += self::mul($s22, 136657, 18);
2256 $s15 -= self::mul($s22, 683901, 20);
2257
2258 $s9 += self::mul($s21, 666643, 20);
2259 $s10 += self::mul($s21, 470296, 19);
2260 $s11 += self::mul($s21, 654183, 20);
2261 $s12 -= self::mul($s21, 997805, 20);
2262 $s13 += self::mul($s21, 136657, 18);
2263 $s14 -= self::mul($s21, 683901, 20);
2264
2265 $s8 += self::mul($s20, 666643, 20);
2266 $s9 += self::mul($s20, 470296, 19);
2267 $s10 += self::mul($s20, 654183, 20);
2268 $s11 -= self::mul($s20, 997805, 20);
2269 $s12 += self::mul($s20, 136657, 18);
2270 $s13 -= self::mul($s20, 683901, 20);
2271
2272 $s7 += self::mul($s19, 666643, 20);
2273 $s8 += self::mul($s19, 470296, 19);
2274 $s9 += self::mul($s19, 654183, 20);
2275 $s10 -= self::mul($s19, 997805, 20);
2276 $s11 += self::mul($s19, 136657, 18);
2277 $s12 -= self::mul($s19, 683901, 20);
2278
2279 $s6 += self::mul($s18, 666643, 20);
2280 $s7 += self::mul($s18, 470296, 19);
2281 $s8 += self::mul($s18, 654183, 20);
2282 $s9 -= self::mul($s18, 997805, 20);
2283 $s10 += self::mul($s18, 136657, 18);
2284 $s11 -= self::mul($s18, 683901, 20);
2285
2286 $carry6 = ($s6 + (1 << 20)) >> 21;
2287 $s7 += $carry6;
2288 $s6 -= $carry6 << 21;
2289 $carry8 = ($s8 + (1 << 20)) >> 21;
2290 $s9 += $carry8;
2291 $s8 -= $carry8 << 21;
2292 $carry10 = ($s10 + (1 << 20)) >> 21;
2293 $s11 += $carry10;
2294 $s10 -= $carry10 << 21;
2295 $carry12 = ($s12 + (1 << 20)) >> 21;
2296 $s13 += $carry12;
2297 $s12 -= $carry12 << 21;
2298 $carry14 = ($s14 + (1 << 20)) >> 21;
2299 $s15 += $carry14;
2300 $s14 -= $carry14 << 21;
2301 $carry16 = ($s16 + (1 << 20)) >> 21;
2302 $s17 += $carry16;
2303 $s16 -= $carry16 << 21;
2304
2305 $carry7 = ($s7 + (1 << 20)) >> 21;
2306 $s8 += $carry7;
2307 $s7 -= $carry7 << 21;
2308 $carry9 = ($s9 + (1 << 20)) >> 21;
2309 $s10 += $carry9;
2310 $s9 -= $carry9 << 21;
2311 $carry11 = ($s11 + (1 << 20)) >> 21;
2312 $s12 += $carry11;
2313 $s11 -= $carry11 << 21;
2314 $carry13 = ($s13 + (1 << 20)) >> 21;
2315 $s14 += $carry13;
2316 $s13 -= $carry13 << 21;
2317 $carry15 = ($s15 + (1 << 20)) >> 21;
2318 $s16 += $carry15;
2319 $s15 -= $carry15 << 21;
2320
2321 $s5 += self::mul($s17, 666643, 20);
2322 $s6 += self::mul($s17, 470296, 19);
2323 $s7 += self::mul($s17, 654183, 20);
2324 $s8 -= self::mul($s17, 997805, 20);
2325 $s9 += self::mul($s17, 136657, 18);
2326 $s10 -= self::mul($s17, 683901, 20);
2327
2328 $s4 += self::mul($s16, 666643, 20);
2329 $s5 += self::mul($s16, 470296, 19);
2330 $s6 += self::mul($s16, 654183, 20);
2331 $s7 -= self::mul($s16, 997805, 20);
2332 $s8 += self::mul($s16, 136657, 18);
2333 $s9 -= self::mul($s16, 683901, 20);
2334
2335 $s3 += self::mul($s15, 666643, 20);
2336 $s4 += self::mul($s15, 470296, 19);
2337 $s5 += self::mul($s15, 654183, 20);
2338 $s6 -= self::mul($s15, 997805, 20);
2339 $s7 += self::mul($s15, 136657, 18);
2340 $s8 -= self::mul($s15, 683901, 20);
2341
2342 $s2 += self::mul($s14, 666643, 20);
2343 $s3 += self::mul($s14, 470296, 19);
2344 $s4 += self::mul($s14, 654183, 20);
2345 $s5 -= self::mul($s14, 997805, 20);
2346 $s6 += self::mul($s14, 136657, 18);
2347 $s7 -= self::mul($s14, 683901, 20);
2348
2349 $s1 += self::mul($s13, 666643, 20);
2350 $s2 += self::mul($s13, 470296, 19);
2351 $s3 += self::mul($s13, 654183, 20);
2352 $s4 -= self::mul($s13, 997805, 20);
2353 $s5 += self::mul($s13, 136657, 18);
2354 $s6 -= self::mul($s13, 683901, 20);
2355
2356 $s0 += self::mul($s12, 666643, 20);
2357 $s1 += self::mul($s12, 470296, 19);
2358 $s2 += self::mul($s12, 654183, 20);
2359 $s3 -= self::mul($s12, 997805, 20);
2360 $s4 += self::mul($s12, 136657, 18);
2361 $s5 -= self::mul($s12, 683901, 20);
2362 $s12 = 0;
2363
2364 $carry0 = ($s0 + (1 << 20)) >> 21;
2365 $s1 += $carry0;
2366 $s0 -= $carry0 << 21;
2367 $carry2 = ($s2 + (1 << 20)) >> 21;
2368 $s3 += $carry2;
2369 $s2 -= $carry2 << 21;
2370 $carry4 = ($s4 + (1 << 20)) >> 21;
2371 $s5 += $carry4;
2372 $s4 -= $carry4 << 21;
2373 $carry6 = ($s6 + (1 << 20)) >> 21;
2374 $s7 += $carry6;
2375 $s6 -= $carry6 << 21;
2376 $carry8 = ($s8 + (1 << 20)) >> 21;
2377 $s9 += $carry8;
2378 $s8 -= $carry8 << 21;
2379 $carry10 = ($s10 + (1 << 20)) >> 21;
2380 $s11 += $carry10;
2381 $s10 -= $carry10 << 21;
2382
2383 $carry1 = ($s1 + (1 << 20)) >> 21;
2384 $s2 += $carry1;
2385 $s1 -= $carry1 << 21;
2386 $carry3 = ($s3 + (1 << 20)) >> 21;
2387 $s4 += $carry3;
2388 $s3 -= $carry3 << 21;
2389 $carry5 = ($s5 + (1 << 20)) >> 21;
2390 $s6 += $carry5;
2391 $s5 -= $carry5 << 21;
2392 $carry7 = ($s7 + (1 << 20)) >> 21;
2393 $s8 += $carry7;
2394 $s7 -= $carry7 << 21;
2395 $carry9 = ($s9 + (1 << 20)) >> 21;
2396 $s10 += $carry9;
2397 $s9 -= $carry9 << 21;
2398 $carry11 = ($s11 + (1 << 20)) >> 21;
2399 $s12 += $carry11;
2400 $s11 -= $carry11 << 21;
2401
2402 $s0 += self::mul($s12, 666643, 20);
2403 $s1 += self::mul($s12, 470296, 19);
2404 $s2 += self::mul($s12, 654183, 20);
2405 $s3 -= self::mul($s12, 997805, 20);
2406 $s4 += self::mul($s12, 136657, 18);
2407 $s5 -= self::mul($s12, 683901, 20);
2408 $s12 = 0;
2409
2410 $carry0 = $s0 >> 21;
2411 $s1 += $carry0;
2412 $s0 -= $carry0 << 21;
2413 $carry1 = $s1 >> 21;
2414 $s2 += $carry1;
2415 $s1 -= $carry1 << 21;
2416 $carry2 = $s2 >> 21;
2417 $s3 += $carry2;
2418 $s2 -= $carry2 << 21;
2419 $carry3 = $s3 >> 21;
2420 $s4 += $carry3;
2421 $s3 -= $carry3 << 21;
2422 $carry4 = $s4 >> 21;
2423 $s5 += $carry4;
2424 $s4 -= $carry4 << 21;
2425 $carry5 = $s5 >> 21;
2426 $s6 += $carry5;
2427 $s5 -= $carry5 << 21;
2428 $carry6 = $s6 >> 21;
2429 $s7 += $carry6;
2430 $s6 -= $carry6 << 21;
2431 $carry7 = $s7 >> 21;
2432 $s8 += $carry7;
2433 $s7 -= $carry7 << 21;
2434 $carry8 = $s8 >> 21;
2435 $s9 += $carry8;
2436 $s8 -= $carry8 << 21;
2437 $carry9 = $s9 >> 21;
2438 $s10 += $carry9;
2439 $s9 -= $carry9 << 21;
2440 $carry10 = $s10 >> 21;
2441 $s11 += $carry10;
2442 $s10 -= $carry10 << 21;
2443 $carry11 = $s11 >> 21;
2444 $s12 += $carry11;
2445 $s11 -= $carry11 << 21;
2446
2447 $s0 += self::mul($s12, 666643, 20);
2448 $s1 += self::mul($s12, 470296, 19);
2449 $s2 += self::mul($s12, 654183, 20);
2450 $s3 -= self::mul($s12, 997805, 20);
2451 $s4 += self::mul($s12, 136657, 18);
2452 $s5 -= self::mul($s12, 683901, 20);
2453
2454 $carry0 = $s0 >> 21;
2455 $s1 += $carry0;
2456 $s0 -= $carry0 << 21;
2457 $carry1 = $s1 >> 21;
2458 $s2 += $carry1;
2459 $s1 -= $carry1 << 21;
2460 $carry2 = $s2 >> 21;
2461 $s3 += $carry2;
2462 $s2 -= $carry2 << 21;
2463 $carry3 = $s3 >> 21;
2464 $s4 += $carry3;
2465 $s3 -= $carry3 << 21;
2466 $carry4 = $s4 >> 21;
2467 $s5 += $carry4;
2468 $s4 -= $carry4 << 21;
2469 $carry5 = $s5 >> 21;
2470 $s6 += $carry5;
2471 $s5 -= $carry5 << 21;
2472 $carry6 = $s6 >> 21;
2473 $s7 += $carry6;
2474 $s6 -= $carry6 << 21;
2475 $carry7 = $s7 >> 21;
2476 $s8 += $carry7;
2477 $s7 -= $carry7 << 21;
2478 $carry8 = $s8 >> 21;
2479 $s9 += $carry8;
2480 $s8 -= $carry8 << 21;
2481 $carry9 = $s9 >> 21;
2482 $s10 += $carry9;
2483 $s9 -= $carry9 << 21;
2484 $carry10 = $s10 >> 21;
2485 $s11 += $carry10;
2486 $s10 -= $carry10 << 21;
2487
2488 /**
2489 * @var array<int, int>
2490 */
2491 $arr = array(
2492 (int) (0xff & ($s0 >> 0)),
2493 (int) (0xff & ($s0 >> 8)),
2494 (int) (0xff & (($s0 >> 16) | $s1 << 5)),
2495 (int) (0xff & ($s1 >> 3)),
2496 (int) (0xff & ($s1 >> 11)),
2497 (int) (0xff & (($s1 >> 19) | $s2 << 2)),
2498 (int) (0xff & ($s2 >> 6)),
2499 (int) (0xff & (($s2 >> 14) | $s3 << 7)),
2500 (int) (0xff & ($s3 >> 1)),
2501 (int) (0xff & ($s3 >> 9)),
2502 (int) (0xff & (($s3 >> 17) | $s4 << 4)),
2503 (int) (0xff & ($s4 >> 4)),
2504 (int) (0xff & ($s4 >> 12)),
2505 (int) (0xff & (($s4 >> 20) | $s5 << 1)),
2506 (int) (0xff & ($s5 >> 7)),
2507 (int) (0xff & (($s5 >> 15) | $s6 << 6)),
2508 (int) (0xff & ($s6 >> 2)),
2509 (int) (0xff & ($s6 >> 10)),
2510 (int) (0xff & (($s6 >> 18) | $s7 << 3)),
2511 (int) (0xff & ($s7 >> 5)),
2512 (int) (0xff & ($s7 >> 13)),
2513 (int) (0xff & ($s8 >> 0)),
2514 (int) (0xff & ($s8 >> 8)),
2515 (int) (0xff & (($s8 >> 16) | $s9 << 5)),
2516 (int) (0xff & ($s9 >> 3)),
2517 (int) (0xff & ($s9 >> 11)),
2518 (int) (0xff & (($s9 >> 19) | $s10 << 2)),
2519 (int) (0xff & ($s10 >> 6)),
2520 (int) (0xff & (($s10 >> 14) | $s11 << 7)),
2521 (int) (0xff & ($s11 >> 1)),
2522 (int) (0xff & ($s11 >> 9)),
2523 0xff & ($s11 >> 17)
2524 );
2525 return self::intArrayToString($arr);
2526 }
2527
2528 /**
2529 * @internal You should not use this directly from another application
2530 *
2531 * @param string $s
2532 * @return string
2533 * @throws TypeError
2534 */
2535 public static function sc_reduce($s)
2536 {
2537 $s0 = 2097151 & self::load_3(self::substr($s, 0, 3));
2538 $s1 = 2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5);
2539 $s2 = 2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2);
2540 $s3 = 2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7);
2541 $s4 = 2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4);
2542 $s5 = 2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1);
2543 $s6 = 2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6);
2544 $s7 = 2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3);
2545 $s8 = 2097151 & self::load_3(self::substr($s, 21, 3));
2546 $s9 = 2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5);
2547 $s10 = 2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2);
2548 $s11 = 2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7);
2549 $s12 = 2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4);
2550 $s13 = 2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1);
2551 $s14 = 2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6);
2552 $s15 = 2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3);
2553 $s16 = 2097151 & self::load_3(self::substr($s, 42, 3));
2554 $s17 = 2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5);
2555 $s18 = 2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2);
2556 $s19 = 2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7);
2557 $s20 = 2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4);
2558 $s21 = 2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1);
2559 $s22 = 2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6);
2560 $s23 = 0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3);
2561
2562 $s11 += self::mul($s23, 666643, 20);
2563 $s12 += self::mul($s23, 470296, 19);
2564 $s13 += self::mul($s23, 654183, 20);
2565 $s14 -= self::mul($s23, 997805, 20);
2566 $s15 += self::mul($s23, 136657, 18);
2567 $s16 -= self::mul($s23, 683901, 20);
2568
2569 $s10 += self::mul($s22, 666643, 20);
2570 $s11 += self::mul($s22, 470296, 19);
2571 $s12 += self::mul($s22, 654183, 20);
2572 $s13 -= self::mul($s22, 997805, 20);
2573 $s14 += self::mul($s22, 136657, 18);
2574 $s15 -= self::mul($s22, 683901, 20);
2575
2576 $s9 += self::mul($s21, 666643, 20);
2577 $s10 += self::mul($s21, 470296, 19);
2578 $s11 += self::mul($s21, 654183, 20);
2579 $s12 -= self::mul($s21, 997805, 20);
2580 $s13 += self::mul($s21, 136657, 18);
2581 $s14 -= self::mul($s21, 683901, 20);
2582
2583 $s8 += self::mul($s20, 666643, 20);
2584 $s9 += self::mul($s20, 470296, 19);
2585 $s10 += self::mul($s20, 654183, 20);
2586 $s11 -= self::mul($s20, 997805, 20);
2587 $s12 += self::mul($s20, 136657, 18);
2588 $s13 -= self::mul($s20, 683901, 20);
2589
2590 $s7 += self::mul($s19, 666643, 20);
2591 $s8 += self::mul($s19, 470296, 19);
2592 $s9 += self::mul($s19, 654183, 20);
2593 $s10 -= self::mul($s19, 997805, 20);
2594 $s11 += self::mul($s19, 136657, 18);
2595 $s12 -= self::mul($s19, 683901, 20);
2596
2597 $s6 += self::mul($s18, 666643, 20);
2598 $s7 += self::mul($s18, 470296, 19);
2599 $s8 += self::mul($s18, 654183, 20);
2600 $s9 -= self::mul($s18, 997805, 20);
2601 $s10 += self::mul($s18, 136657, 18);
2602 $s11 -= self::mul($s18, 683901, 20);
2603
2604 $carry6 = ($s6 + (1 << 20)) >> 21;
2605 $s7 += $carry6;
2606 $s6 -= $carry6 << 21;
2607 $carry8 = ($s8 + (1 << 20)) >> 21;
2608 $s9 += $carry8;
2609 $s8 -= $carry8 << 21;
2610 $carry10 = ($s10 + (1 << 20)) >> 21;
2611 $s11 += $carry10;
2612 $s10 -= $carry10 << 21;
2613 $carry12 = ($s12 + (1 << 20)) >> 21;
2614 $s13 += $carry12;
2615 $s12 -= $carry12 << 21;
2616 $carry14 = ($s14 + (1 << 20)) >> 21;
2617 $s15 += $carry14;
2618 $s14 -= $carry14 << 21;
2619 $carry16 = ($s16 + (1 << 20)) >> 21;
2620 $s17 += $carry16;
2621 $s16 -= $carry16 << 21;
2622
2623 $carry7 = ($s7 + (1 << 20)) >> 21;
2624 $s8 += $carry7;
2625 $s7 -= $carry7 << 21;
2626 $carry9 = ($s9 + (1 << 20)) >> 21;
2627 $s10 += $carry9;
2628 $s9 -= $carry9 << 21;
2629 $carry11 = ($s11 + (1 << 20)) >> 21;
2630 $s12 += $carry11;
2631 $s11 -= $carry11 << 21;
2632 $carry13 = ($s13 + (1 << 20)) >> 21;
2633 $s14 += $carry13;
2634 $s13 -= $carry13 << 21;
2635 $carry15 = ($s15 + (1 << 20)) >> 21;
2636 $s16 += $carry15;
2637 $s15 -= $carry15 << 21;
2638
2639 $s5 += self::mul($s17, 666643, 20);
2640 $s6 += self::mul($s17, 470296, 19);
2641 $s7 += self::mul($s17, 654183, 20);
2642 $s8 -= self::mul($s17, 997805, 20);
2643 $s9 += self::mul($s17, 136657, 18);
2644 $s10 -= self::mul($s17, 683901, 20);
2645
2646 $s4 += self::mul($s16, 666643, 20);
2647 $s5 += self::mul($s16, 470296, 19);
2648 $s6 += self::mul($s16, 654183, 20);
2649 $s7 -= self::mul($s16, 997805, 20);
2650 $s8 += self::mul($s16, 136657, 18);
2651 $s9 -= self::mul($s16, 683901, 20);
2652
2653 $s3 += self::mul($s15, 666643, 20);
2654 $s4 += self::mul($s15, 470296, 19);
2655 $s5 += self::mul($s15, 654183, 20);
2656 $s6 -= self::mul($s15, 997805, 20);
2657 $s7 += self::mul($s15, 136657, 18);
2658 $s8 -= self::mul($s15, 683901, 20);
2659
2660 $s2 += self::mul($s14, 666643, 20);
2661 $s3 += self::mul($s14, 470296, 19);
2662 $s4 += self::mul($s14, 654183, 20);
2663 $s5 -= self::mul($s14, 997805, 20);
2664 $s6 += self::mul($s14, 136657, 18);
2665 $s7 -= self::mul($s14, 683901, 20);
2666
2667 $s1 += self::mul($s13, 666643, 20);
2668 $s2 += self::mul($s13, 470296, 19);
2669 $s3 += self::mul($s13, 654183, 20);
2670 $s4 -= self::mul($s13, 997805, 20);
2671 $s5 += self::mul($s13, 136657, 18);
2672 $s6 -= self::mul($s13, 683901, 20);
2673
2674 $s0 += self::mul($s12, 666643, 20);
2675 $s1 += self::mul($s12, 470296, 19);
2676 $s2 += self::mul($s12, 654183, 20);
2677 $s3 -= self::mul($s12, 997805, 20);
2678 $s4 += self::mul($s12, 136657, 18);
2679 $s5 -= self::mul($s12, 683901, 20);
2680 $s12 = 0;
2681
2682 $carry0 = ($s0 + (1 << 20)) >> 21;
2683 $s1 += $carry0;
2684 $s0 -= $carry0 << 21;
2685 $carry2 = ($s2 + (1 << 20)) >> 21;
2686 $s3 += $carry2;
2687 $s2 -= $carry2 << 21;
2688 $carry4 = ($s4 + (1 << 20)) >> 21;
2689 $s5 += $carry4;
2690 $s4 -= $carry4 << 21;
2691 $carry6 = ($s6 + (1 << 20)) >> 21;
2692 $s7 += $carry6;
2693 $s6 -= $carry6 << 21;
2694 $carry8 = ($s8 + (1 << 20)) >> 21;
2695 $s9 += $carry8;
2696 $s8 -= $carry8 << 21;
2697 $carry10 = ($s10 + (1 << 20)) >> 21;
2698 $s11 += $carry10;
2699 $s10 -= $carry10 << 21;
2700
2701 $carry1 = ($s1 + (1 << 20)) >> 21;
2702 $s2 += $carry1;
2703 $s1 -= $carry1 << 21;
2704 $carry3 = ($s3 + (1 << 20)) >> 21;
2705 $s4 += $carry3;
2706 $s3 -= $carry3 << 21;
2707 $carry5 = ($s5 + (1 << 20)) >> 21;
2708 $s6 += $carry5;
2709 $s5 -= $carry5 << 21;
2710 $carry7 = ($s7 + (1 << 20)) >> 21;
2711 $s8 += $carry7;
2712 $s7 -= $carry7 << 21;
2713 $carry9 = ($s9 + (1 << 20)) >> 21;
2714 $s10 += $carry9;
2715 $s9 -= $carry9 << 21;
2716 $carry11 = ($s11 + (1 << 20)) >> 21;
2717 $s12 += $carry11;
2718 $s11 -= $carry11 << 21;
2719
2720 $s0 += self::mul($s12, 666643, 20);
2721 $s1 += self::mul($s12, 470296, 19);
2722 $s2 += self::mul($s12, 654183, 20);
2723 $s3 -= self::mul($s12, 997805, 20);
2724 $s4 += self::mul($s12, 136657, 18);
2725 $s5 -= self::mul($s12, 683901, 20);
2726 $s12 = 0;
2727
2728 $carry0 = $s0 >> 21;
2729 $s1 += $carry0;
2730 $s0 -= $carry0 << 21;
2731 $carry1 = $s1 >> 21;
2732 $s2 += $carry1;
2733 $s1 -= $carry1 << 21;
2734 $carry2 = $s2 >> 21;
2735 $s3 += $carry2;
2736 $s2 -= $carry2 << 21;
2737 $carry3 = $s3 >> 21;
2738 $s4 += $carry3;
2739 $s3 -= $carry3 << 21;
2740 $carry4 = $s4 >> 21;
2741 $s5 += $carry4;
2742 $s4 -= $carry4 << 21;
2743 $carry5 = $s5 >> 21;
2744 $s6 += $carry5;
2745 $s5 -= $carry5 << 21;
2746 $carry6 = $s6 >> 21;
2747 $s7 += $carry6;
2748 $s6 -= $carry6 << 21;
2749 $carry7 = $s7 >> 21;
2750 $s8 += $carry7;
2751 $s7 -= $carry7 << 21;
2752 $carry8 = $s8 >> 21;
2753 $s9 += $carry8;
2754 $s8 -= $carry8 << 21;
2755 $carry9 = $s9 >> 21;
2756 $s10 += $carry9;
2757 $s9 -= $carry9 << 21;
2758 $carry10 = $s10 >> 21;
2759 $s11 += $carry10;
2760 $s10 -= $carry10 << 21;
2761 $carry11 = $s11 >> 21;
2762 $s12 += $carry11;
2763 $s11 -= $carry11 << 21;
2764
2765 $s0 += self::mul($s12, 666643, 20);
2766 $s1 += self::mul($s12, 470296, 19);
2767 $s2 += self::mul($s12, 654183, 20);
2768 $s3 -= self::mul($s12, 997805, 20);
2769 $s4 += self::mul($s12, 136657, 18);
2770 $s5 -= self::mul($s12, 683901, 20);
2771
2772 $carry0 = $s0 >> 21;
2773 $s1 += $carry0;
2774 $s0 -= $carry0 << 21;
2775 $carry1 = $s1 >> 21;
2776 $s2 += $carry1;
2777 $s1 -= $carry1 << 21;
2778 $carry2 = $s2 >> 21;
2779 $s3 += $carry2;
2780 $s2 -= $carry2 << 21;
2781 $carry3 = $s3 >> 21;
2782 $s4 += $carry3;
2783 $s3 -= $carry3 << 21;
2784 $carry4 = $s4 >> 21;
2785 $s5 += $carry4;
2786 $s4 -= $carry4 << 21;
2787 $carry5 = $s5 >> 21;
2788 $s6 += $carry5;
2789 $s5 -= $carry5 << 21;
2790 $carry6 = $s6 >> 21;
2791 $s7 += $carry6;
2792 $s6 -= $carry6 << 21;
2793 $carry7 = $s7 >> 21;
2794 $s8 += $carry7;
2795 $s7 -= $carry7 << 21;
2796 $carry8 = $s8 >> 21;
2797 $s9 += $carry8;
2798 $s8 -= $carry8 << 21;
2799 $carry9 = $s9 >> 21;
2800 $s10 += $carry9;
2801 $s9 -= $carry9 << 21;
2802 $carry10 = $s10 >> 21;
2803 $s11 += $carry10;
2804 $s10 -= $carry10 << 21;
2805
2806 /**
2807 * @var array<int, int>
2808 */
2809 $arr = array(
2810 (int) (0xff & ($s0 >> 0)),
2811 (int) (0xff & ($s0 >> 8)),
2812 (int) (0xff & (($s0 >> 16) | $s1 << 5)),
2813 (int) (0xff & ($s1 >> 3)),
2814 (int) (0xff & ($s1 >> 11)),
2815 (int) (0xff & (($s1 >> 19) | $s2 << 2)),
2816 (int) (0xff & ($s2 >> 6)),
2817 (int) (0xff & (($s2 >> 14) | $s3 << 7)),
2818 (int) (0xff & ($s3 >> 1)),
2819 (int) (0xff & ($s3 >> 9)),
2820 (int) (0xff & (($s3 >> 17) | $s4 << 4)),
2821 (int) (0xff & ($s4 >> 4)),
2822 (int) (0xff & ($s4 >> 12)),
2823 (int) (0xff & (($s4 >> 20) | $s5 << 1)),
2824 (int) (0xff & ($s5 >> 7)),
2825 (int) (0xff & (($s5 >> 15) | $s6 << 6)),
2826 (int) (0xff & ($s6 >> 2)),
2827 (int) (0xff & ($s6 >> 10)),
2828 (int) (0xff & (($s6 >> 18) | $s7 << 3)),
2829 (int) (0xff & ($s7 >> 5)),
2830 (int) (0xff & ($s7 >> 13)),
2831 (int) (0xff & ($s8 >> 0)),
2832 (int) (0xff & ($s8 >> 8)),
2833 (int) (0xff & (($s8 >> 16) | $s9 << 5)),
2834 (int) (0xff & ($s9 >> 3)),
2835 (int) (0xff & ($s9 >> 11)),
2836 (int) (0xff & (($s9 >> 19) | $s10 << 2)),
2837 (int) (0xff & ($s10 >> 6)),
2838 (int) (0xff & (($s10 >> 14) | $s11 << 7)),
2839 (int) (0xff & ($s11 >> 1)),
2840 (int) (0xff & ($s11 >> 9)),
2841 (int) (0xff & ($s11 >> 17))
2842 );
2843 return self::intArrayToString($arr);
2844 }
2845
2846 /**
2847 * multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493
2848 *
2849 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A
2850 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
2851 */
2852 public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A)
2853 {
2854 $aslide = array(
2855 13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0,
2856 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0,
2857 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0,
2858 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1,
2859 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
2860 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0,
2861 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2862 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2863 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2864 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2865 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2866 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
2867 );
2868
2869 /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai size 8 */
2870 $Ai = array();
2871
2872 # ge_p3_to_cached(&Ai[0], A);
2873 $Ai[0] = self::ge_p3_to_cached($A);
2874 # ge_p3_dbl(&t, A);
2875 $t = self::ge_p3_dbl($A);
2876 # ge_p1p1_to_p3(&A2, &t);
2877 $A2 = self::ge_p1p1_to_p3($t);
2878
2879 for ($i = 1; $i < 8; ++$i) {
2880 # ge_add(&t, &A2, &Ai[0]);
2881 $t = self::ge_add($A2, $Ai[$i - 1]);
2882 # ge_p1p1_to_p3(&u, &t);
2883 $u = self::ge_p1p1_to_p3($t);
2884 # ge_p3_to_cached(&Ai[i], &u);
2885 $Ai[$i] = self::ge_p3_to_cached($u);
2886 }
2887
2888 $r = self::ge_p3_0();
2889 for ($i = 252; $i >= 0; --$i) {
2890 $t = self::ge_p3_dbl($r);
2891 if ($aslide[$i] > 0) {
2892 # ge_p1p1_to_p3(&u, &t);
2893 $u = self::ge_p1p1_to_p3($t);
2894 # ge_add(&t, &u, &Ai[aslide[i] / 2]);
2895 $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]);
2896 } elseif ($aslide[$i] < 0) {
2897 # ge_p1p1_to_p3(&u, &t);
2898 $u = self::ge_p1p1_to_p3($t);
2899 # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
2900 $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]);
2901 }
2902 }
2903
2904 # ge_p1p1_to_p3(r, &t);
2905 return self::ge_p1p1_to_p3($t);
2906 }
2907
2908 /**
2909 * @param string $a
2910 * @param string $b
2911 * @return string
2912 */
2913 public static function sc25519_mul($a, $b)
2914 {
2915 // int64_t a0 = 2097151 & load_3(a);
2916 // int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
2917 // int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
2918 // int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
2919 // int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
2920 // int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
2921 // int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
2922 // int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
2923 // int64_t a8 = 2097151 & load_3(a + 21);
2924 // int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
2925 // int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
2926 // int64_t a11 = (load_4(a + 28) >> 7);
2927 $a0 = 2097151 & self::load_3(self::substr($a, 0, 3));
2928 $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5);
2929 $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2);
2930 $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7);
2931 $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4);
2932 $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1);
2933 $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6);
2934 $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3);
2935 $a8 = 2097151 & self::load_3(self::substr($a, 21, 3));
2936 $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5);
2937 $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2);
2938 $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7);
2939
2940 // int64_t b0 = 2097151 & load_3(b);
2941 // int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
2942 // int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
2943 // int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
2944 // int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
2945 // int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
2946 // int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
2947 // int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
2948 // int64_t b8 = 2097151 & load_3(b + 21);
2949 // int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
2950 // int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
2951 // int64_t b11 = (load_4(b + 28) >> 7);
2952 $b0 = 2097151 & self::load_3(self::substr($b, 0, 3));
2953 $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5);
2954 $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2);
2955 $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7);
2956 $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4);
2957 $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1);
2958 $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6);
2959 $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3);
2960 $b8 = 2097151 & self::load_3(self::substr($b, 21, 3));
2961 $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5);
2962 $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2);
2963 $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7);
2964
2965 // s0 = a0 * b0;
2966 // s1 = a0 * b1 + a1 * b0;
2967 // s2 = a0 * b2 + a1 * b1 + a2 * b0;
2968 // s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
2969 // s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
2970 // s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
2971 // s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
2972 // s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
2973 // a6 * b1 + a7 * b0;
2974 // s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
2975 // a6 * b2 + a7 * b1 + a8 * b0;
2976 // s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
2977 // a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
2978 // s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
2979 // a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
2980 // s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
2981 // a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
2982 // s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 +
2983 // a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
2984 // s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 +
2985 // a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
2986 // s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 +
2987 // a9 * b5 + a10 * b4 + a11 * b3;
2988 // s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 +
2989 // a10 * b5 + a11 * b4;
2990 // s16 =
2991 // a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
2992 // s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
2993 // s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
2994 // s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
2995 // s20 = a9 * b11 + a10 * b10 + a11 * b9;
2996 // s21 = a10 * b11 + a11 * b10;
2997 // s22 = a11 * b11;
2998 // s23 = 0;
2999 $s0 = self::mul($a0, $b0, 22);
3000 $s1 = self::mul($a0, $b1, 22) + self::mul($a1, $b0, 22);
3001 $s2 = self::mul($a0, $b2, 22) + self::mul($a1, $b1, 22) + self::mul($a2, $b0, 22);
3002 $s3 = self::mul($a0, $b3, 22) + self::mul($a1, $b2, 22) + self::mul($a2, $b1, 22) + self::mul($a3, $b0, 22);
3003 $s4 = self::mul($a0, $b4, 22) + self::mul($a1, $b3, 22) + self::mul($a2, $b2, 22) + self::mul($a3, $b1, 22) +
3004 self::mul($a4, $b0, 22);
3005 $s5 = self::mul($a0, $b5, 22) + self::mul($a1, $b4, 22) + self::mul($a2, $b3, 22) + self::mul($a3, $b2, 22) +
3006 self::mul($a4, $b1, 22) + self::mul($a5, $b0, 22);
3007 $s6 = self::mul($a0, $b6, 22) + self::mul($a1, $b5, 22) + self::mul($a2, $b4, 22) + self::mul($a3, $b3, 22) +
3008 self::mul($a4, $b2, 22) + self::mul($a5, $b1, 22) + self::mul($a6, $b0, 22);
3009 $s7 = self::mul($a0, $b7, 22) + self::mul($a1, $b6, 22) + self::mul($a2, $b5, 22) + self::mul($a3, $b4, 22) +
3010 self::mul($a4, $b3, 22) + self::mul($a5, $b2, 22) + self::mul($a6, $b1, 22) + self::mul($a7, $b0, 22);
3011 $s8 = self::mul($a0, $b8, 22) + self::mul($a1, $b7, 22) + self::mul($a2, $b6, 22) + self::mul($a3, $b5, 22) +
3012 self::mul($a4, $b4, 22) + self::mul($a5, $b3, 22) + self::mul($a6, $b2, 22) + self::mul($a7, $b1, 22) +
3013 self::mul($a8, $b0, 22);
3014 $s9 = self::mul($a0, $b9, 22) + self::mul($a1, $b8, 22) + self::mul($a2, $b7, 22) + self::mul($a3, $b6, 22) +
3015 self::mul($a4, $b5, 22) + self::mul($a5, $b4, 22) + self::mul($a6, $b3, 22) + self::mul($a7, $b2, 22) +
3016 self::mul($a8, $b1, 22) + self::mul($a9, $b0, 22);
3017 $s10 = self::mul($a0, $b10, 22) + self::mul($a1, $b9, 22) + self::mul($a2, $b8, 22) + self::mul($a3, $b7, 22) +
3018 self::mul($a4, $b6, 22) + self::mul($a5, $b5, 22) + self::mul($a6, $b4, 22) + self::mul($a7, $b3, 22) +
3019 self::mul($a8, $b2, 22) + self::mul($a9, $b1, 22) + self::mul($a10, $b0, 22);
3020 $s11 = self::mul($a0, $b11, 22) + self::mul($a1, $b10, 22) + self::mul($a2, $b9, 22) + self::mul($a3, $b8, 22) +
3021 self::mul($a4, $b7, 22) + self::mul($a5, $b6, 22) + self::mul($a6, $b5, 22) + self::mul($a7, $b4, 22) +
3022 self::mul($a8, $b3, 22) + self::mul($a9, $b2, 22) + self::mul($a10, $b1, 22) + self::mul($a11, $b0, 22);
3023 $s12 = self::mul($a1, $b11, 22) + self::mul($a2, $b10, 22) + self::mul($a3, $b9, 22) + self::mul($a4, $b8, 22) +
3024 self::mul($a5, $b7, 22) + self::mul($a6, $b6, 22) + self::mul($a7, $b5, 22) + self::mul($a8, $b4, 22) +
3025 self::mul($a9, $b3, 22) + self::mul($a10, $b2, 22) + self::mul($a11, $b1, 22);
3026 $s13 = self::mul($a2, $b11, 22) + self::mul($a3, $b10, 22) + self::mul($a4, $b9, 22) + self::mul($a5, $b8, 22) +
3027 self::mul($a6, $b7, 22) + self::mul($a7, $b6, 22) + self::mul($a8, $b5, 22) + self::mul($a9, $b4, 22) +
3028 self::mul($a10, $b3, 22) + self::mul($a11, $b2, 22);
3029 $s14 = self::mul($a3, $b11, 22) + self::mul($a4, $b10, 22) + self::mul($a5, $b9, 22) + self::mul($a6, $b8, 22) +
3030 self::mul($a7, $b7, 22) + self::mul($a8, $b6, 22) + self::mul($a9, $b5, 22) + self::mul($a10, $b4, 22) +
3031 self::mul($a11, $b3, 22);
3032 $s15 = self::mul($a4, $b11, 22) + self::mul($a5, $b10, 22) + self::mul($a6, $b9, 22) + self::mul($a7, $b8, 22) +
3033 self::mul($a8, $b7, 22) + self::mul($a9, $b6, 22) + self::mul($a10, $b5, 22) + self::mul($a11, $b4, 22);
3034 $s16 =
3035 self::mul($a5, $b11, 22) + self::mul($a6, $b10, 22) + self::mul($a7, $b9, 22) + self::mul($a8, $b8, 22) +
3036 self::mul($a9, $b7, 22) + self::mul($a10, $b6, 22) + self::mul($a11, $b5, 22);
3037 $s17 = self::mul($a6, $b11, 22) + self::mul($a7, $b10, 22) + self::mul($a8, $b9, 22) + self::mul($a9, $b8, 22) +
3038 self::mul($a10, $b7, 22) + self::mul($a11, $b6, 22);
3039 $s18 = self::mul($a7, $b11, 22) + self::mul($a8, $b10, 22) + self::mul($a9, $b9, 22) + self::mul($a10, $b8, 22)
3040 + self::mul($a11, $b7, 22);
3041 $s19 = self::mul($a8, $b11, 22) + self::mul($a9, $b10, 22) + self::mul($a10, $b9, 22) +
3042 self::mul($a11, $b8, 22);
3043 $s20 = self::mul($a9, $b11, 22) + self::mul($a10, $b10, 22) + self::mul($a11, $b9, 22);
3044 $s21 = self::mul($a10, $b11, 22) + self::mul($a11, $b10, 22);
3045 $s22 = self::mul($a11, $b11, 22);
3046 $s23 = 0;
3047
3048 // carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
3049 // s1 += carry0;
3050 // s0 -= carry0 * ((uint64_t) 1L << 21);
3051 $carry0 = ($s0 + (1 << 20)) >> 21;
3052 $s1 += $carry0;
3053 $s0 -= $carry0 << 21;
3054 // carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
3055 // s3 += carry2;
3056 // s2 -= carry2 * ((uint64_t) 1L << 21);
3057 $carry2 = ($s2 + (1 << 20)) >> 21;
3058 $s3 += $carry2;
3059 $s2 -= $carry2 << 21;
3060 // carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
3061 // s5 += carry4;
3062 // s4 -= carry4 * ((uint64_t) 1L << 21);
3063 $carry4 = ($s4 + (1 << 20)) >> 21;
3064 $s5 += $carry4;
3065 $s4 -= $carry4 << 21;
3066 // carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
3067 // s7 += carry6;
3068 // s6 -= carry6 * ((uint64_t) 1L << 21);
3069 $carry6 = ($s6 + (1 << 20)) >> 21;
3070 $s7 += $carry6;
3071 $s6 -= $carry6 << 21;
3072 // carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
3073 // s9 += carry8;
3074 // s8 -= carry8 * ((uint64_t) 1L << 21);
3075 $carry8 = ($s8 + (1 << 20)) >> 21;
3076 $s9 += $carry8;
3077 $s8 -= $carry8 << 21;
3078 // carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
3079 // s11 += carry10;
3080 // s10 -= carry10 * ((uint64_t) 1L << 21);
3081 $carry10 = ($s10 + (1 << 20)) >> 21;
3082 $s11 += $carry10;
3083 $s10 -= $carry10 << 21;
3084 // carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
3085 // s13 += carry12;
3086 // s12 -= carry12 * ((uint64_t) 1L << 21);
3087 $carry12 = ($s12 + (1 << 20)) >> 21;
3088 $s13 += $carry12;
3089 $s12 -= $carry12 << 21;
3090 // carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
3091 // s15 += carry14;
3092 // s14 -= carry14 * ((uint64_t) 1L << 21);
3093 $carry14 = ($s14 + (1 << 20)) >> 21;
3094 $s15 += $carry14;
3095 $s14 -= $carry14 << 21;
3096 // carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
3097 // s17 += carry16;
3098 // s16 -= carry16 * ((uint64_t) 1L << 21);
3099 $carry16 = ($s16 + (1 << 20)) >> 21;
3100 $s17 += $carry16;
3101 $s16 -= $carry16 << 21;
3102 // carry18 = (s18 + (int64_t) (1L << 20)) >> 21;
3103 // s19 += carry18;
3104 // s18 -= carry18 * ((uint64_t) 1L << 21);
3105 $carry18 = ($s18 + (1 << 20)) >> 21;
3106 $s19 += $carry18;
3107 $s18 -= $carry18 << 21;
3108 // carry20 = (s20 + (int64_t) (1L << 20)) >> 21;
3109 // s21 += carry20;
3110 // s20 -= carry20 * ((uint64_t) 1L << 21);
3111 $carry20 = ($s20 + (1 << 20)) >> 21;
3112 $s21 += $carry20;
3113 $s20 -= $carry20 << 21;
3114 // carry22 = (s22 + (int64_t) (1L << 20)) >> 21;
3115 // s23 += carry22;
3116 // s22 -= carry22 * ((uint64_t) 1L << 21);
3117 $carry22 = ($s22 + (1 << 20)) >> 21;
3118 $s23 += $carry22;
3119 $s22 -= $carry22 << 21;
3120
3121 // carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
3122 // s2 += carry1;
3123 // s1 -= carry1 * ((uint64_t) 1L << 21);
3124 $carry1 = ($s1 + (1 << 20)) >> 21;
3125 $s2 += $carry1;
3126 $s1 -= $carry1 << 21;
3127 // carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
3128 // s4 += carry3;
3129 // s3 -= carry3 * ((uint64_t) 1L << 21);
3130 $carry3 = ($s3 + (1 << 20)) >> 21;
3131 $s4 += $carry3;
3132 $s3 -= $carry3 << 21;
3133 // carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
3134 // s6 += carry5;
3135 // s5 -= carry5 * ((uint64_t) 1L << 21);
3136 $carry5 = ($s5 + (1 << 20)) >> 21;
3137 $s6 += $carry5;
3138 $s5 -= $carry5 << 21;
3139 // carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
3140 // s8 += carry7;
3141 // s7 -= carry7 * ((uint64_t) 1L << 21);
3142 $carry7 = ($s7 + (1 << 20)) >> 21;
3143 $s8 += $carry7;
3144 $s7 -= $carry7 << 21;
3145 // carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
3146 // s10 += carry9;
3147 // s9 -= carry9 * ((uint64_t) 1L << 21);
3148 $carry9 = ($s9 + (1 << 20)) >> 21;
3149 $s10 += $carry9;
3150 $s9 -= $carry9 << 21;
3151 // carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
3152 // s12 += carry11;
3153 // s11 -= carry11 * ((uint64_t) 1L << 21);
3154 $carry11 = ($s11 + (1 << 20)) >> 21;
3155 $s12 += $carry11;
3156 $s11 -= $carry11 << 21;
3157 // carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
3158 // s14 += carry13;
3159 // s13 -= carry13 * ((uint64_t) 1L << 21);
3160 $carry13 = ($s13 + (1 << 20)) >> 21;
3161 $s14 += $carry13;
3162 $s13 -= $carry13 << 21;
3163 // carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
3164 // s16 += carry15;
3165 // s15 -= carry15 * ((uint64_t) 1L << 21);
3166 $carry15 = ($s15 + (1 << 20)) >> 21;
3167 $s16 += $carry15;
3168 $s15 -= $carry15 << 21;
3169 // carry17 = (s17 + (int64_t) (1L << 20)) >> 21;
3170 // s18 += carry17;
3171 // s17 -= carry17 * ((uint64_t) 1L << 21);
3172 $carry17 = ($s17 + (1 << 20)) >> 21;
3173 $s18 += $carry17;
3174 $s17 -= $carry17 << 21;
3175 // carry19 = (s19 + (int64_t) (1L << 20)) >> 21;
3176 // s20 += carry19;
3177 // s19 -= carry19 * ((uint64_t) 1L << 21);
3178 $carry19 = ($s19 + (1 << 20)) >> 21;
3179 $s20 += $carry19;
3180 $s19 -= $carry19 << 21;
3181 // carry21 = (s21 + (int64_t) (1L << 20)) >> 21;
3182 // s22 += carry21;
3183 // s21 -= carry21 * ((uint64_t) 1L << 21);
3184 $carry21 = ($s21 + (1 << 20)) >> 21;
3185 $s22 += $carry21;
3186 $s21 -= $carry21 << 21;
3187
3188 // s11 += s23 * 666643;
3189 // s12 += s23 * 470296;
3190 // s13 += s23 * 654183;
3191 // s14 -= s23 * 997805;
3192 // s15 += s23 * 136657;
3193 // s16 -= s23 * 683901;
3194 $s11 += self::mul($s23, 666643, 20);
3195 $s12 += self::mul($s23, 470296, 19);
3196 $s13 += self::mul($s23, 654183, 20);
3197 $s14 -= self::mul($s23, 997805, 20);
3198 $s15 += self::mul($s23, 136657, 18);
3199 $s16 -= self::mul($s23, 683901, 20);
3200
3201 // s10 += s22 * 666643;
3202 // s11 += s22 * 470296;
3203 // s12 += s22 * 654183;
3204 // s13 -= s22 * 997805;
3205 // s14 += s22 * 136657;
3206 // s15 -= s22 * 683901;
3207 $s10 += self::mul($s22, 666643, 20);
3208 $s11 += self::mul($s22, 470296, 19);
3209 $s12 += self::mul($s22, 654183, 20);
3210 $s13 -= self::mul($s22, 997805, 20);
3211 $s14 += self::mul($s22, 136657, 18);
3212 $s15 -= self::mul($s22, 683901, 20);
3213
3214 // s9 += s21 * 666643;
3215 // s10 += s21 * 470296;
3216 // s11 += s21 * 654183;
3217 // s12 -= s21 * 997805;
3218 // s13 += s21 * 136657;
3219 // s14 -= s21 * 683901;
3220 $s9 += self::mul($s21, 666643, 20);
3221 $s10 += self::mul($s21, 470296, 19);
3222 $s11 += self::mul($s21, 654183, 20);
3223 $s12 -= self::mul($s21, 997805, 20);
3224 $s13 += self::mul($s21, 136657, 18);
3225 $s14 -= self::mul($s21, 683901, 20);
3226
3227 // s8 += s20 * 666643;
3228 // s9 += s20 * 470296;
3229 // s10 += s20 * 654183;
3230 // s11 -= s20 * 997805;
3231 // s12 += s20 * 136657;
3232 // s13 -= s20 * 683901;
3233 $s8 += self::mul($s20, 666643, 20);
3234 $s9 += self::mul($s20, 470296, 19);
3235 $s10 += self::mul($s20, 654183, 20);
3236 $s11 -= self::mul($s20, 997805, 20);
3237 $s12 += self::mul($s20, 136657, 18);
3238 $s13 -= self::mul($s20, 683901, 20);
3239
3240 // s7 += s19 * 666643;
3241 // s8 += s19 * 470296;
3242 // s9 += s19 * 654183;
3243 // s10 -= s19 * 997805;
3244 // s11 += s19 * 136657;
3245 // s12 -= s19 * 683901;
3246 $s7 += self::mul($s19, 666643, 20);
3247 $s8 += self::mul($s19, 470296, 19);
3248 $s9 += self::mul($s19, 654183, 20);
3249 $s10 -= self::mul($s19, 997805, 20);
3250 $s11 += self::mul($s19, 136657, 18);
3251 $s12 -= self::mul($s19, 683901, 20);
3252
3253 // s6 += s18 * 666643;
3254 // s7 += s18 * 470296;
3255 // s8 += s18 * 654183;
3256 // s9 -= s18 * 997805;
3257 // s10 += s18 * 136657;
3258 // s11 -= s18 * 683901;
3259 $s6 += self::mul($s18, 666643, 20);
3260 $s7 += self::mul($s18, 470296, 19);
3261 $s8 += self::mul($s18, 654183, 20);
3262 $s9 -= self::mul($s18, 997805, 20);
3263 $s10 += self::mul($s18, 136657, 18);
3264 $s11 -= self::mul($s18, 683901, 20);
3265
3266 // carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
3267 // s7 += carry6;
3268 // s6 -= carry6 * ((uint64_t) 1L << 21);
3269 $carry6 = ($s6 + (1 << 20)) >> 21;
3270 $s7 += $carry6;
3271 $s6 -= $carry6 << 21;
3272 // carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
3273 // s9 += carry8;
3274 // s8 -= carry8 * ((uint64_t) 1L << 21);
3275 $carry8 = ($s8 + (1 << 20)) >> 21;
3276 $s9 += $carry8;
3277 $s8 -= $carry8 << 21;
3278 // carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
3279 // s11 += carry10;
3280 // s10 -= carry10 * ((uint64_t) 1L << 21);
3281 $carry10 = ($s10 + (1 << 20)) >> 21;
3282 $s11 += $carry10;
3283 $s10 -= $carry10 << 21;
3284 // carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
3285 // s13 += carry12;
3286 // s12 -= carry12 * ((uint64_t) 1L << 21);
3287 $carry12 = ($s12 + (1 << 20)) >> 21;
3288 $s13 += $carry12;
3289 $s12 -= $carry12 << 21;
3290 // carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
3291 // s15 += carry14;
3292 // s14 -= carry14 * ((uint64_t) 1L << 21);
3293 $carry14 = ($s14 + (1 << 20)) >> 21;
3294 $s15 += $carry14;
3295 $s14 -= $carry14 << 21;
3296 // carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
3297 // s17 += carry16;
3298 // s16 -= carry16 * ((uint64_t) 1L << 21);
3299 $carry16 = ($s16 + (1 << 20)) >> 21;
3300 $s17 += $carry16;
3301 $s16 -= $carry16 << 21;
3302
3303 // carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
3304 // s8 += carry7;
3305 // s7 -= carry7 * ((uint64_t) 1L << 21);
3306 $carry7 = ($s7 + (1 << 20)) >> 21;
3307 $s8 += $carry7;
3308 $s7 -= $carry7 << 21;
3309 // carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
3310 // s10 += carry9;
3311 // s9 -= carry9 * ((uint64_t) 1L << 21);
3312 $carry9 = ($s9 + (1 << 20)) >> 21;
3313 $s10 += $carry9;
3314 $s9 -= $carry9 << 21;
3315 // carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
3316 // s12 += carry11;
3317 // s11 -= carry11 * ((uint64_t) 1L << 21);
3318 $carry11 = ($s11 + (1 << 20)) >> 21;
3319 $s12 += $carry11;
3320 $s11 -= $carry11 << 21;
3321 // carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
3322 // s14 += carry13;
3323 // s13 -= carry13 * ((uint64_t) 1L << 21);
3324 $carry13 = ($s13 + (1 << 20)) >> 21;
3325 $s14 += $carry13;
3326 $s13 -= $carry13 << 21;
3327 // carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
3328 // s16 += carry15;
3329 // s15 -= carry15 * ((uint64_t) 1L << 21);
3330 $carry15 = ($s15 + (1 << 20)) >> 21;
3331 $s16 += $carry15;
3332 $s15 -= $carry15 << 21;
3333
3334 // s5 += s17 * 666643;
3335 // s6 += s17 * 470296;
3336 // s7 += s17 * 654183;
3337 // s8 -= s17 * 997805;
3338 // s9 += s17 * 136657;
3339 // s10 -= s17 * 683901;
3340 $s5 += self::mul($s17, 666643, 20);
3341 $s6 += self::mul($s17, 470296, 19);
3342 $s7 += self::mul($s17, 654183, 20);
3343 $s8 -= self::mul($s17, 997805, 20);
3344 $s9 += self::mul($s17, 136657, 18);
3345 $s10 -= self::mul($s17, 683901, 20);
3346
3347 // s4 += s16 * 666643;
3348 // s5 += s16 * 470296;
3349 // s6 += s16 * 654183;
3350 // s7 -= s16 * 997805;
3351 // s8 += s16 * 136657;
3352 // s9 -= s16 * 683901;
3353 $s4 += self::mul($s16, 666643, 20);
3354 $s5 += self::mul($s16, 470296, 19);
3355 $s6 += self::mul($s16, 654183, 20);
3356 $s7 -= self::mul($s16, 997805, 20);
3357 $s8 += self::mul($s16, 136657, 18);
3358 $s9 -= self::mul($s16, 683901, 20);
3359
3360 // s3 += s15 * 666643;
3361 // s4 += s15 * 470296;
3362 // s5 += s15 * 654183;
3363 // s6 -= s15 * 997805;
3364 // s7 += s15 * 136657;
3365 // s8 -= s15 * 683901;
3366 $s3 += self::mul($s15, 666643, 20);
3367 $s4 += self::mul($s15, 470296, 19);
3368 $s5 += self::mul($s15, 654183, 20);
3369 $s6 -= self::mul($s15, 997805, 20);
3370 $s7 += self::mul($s15, 136657, 18);
3371 $s8 -= self::mul($s15, 683901, 20);
3372
3373 // s2 += s14 * 666643;
3374 // s3 += s14 * 470296;
3375 // s4 += s14 * 654183;
3376 // s5 -= s14 * 997805;
3377 // s6 += s14 * 136657;
3378 // s7 -= s14 * 683901;
3379 $s2 += self::mul($s14, 666643, 20);
3380 $s3 += self::mul($s14, 470296, 19);
3381 $s4 += self::mul($s14, 654183, 20);
3382 $s5 -= self::mul($s14, 997805, 20);
3383 $s6 += self::mul($s14, 136657, 18);
3384 $s7 -= self::mul($s14, 683901, 20);
3385
3386 // s1 += s13 * 666643;
3387 // s2 += s13 * 470296;
3388 // s3 += s13 * 654183;
3389 // s4 -= s13 * 997805;
3390 // s5 += s13 * 136657;
3391 // s6 -= s13 * 683901;
3392 $s1 += self::mul($s13, 666643, 20);
3393 $s2 += self::mul($s13, 470296, 19);
3394 $s3 += self::mul($s13, 654183, 20);
3395 $s4 -= self::mul($s13, 997805, 20);
3396 $s5 += self::mul($s13, 136657, 18);
3397 $s6 -= self::mul($s13, 683901, 20);
3398
3399 // s0 += s12 * 666643;
3400 // s1 += s12 * 470296;
3401 // s2 += s12 * 654183;
3402 // s3 -= s12 * 997805;
3403 // s4 += s12 * 136657;
3404 // s5 -= s12 * 683901;
3405 // s12 = 0;
3406 $s0 += self::mul($s12, 666643, 20);
3407 $s1 += self::mul($s12, 470296, 19);
3408 $s2 += self::mul($s12, 654183, 20);
3409 $s3 -= self::mul($s12, 997805, 20);
3410 $s4 += self::mul($s12, 136657, 18);
3411 $s5 -= self::mul($s12, 683901, 20);
3412 $s12 = 0;
3413
3414 // carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
3415 // s1 += carry0;
3416 // s0 -= carry0 * ((uint64_t) 1L << 21);
3417 $carry0 = ($s0 + (1 << 20)) >> 21;
3418 $s1 += $carry0;
3419 $s0 -= $carry0 << 21;
3420 // carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
3421 // s3 += carry2;
3422 // s2 -= carry2 * ((uint64_t) 1L << 21);
3423 $carry2 = ($s2 + (1 << 20)) >> 21;
3424 $s3 += $carry2;
3425 $s2 -= $carry2 << 21;
3426 // carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
3427 // s5 += carry4;
3428 // s4 -= carry4 * ((uint64_t) 1L << 21);
3429 $carry4 = ($s4 + (1 << 20)) >> 21;
3430 $s5 += $carry4;
3431 $s4 -= $carry4 << 21;
3432 // carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
3433 // s7 += carry6;
3434 // s6 -= carry6 * ((uint64_t) 1L << 21);
3435 $carry6 = ($s6 + (1 << 20)) >> 21;
3436 $s7 += $carry6;
3437 $s6 -= $carry6 << 21;
3438 // carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
3439 // s9 += carry8;
3440 // s8 -= carry8 * ((uint64_t) 1L << 21);
3441 $carry8 = ($s8 + (1 << 20)) >> 21;
3442 $s9 += $carry8;
3443 $s8 -= $carry8 << 21;
3444 // carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
3445 // s11 += carry10;
3446 // s10 -= carry10 * ((uint64_t) 1L << 21);
3447 $carry10 = ($s10 + (1 << 20)) >> 21;
3448 $s11 += $carry10;
3449 $s10 -= $carry10 << 21;
3450
3451 // carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
3452 // s2 += carry1;
3453 // s1 -= carry1 * ((uint64_t) 1L << 21);
3454 $carry1 = ($s1 + (1 << 20)) >> 21;
3455 $s2 += $carry1;
3456 $s1 -= $carry1 << 21;
3457 // carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
3458 // s4 += carry3;
3459 // s3 -= carry3 * ((uint64_t) 1L << 21);
3460 $carry3 = ($s3 + (1 << 20)) >> 21;
3461 $s4 += $carry3;
3462 $s3 -= $carry3 << 21;
3463 // carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
3464 // s6 += carry5;
3465 // s5 -= carry5 * ((uint64_t) 1L << 21);
3466 $carry5 = ($s5 + (1 << 20)) >> 21;
3467 $s6 += $carry5;
3468 $s5 -= $carry5 << 21;
3469 // carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
3470 // s8 += carry7;
3471 // s7 -= carry7 * ((uint64_t) 1L << 21);
3472 $carry7 = ($s7 + (1 << 20)) >> 21;
3473 $s8 += $carry7;
3474 $s7 -= $carry7 << 21;
3475 // carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
3476 // s10 += carry9;
3477 // s9 -= carry9 * ((uint64_t) 1L << 21);
3478 $carry9 = ($s9 + (1 << 20)) >> 21;
3479 $s10 += $carry9;
3480 $s9 -= $carry9 << 21;
3481 // carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
3482 // s12 += carry11;
3483 // s11 -= carry11 * ((uint64_t) 1L << 21);
3484 $carry11 = ($s11 + (1 << 20)) >> 21;
3485 $s12 += $carry11;
3486 $s11 -= $carry11 << 21;
3487
3488 // s0 += s12 * 666643;
3489 // s1 += s12 * 470296;
3490 // s2 += s12 * 654183;
3491 // s3 -= s12 * 997805;
3492 // s4 += s12 * 136657;
3493 // s5 -= s12 * 683901;
3494 // s12 = 0;
3495 $s0 += self::mul($s12, 666643, 20);
3496 $s1 += self::mul($s12, 470296, 19);
3497 $s2 += self::mul($s12, 654183, 20);
3498 $s3 -= self::mul($s12, 997805, 20);
3499 $s4 += self::mul($s12, 136657, 18);
3500 $s5 -= self::mul($s12, 683901, 20);
3501 $s12 = 0;
3502
3503 // carry0 = s0 >> 21;
3504 // s1 += carry0;
3505 // s0 -= carry0 * ((uint64_t) 1L << 21);
3506 $carry0 = $s0 >> 21;
3507 $s1 += $carry0;
3508 $s0 -= $carry0 << 21;
3509 // carry1 = s1 >> 21;
3510 // s2 += carry1;
3511 // s1 -= carry1 * ((uint64_t) 1L << 21);
3512 $carry1 = $s1 >> 21;
3513 $s2 += $carry1;
3514 $s1 -= $carry1 << 21;
3515 // carry2 = s2 >> 21;
3516 // s3 += carry2;
3517 // s2 -= carry2 * ((uint64_t) 1L << 21);
3518 $carry2 = $s2 >> 21;
3519 $s3 += $carry2;
3520 $s2 -= $carry2 << 21;
3521 // carry3 = s3 >> 21;
3522 // s4 += carry3;
3523 // s3 -= carry3 * ((uint64_t) 1L << 21);
3524 $carry3 = $s3 >> 21;
3525 $s4 += $carry3;
3526 $s3 -= $carry3 << 21;
3527 // carry4 = s4 >> 21;
3528 // s5 += carry4;
3529 // s4 -= carry4 * ((uint64_t) 1L << 21);
3530 $carry4 = $s4 >> 21;
3531 $s5 += $carry4;
3532 $s4 -= $carry4 << 21;
3533 // carry5 = s5 >> 21;
3534 // s6 += carry5;
3535 // s5 -= carry5 * ((uint64_t) 1L << 21);
3536 $carry5 = $s5 >> 21;
3537 $s6 += $carry5;
3538 $s5 -= $carry5 << 21;
3539 // carry6 = s6 >> 21;
3540 // s7 += carry6;
3541 // s6 -= carry6 * ((uint64_t) 1L << 21);
3542 $carry6 = $s6 >> 21;
3543 $s7 += $carry6;
3544 $s6 -= $carry6 << 21;
3545 // carry7 = s7 >> 21;
3546 // s8 += carry7;
3547 // s7 -= carry7 * ((uint64_t) 1L << 21);
3548 $carry7 = $s7 >> 21;
3549 $s8 += $carry7;
3550 $s7 -= $carry7 << 21;
3551 // carry8 = s8 >> 21;
3552 // s9 += carry8;
3553 // s8 -= carry8 * ((uint64_t) 1L << 21);
3554 $carry8 = $s8 >> 21;
3555 $s9 += $carry8;
3556 $s8 -= $carry8 << 21;
3557 // carry9 = s9 >> 21;
3558 // s10 += carry9;
3559 // s9 -= carry9 * ((uint64_t) 1L << 21);
3560 $carry9 = $s9 >> 21;
3561 $s10 += $carry9;
3562 $s9 -= $carry9 << 21;
3563 // carry10 = s10 >> 21;
3564 // s11 += carry10;
3565 // s10 -= carry10 * ((uint64_t) 1L << 21);
3566 $carry10 = $s10 >> 21;
3567 $s11 += $carry10;
3568 $s10 -= $carry10 << 21;
3569 // carry11 = s11 >> 21;
3570 // s12 += carry11;
3571 // s11 -= carry11 * ((uint64_t) 1L << 21);
3572 $carry11 = $s11 >> 21;
3573 $s12 += $carry11;
3574 $s11 -= $carry11 << 21;
3575
3576 // s0 += s12 * 666643;
3577 // s1 += s12 * 470296;
3578 // s2 += s12 * 654183;
3579 // s3 -= s12 * 997805;
3580 // s4 += s12 * 136657;
3581 // s5 -= s12 * 683901;
3582 $s0 += self::mul($s12, 666643, 20);
3583 $s1 += self::mul($s12, 470296, 19);
3584 $s2 += self::mul($s12, 654183, 20);
3585 $s3 -= self::mul($s12, 997805, 20);
3586 $s4 += self::mul($s12, 136657, 18);
3587 $s5 -= self::mul($s12, 683901, 20);
3588
3589 // carry0 = s0 >> 21;
3590 // s1 += carry0;
3591 // s0 -= carry0 * ((uint64_t) 1L << 21);
3592 $carry0 = $s0 >> 21;
3593 $s1 += $carry0;
3594 $s0 -= $carry0 << 21;
3595 // carry1 = s1 >> 21;
3596 // s2 += carry1;
3597 // s1 -= carry1 * ((uint64_t) 1L << 21);
3598 $carry1 = $s1 >> 21;
3599 $s2 += $carry1;
3600 $s1 -= $carry1 << 21;
3601 // carry2 = s2 >> 21;
3602 // s3 += carry2;
3603 // s2 -= carry2 * ((uint64_t) 1L << 21);
3604 $carry2 = $s2 >> 21;
3605 $s3 += $carry2;
3606 $s2 -= $carry2 << 21;
3607 // carry3 = s3 >> 21;
3608 // s4 += carry3;
3609 // s3 -= carry3 * ((uint64_t) 1L << 21);
3610 $carry3 = $s3 >> 21;
3611 $s4 += $carry3;
3612 $s3 -= $carry3 << 21;
3613 // carry4 = s4 >> 21;
3614 // s5 += carry4;
3615 // s4 -= carry4 * ((uint64_t) 1L << 21);
3616 $carry4 = $s4 >> 21;
3617 $s5 += $carry4;
3618 $s4 -= $carry4 << 21;
3619 // carry5 = s5 >> 21;
3620 // s6 += carry5;
3621 // s5 -= carry5 * ((uint64_t) 1L << 21);
3622 $carry5 = $s5 >> 21;
3623 $s6 += $carry5;
3624 $s5 -= $carry5 << 21;
3625 // carry6 = s6 >> 21;
3626 // s7 += carry6;
3627 // s6 -= carry6 * ((uint64_t) 1L << 21);
3628 $carry6 = $s6 >> 21;
3629 $s7 += $carry6;
3630 $s6 -= $carry6 << 21;
3631 // carry7 = s7 >> 21;
3632 // s8 += carry7;
3633 // s7 -= carry7 * ((uint64_t) 1L << 21);
3634 $carry7 = $s7 >> 21;
3635 $s8 += $carry7;
3636 $s7 -= $carry7 << 21;
3637 // carry8 = s8 >> 21;
3638 // s9 += carry8;
3639 // s8 -= carry8 * ((uint64_t) 1L << 21);
3640 $carry8 = $s8 >> 21;
3641 $s9 += $carry8;
3642 $s8 -= $carry8 << 21;
3643 // carry9 = s9 >> 21;
3644 // s10 += carry9;
3645 // s9 -= carry9 * ((uint64_t) 1L << 21);
3646 $carry9 = $s9 >> 21;
3647 $s10 += $carry9;
3648 $s9 -= $carry9 << 21;
3649 // carry10 = s10 >> 21;
3650 // s11 += carry10;
3651 // s10 -= carry10 * ((uint64_t) 1L << 21);
3652 $carry10 = $s10 >> 21;
3653 $s11 += $carry10;
3654 $s10 -= $carry10 << 21;
3655
3656 $s = array_fill(0, 32, 0);
3657 // s[0] = s0 >> 0;
3658 $s[0] = $s0 >> 0;
3659 // s[1] = s0 >> 8;
3660 $s[1] = $s0 >> 8;
3661 // s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5));
3662 $s[2] = ($s0 >> 16) | ($s1 << 5);
3663 // s[3] = s1 >> 3;
3664 $s[3] = $s1 >> 3;
3665 // s[4] = s1 >> 11;
3666 $s[4] = $s1 >> 11;
3667 // s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2));
3668 $s[5] = ($s1 >> 19) | ($s2 << 2);
3669 // s[6] = s2 >> 6;
3670 $s[6] = $s2 >> 6;
3671 // s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7));
3672 $s[7] = ($s2 >> 14) | ($s3 << 7);
3673 // s[8] = s3 >> 1;
3674 $s[8] = $s3 >> 1;
3675 // s[9] = s3 >> 9;
3676 $s[9] = $s3 >> 9;
3677 // s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4));
3678 $s[10] = ($s3 >> 17) | ($s4 << 4);
3679 // s[11] = s4 >> 4;
3680 $s[11] = $s4 >> 4;
3681 // s[12] = s4 >> 12;
3682 $s[12] = $s4 >> 12;
3683 // s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1));
3684 $s[13] = ($s4 >> 20) | ($s5 << 1);
3685 // s[14] = s5 >> 7;
3686 $s[14] = $s5 >> 7;
3687 // s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6));
3688 $s[15] = ($s5 >> 15) | ($s6 << 6);
3689 // s[16] = s6 >> 2;
3690 $s[16] = $s6 >> 2;
3691 // s[17] = s6 >> 10;
3692 $s[17] = $s6 >> 10;
3693 // s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3));
3694 $s[18] = ($s6 >> 18) | ($s7 << 3);
3695 // s[19] = s7 >> 5;
3696 $s[19] = $s7 >> 5;
3697 // s[20] = s7 >> 13;
3698 $s[20] = $s7 >> 13;
3699 // s[21] = s8 >> 0;
3700 $s[21] = $s8 >> 0;
3701 // s[22] = s8 >> 8;
3702 $s[22] = $s8 >> 8;
3703 // s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5));
3704 $s[23] = ($s8 >> 16) | ($s9 << 5);
3705 // s[24] = s9 >> 3;
3706 $s[24] = $s9 >> 3;
3707 // s[25] = s9 >> 11;
3708 $s[25] = $s9 >> 11;
3709 // s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2));
3710 $s[26] = ($s9 >> 19) | ($s10 << 2);
3711 // s[27] = s10 >> 6;
3712 $s[27] = $s10 >> 6;
3713 // s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7));
3714 $s[28] = ($s10 >> 14) | ($s11 << 7);
3715 // s[29] = s11 >> 1;
3716 $s[29] = $s11 >> 1;
3717 // s[30] = s11 >> 9;
3718 $s[30] = $s11 >> 9;
3719 // s[31] = s11 >> 17;
3720 $s[31] = $s11 >> 17;
3721 return self::intArrayToString($s);
3722 }
3723
3724 /**
3725 * @param string $s
3726 * @return string
3727 */
3728 public static function sc25519_sq($s)
3729 {
3730 return self::sc25519_mul($s, $s);
3731 }
3732
3733 /**
3734 * @param string $s
3735 * @param int $n
3736 * @param string $a
3737 * @return string
3738 */
3739 public static function sc25519_sqmul($s, $n, $a)
3740 {
3741 for ($i = 0; $i < $n; ++$i) {
3742 $s = self::sc25519_sq($s);
3743 }
3744 return self::sc25519_mul($s, $a);
3745 }
3746
3747 /**
3748 * @param string $s
3749 * @return string
3750 */
3751 public static function sc25519_invert($s)
3752 {
3753 $_10 = self::sc25519_sq($s);
3754 $_11 = self::sc25519_mul($s, $_10);
3755 $_100 = self::sc25519_mul($s, $_11);
3756 $_1000 = self::sc25519_sq($_100);
3757 $_1010 = self::sc25519_mul($_10, $_1000);
3758 $_1011 = self::sc25519_mul($s, $_1010);
3759 $_10000 = self::sc25519_sq($_1000);
3760 $_10110 = self::sc25519_sq($_1011);
3761 $_100000 = self::sc25519_mul($_1010, $_10110);
3762 $_100110 = self::sc25519_mul($_10000, $_10110);
3763 $_1000000 = self::sc25519_sq($_100000);
3764 $_1010000 = self::sc25519_mul($_10000, $_1000000);
3765 $_1010011 = self::sc25519_mul($_11, $_1010000);
3766 $_1100011 = self::sc25519_mul($_10000, $_1010011);
3767 $_1100111 = self::sc25519_mul($_100, $_1100011);
3768 $_1101011 = self::sc25519_mul($_100, $_1100111);
3769 $_10010011 = self::sc25519_mul($_1000000, $_1010011);
3770 $_10010111 = self::sc25519_mul($_100, $_10010011);
3771 $_10111101 = self::sc25519_mul($_100110, $_10010111);
3772 $_11010011 = self::sc25519_mul($_10110, $_10111101);
3773 $_11100111 = self::sc25519_mul($_1010000, $_10010111);
3774 $_11101011 = self::sc25519_mul($_100, $_11100111);
3775 $_11110101 = self::sc25519_mul($_1010, $_11101011);
3776
3777 $recip = self::sc25519_mul($_1011, $_11110101);
3778 $recip = self::sc25519_sqmul($recip, 126, $_1010011);
3779 $recip = self::sc25519_sqmul($recip, 9, $_10);
3780 $recip = self::sc25519_mul($recip, $_11110101);
3781 $recip = self::sc25519_sqmul($recip, 7, $_1100111);
3782 $recip = self::sc25519_sqmul($recip, 9, $_11110101);
3783 $recip = self::sc25519_sqmul($recip, 11, $_10111101);
3784 $recip = self::sc25519_sqmul($recip, 8, $_11100111);
3785 $recip = self::sc25519_sqmul($recip, 9, $_1101011);
3786 $recip = self::sc25519_sqmul($recip, 6, $_1011);
3787 $recip = self::sc25519_sqmul($recip, 14, $_10010011);
3788 $recip = self::sc25519_sqmul($recip, 10, $_1100011);
3789 $recip = self::sc25519_sqmul($recip, 9, $_10010111);
3790 $recip = self::sc25519_sqmul($recip, 10, $_11110101);
3791 $recip = self::sc25519_sqmul($recip, 8, $_11010011);
3792 return self::sc25519_sqmul($recip, 8, $_11101011);
3793 }
3794
3795 /**
3796 * @param string $s
3797 * @return string
3798 */
3799 public static function clamp($s)
3800 {
3801 $s_ = self::stringToIntArray($s);
3802 $s_[0] &= 248;
3803 $s_[31] |= 64;
3804 $s_[31] &= 127;
3805 return self::intArrayToString($s_);
3806 }
3807
3808 /**
3809 * Ensure limbs are less than 28 bits long to prevent float promotion.
3810 *
3811 * This uses a constant-time conditional swap under the hood.
3812 *
3813 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
3814 * @return ParagonIE_Sodium_Core_Curve25519_Fe
3815 */
3816 public static function fe_normalize(ParagonIE_Sodium_Core_Curve25519_Fe $f)
3817 {
3818 $x = (PHP_INT_SIZE << 3) - 1; // 31 or 63
3819
3820 $g = self::fe_copy($f);
3821 $e = array(
3822 $g->e0, $g->e1, $g->e2, $g->e3, $g->e4,
3823 $g->e5, $g->e6, $g->e7, $g->e8, $g->e9
3824 );
3825 for ($i = 0; $i < 10; ++$i) {
3826 $mask = -(($e[$i] >> $x) & 1);
3827
3828 /*
3829 * Get two candidate normalized values for $e[$i], depending on the sign of $e[$i]:
3830 */
3831 $a = $e[$i] & 0x7ffffff;
3832 $b = -((-$e[$i]) & 0x7ffffff);
3833
3834 /*
3835 * Return the appropriate candidate value, based on the sign of the original input:
3836 *
3837 * The following is equivalent to this ternary:
3838 *
3839 * $e[$i] = (($e[$i] >> $x) & 1) ? $a : $b;
3840 *
3841 * Except what's written doesn't contain timing leaks.
3842 */
3843 $e[$i] = ($a ^ (($a ^ $b) & $mask));
3844 }
3845 $g->e0 = $e[0];
3846 $g->e1 = $e[1];
3847 $g->e2 = $e[2];
3848 $g->e3 = $e[3];
3849 $g->e4 = $e[4];
3850 $g->e5 = $e[5];
3851 $g->e6 = $e[6];
3852 $g->e7 = $e[7];
3853 $g->e8 = $e[8];
3854 $g->e9 = $e[9];
3855 return $g;
3856 }
3857}
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1