Completed
Push — develop ( 3424d9...5f5160 )
by
unknown
19:11
created
vendor/paragonie/sodium_compat/src/Core/Ristretto255.php 1 patch
Indentation   +699 added lines, -699 removed lines patch added patch discarded remove patch
@@ -5,703 +5,703 @@
 block discarded – undo
5 5
  */
6 6
 class ParagonIE_Sodium_Core_Ristretto255 extends ParagonIE_Sodium_Core_Ed25519
7 7
 {
8
-    const crypto_core_ristretto255_HASHBYTES = 64;
9
-    const HASH_SC_L = 48;
10
-    const CORE_H2C_SHA256 = 1;
11
-    const CORE_H2C_SHA512 = 2;
12
-
13
-    /**
14
-     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
15
-     * @param int $b
16
-     * @return ParagonIE_Sodium_Core_Curve25519_Fe
17
-     */
18
-    public static function fe_cneg(ParagonIE_Sodium_Core_Curve25519_Fe $f, $b)
19
-    {
20
-        $negf = self::fe_neg($f);
21
-        return self::fe_cmov($f, $negf, $b);
22
-    }
23
-
24
-    /**
25
-     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
26
-     * @return ParagonIE_Sodium_Core_Curve25519_Fe
27
-     * @throws SodiumException
28
-     */
29
-    public static function fe_abs(ParagonIE_Sodium_Core_Curve25519_Fe $f)
30
-    {
31
-        return self::fe_cneg($f, self::fe_isnegative($f));
32
-    }
33
-
34
-    /**
35
-     * Returns 0 if this field element results in all NUL bytes.
36
-     *
37
-     * @internal You should not use this directly from another application
38
-     *
39
-     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
40
-     * @return int
41
-     * @throws SodiumException
42
-     */
43
-    public static function fe_iszero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
44
-    {
45
-        static $zero;
46
-        if ($zero === null) {
47
-            $zero = str_repeat("\x00", 32);
48
-        }
49
-        /** @var string $zero */
50
-        $str = self::fe_tobytes($f);
51
-
52
-        $d = 0;
53
-        for ($i = 0; $i < 32; ++$i) {
54
-            $d |= self::chrToInt($str[$i]);
55
-        }
56
-        return (($d - 1) >> 31) & 1;
57
-    }
58
-
59
-
60
-    /**
61
-     * @param ParagonIE_Sodium_Core_Curve25519_Fe $u
62
-     * @param ParagonIE_Sodium_Core_Curve25519_Fe $v
63
-     * @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int}
64
-     *
65
-     * @throws SodiumException
66
-     */
67
-    public static function ristretto255_sqrt_ratio_m1(
68
-        ParagonIE_Sodium_Core_Curve25519_Fe $u,
69
-        ParagonIE_Sodium_Core_Curve25519_Fe $v
70
-    ) {
71
-        $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
72
-
73
-        $v3 = self::fe_mul(
74
-            self::fe_sq($v),
75
-            $v
76
-        ); /* v3 = v^3 */
77
-        $x = self::fe_mul(
78
-            self::fe_mul(
79
-                self::fe_sq($v3),
80
-                $u
81
-            ),
82
-            $v
83
-        ); /* x = uv^7 */
84
-
85
-        $x = self::fe_mul(
86
-            self::fe_mul(
87
-                self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */
88
-                $v3
89
-            ),
90
-            $u
91
-        ); /* x = uv^3(uv^7)^((q-5)/8) */
92
-
93
-        $vxx = self::fe_mul(
94
-            self::fe_sq($x),
95
-            $v
96
-        ); /* vx^2 */
97
-
98
-        $m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */
99
-        $p_root_check = self::fe_add($vxx, $u); /* vx^2+u */
100
-        $f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */
101
-        $f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */
102
-
103
-        $has_m_root = self::fe_iszero($m_root_check);
104
-        $has_p_root = self::fe_iszero($p_root_check);
105
-        $has_f_root = self::fe_iszero($f_root_check);
106
-
107
-        $x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */
108
-
109
-        $x = self::fe_abs(
110
-            self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root)
111
-        );
112
-        return array(
113
-            'x' => $x,
114
-            'nonsquare' => $has_m_root | $has_p_root
115
-        );
116
-    }
117
-
118
-    /**
119
-     * @param string $s
120
-     * @return int
121
-     * @throws SodiumException
122
-     */
123
-    public static function ristretto255_point_is_canonical($s)
124
-    {
125
-        $c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f;
126
-        for ($i = 30; $i > 0; --$i) {
127
-            $c |= self::chrToInt($s[$i]) ^ 0xff;
128
-        }
129
-        $c = ($c - 1) >> 8;
130
-        $d = (0xed - 1 - self::chrToInt($s[0])) >> 8;
131
-        $e = self::chrToInt($s[31]) >> 7;
132
-
133
-        return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1);
134
-    }
135
-
136
-    /**
137
-     * @param string $s
138
-     * @param bool $skipCanonicalCheck
139
-     * @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int}
140
-     * @throws SodiumException
141
-     */
142
-    public static function ristretto255_frombytes($s, $skipCanonicalCheck = false)
143
-    {
144
-        if (!$skipCanonicalCheck) {
145
-            if (!self::ristretto255_point_is_canonical($s)) {
146
-                throw new SodiumException('S is not canonical');
147
-            }
148
-        }
149
-
150
-        $s_ = self::fe_frombytes($s);
151
-        $ss = self::fe_sq($s_); /* ss = s^2 */
152
-
153
-        $u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */
154
-        $u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */
155
-
156
-        $u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */
157
-        $u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */
158
-
159
-        $v = self::fe_mul(
160
-            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d),
161
-            $u1u1
162
-        ); /* v = d*u1^2 */
163
-        $v = self::fe_neg($v); /* v = -d*u1^2 */
164
-        $v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */
165
-        $v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */
166
-
167
-        // fe25519_1(one);
168
-        // notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2);
169
-        $one = self::fe_1();
170
-        $result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2);
171
-        $inv_sqrt = $result['x'];
172
-        $notsquare = $result['nonsquare'];
173
-
174
-        $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();
175
-
176
-        $h->X = self::fe_mul($inv_sqrt, $u2);
177
-        $h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v);
178
-
179
-        $h->X = self::fe_mul($h->X, $s_);
180
-        $h->X = self::fe_abs(
181
-            self::fe_add($h->X, $h->X)
182
-        );
183
-        $h->Y = self::fe_mul($u1, $h->Y);
184
-        $h->Z = self::fe_1();
185
-        $h->T = self::fe_mul($h->X, $h->Y);
186
-
187
-        $res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y));
188
-        return array('h' => $h, 'res' => $res);
189
-    }
190
-
191
-    /**
192
-     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
193
-     * @return string
194
-     * @throws SodiumException
195
-     */
196
-    public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
197
-    {
198
-        $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
199
-        $invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd);
200
-
201
-        $u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */
202
-        $zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */
203
-        $u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */
204
-        $u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */
205
-
206
-        $u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */
207
-        $one = self::fe_1();
208
-
209
-        // fe25519_1(one);
210
-        // (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2);
211
-        $result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2);
212
-        $inv_sqrt = $result['x'];
213
-
214
-        $den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */
215
-        $den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */
216
-        $z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */
217
-
218
-        $ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */
219
-        $iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */
220
-        $eden = self::fe_mul($den1, $invsqrtamd);
221
-
222
-        $t_z_inv =  self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */
223
-        $rotate = self::fe_isnegative($t_z_inv);
224
-
225
-        $x_ = self::fe_copy($h->X);
226
-        $y_ = self::fe_copy($h->Y);
227
-        $den_inv = self::fe_copy($den2);
228
-
229
-        $x_ = self::fe_cmov($x_, $iy, $rotate);
230
-        $y_ = self::fe_cmov($y_, $ix, $rotate);
231
-        $den_inv = self::fe_cmov($den_inv, $eden, $rotate);
232
-
233
-        $x_z_inv = self::fe_mul($x_, $z_inv);
234
-        $y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv));
235
-
236
-
237
-        // fe25519_sub(s_, h->Z, y_);
238
-        // fe25519_mul(s_, den_inv, s_);
239
-        // fe25519_abs(s_, s_);
240
-        // fe25519_tobytes(s, s_);
241
-        return self::fe_tobytes(
242
-            self::fe_abs(
243
-                self::fe_mul(
244
-                    $den_inv,
245
-                    self::fe_sub($h->Z, $y_)
246
-                )
247
-            )
248
-        );
249
-    }
250
-
251
-    /**
252
-     * @param ParagonIE_Sodium_Core_Curve25519_Fe $t
253
-     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
254
-     *
255
-     * @throws SodiumException
256
-     */
257
-    public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t)
258
-    {
259
-        $sqrtm1   = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
260
-        $onemsqd  = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd);
261
-        $d        = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
262
-        $sqdmone  = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone);
263
-        $sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1);
264
-
265
-        $one = self::fe_1();
266
-        $r   = self::fe_mul($sqrtm1, self::fe_sq($t));         /* r = sqrt(-1)*t^2 */
267
-        $u   = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */
268
-        $c   = self::fe_neg(self::fe_1());                     /* c = -1 */
269
-        $rpd = self::fe_add($r, $d);                           /* rpd = r+d */
270
-
271
-        $v = self::fe_mul(
272
-            self::fe_sub(
273
-                $c,
274
-                self::fe_mul($r, $d)
275
-            ),
276
-            $rpd
277
-        ); /* v = (c-r*d)*(r+d) */
278
-
279
-        $result = self::ristretto255_sqrt_ratio_m1($u, $v);
280
-        $s = $result['x'];
281
-        $wasnt_square = 1 - $result['nonsquare'];
282
-
283
-        $s_prime = self::fe_neg(
284
-            self::fe_abs(
285
-                self::fe_mul($s, $t)
286
-            )
287
-        ); /* s_prime = -|s*t| */
288
-        $s = self::fe_cmov($s, $s_prime, $wasnt_square);
289
-        $c = self::fe_cmov($c, $r, $wasnt_square);
290
-
291
-        // fe25519_sub(n, r, one);            /* n = r-1 */
292
-        // fe25519_mul(n, n, c);              /* n = c*(r-1) */
293
-        // fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */
294
-        // fe25519_sub(n, n, v);              /* n =  c*(r-1)*(d-1)^2-v */
295
-        $n = self::fe_sub(
296
-            self::fe_mul(
297
-                self::fe_mul(
298
-                    self::fe_sub($r, $one),
299
-                    $c
300
-                ),
301
-                $sqdmone
302
-            ),
303
-            $v
304
-        ); /* n =  c*(r-1)*(d-1)^2-v */
305
-
306
-        $w0 = self::fe_mul(
307
-            self::fe_add($s, $s),
308
-            $v
309
-        ); /* w0 = 2s*v */
310
-
311
-        $w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */
312
-        $ss = self::fe_sq($s); /* ss = s^2 */
313
-        $w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */
314
-        $w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */
315
-
316
-        return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
317
-            self::fe_mul($w0, $w3),
318
-            self::fe_mul($w2, $w1),
319
-            self::fe_mul($w1, $w3),
320
-            self::fe_mul($w0, $w2)
321
-        );
322
-    }
323
-
324
-    /**
325
-     * @param string $h
326
-     * @return string
327
-     * @throws SodiumException
328
-     */
329
-    public static function ristretto255_from_hash($h)
330
-    {
331
-        if (self::strlen($h) !== 64) {
332
-            throw new SodiumException('Hash must be 64 bytes');
333
-        }
334
-        //fe25519_frombytes(r0, h);
335
-        //fe25519_frombytes(r1, h + 32);
336
-        $r0 = self::fe_frombytes(self::substr($h, 0, 32));
337
-        $r1 = self::fe_frombytes(self::substr($h, 32, 32));
338
-
339
-        //ristretto255_elligator(&p0, r0);
340
-        //ristretto255_elligator(&p1, r1);
341
-        $p0 = self::ristretto255_elligator($r0);
342
-        $p1 = self::ristretto255_elligator($r1);
343
-
344
-        //ge25519_p3_to_cached(&p1_cached, &p1);
345
-        //ge25519_add_cached(&p_p1p1, &p0, &p1_cached);
346
-        $p_p1p1 = self::ge_add(
347
-            $p0,
348
-            self::ge_p3_to_cached($p1)
349
-        );
350
-
351
-        //ge25519_p1p1_to_p3(&p, &p_p1p1);
352
-        //ristretto255_p3_tobytes(s, &p);
353
-        return self::ristretto255_p3_tobytes(
354
-            self::ge_p1p1_to_p3($p_p1p1)
355
-        );
356
-    }
357
-
358
-    /**
359
-     * @param string $p
360
-     * @return int
361
-     * @throws SodiumException
362
-     */
363
-    public static function is_valid_point($p)
364
-    {
365
-        $result = self::ristretto255_frombytes($p);
366
-        if ($result['res'] !== 0) {
367
-            return 0;
368
-        }
369
-        return 1;
370
-    }
371
-
372
-    /**
373
-     * @param string $p
374
-     * @param string $q
375
-     * @return string
376
-     * @throws SodiumException
377
-     */
378
-    public static function ristretto255_add($p, $q)
379
-    {
380
-        $p_res = self::ristretto255_frombytes($p);
381
-        $q_res = self::ristretto255_frombytes($q);
382
-        if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
383
-            throw new SodiumException('Could not add points');
384
-        }
385
-        $p_p3 = $p_res['h'];
386
-        $q_p3 = $q_res['h'];
387
-        $q_cached = self::ge_p3_to_cached($q_p3);
388
-        $r_p1p1 = self::ge_add($p_p3, $q_cached);
389
-        $r_p3 = self::ge_p1p1_to_p3($r_p1p1);
390
-        return self::ristretto255_p3_tobytes($r_p3);
391
-    }
392
-
393
-    /**
394
-     * @param string $p
395
-     * @param string $q
396
-     * @return string
397
-     * @throws SodiumException
398
-     */
399
-    public static function ristretto255_sub($p, $q)
400
-    {
401
-        $p_res = self::ristretto255_frombytes($p);
402
-        $q_res = self::ristretto255_frombytes($q);
403
-        if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
404
-            throw new SodiumException('Could not add points');
405
-        }
406
-        $p_p3 = $p_res['h'];
407
-        $q_p3 = $q_res['h'];
408
-        $q_cached = self::ge_p3_to_cached($q_p3);
409
-        $r_p1p1 = self::ge_sub($p_p3, $q_cached);
410
-        $r_p3 = self::ge_p1p1_to_p3($r_p1p1);
411
-        return self::ristretto255_p3_tobytes($r_p3);
412
-    }
413
-
414
-
415
-    /**
416
-     * @param int $hLen
417
-     * @param ?string $ctx
418
-     * @param string $msg
419
-     * @return string
420
-     * @throws SodiumException
421
-     * @psalm-suppress PossiblyInvalidArgument hash API
422
-     */
423
-    protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg)
424
-    {
425
-        $h = array_fill(0, $hLen, 0);
426
-        $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
427
-        if ($hLen > 0xff) {
428
-            throw new SodiumException('Hash must be less than 256 bytes');
429
-        }
430
-
431
-        if ($ctx_len > 0xff) {
432
-            $st = hash_init('sha256');
433
-            self::hash_update($st, "H2C-OVERSIZE-DST-");
434
-            self::hash_update($st, $ctx);
435
-            $ctx = hash_final($st, true);
436
-            $ctx_len = 32;
437
-        }
438
-        $t = array(0, $hLen, 0);
439
-        $ux = str_repeat("\0", 64);
440
-        $st = hash_init('sha256');
441
-        self::hash_update($st, $ux);
442
-        self::hash_update($st, $msg);
443
-        self::hash_update($st, self::intArrayToString($t));
444
-        self::hash_update($st, $ctx);
445
-        self::hash_update($st, self::intToChr($ctx_len));
446
-        $u0 = hash_final($st, true);
447
-
448
-        for ($i = 0; $i < $hLen; $i += 64) {
449
-            $ux = self::xorStrings($ux, $u0);
450
-            ++$t[2];
451
-            $st = hash_init('sha256');
452
-            self::hash_update($st, $ux);
453
-            self::hash_update($st, self::intToChr($t[2]));
454
-            self::hash_update($st, $ctx);
455
-            self::hash_update($st, self::intToChr($ctx_len));
456
-            $ux = hash_final($st, true);
457
-            $amount = min($hLen - $i, 64);
458
-            for ($j = 0; $j < $amount; ++$j) {
459
-                $h[$i + $j] = self::chrToInt($ux[$i]);
460
-            }
461
-        }
462
-        return self::intArrayToString(array_slice($h, 0, $hLen));
463
-    }
464
-
465
-    /**
466
-     * @param int $hLen
467
-     * @param ?string $ctx
468
-     * @param string $msg
469
-     * @return string
470
-     * @throws SodiumException
471
-     * @psalm-suppress PossiblyInvalidArgument hash API
472
-     */
473
-    protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg)
474
-    {
475
-        $h = array_fill(0, $hLen, 0);
476
-        $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
477
-        if ($hLen > 0xff) {
478
-            throw new SodiumException('Hash must be less than 256 bytes');
479
-        }
480
-
481
-        if ($ctx_len > 0xff) {
482
-            $st = hash_init('sha256');
483
-            self::hash_update($st, "H2C-OVERSIZE-DST-");
484
-            self::hash_update($st, $ctx);
485
-            $ctx = hash_final($st, true);
486
-            $ctx_len = 32;
487
-        }
488
-        $t = array(0, $hLen, 0);
489
-        $ux = str_repeat("\0", 128);
490
-        $st = hash_init('sha512');
491
-        self::hash_update($st, $ux);
492
-        self::hash_update($st, $msg);
493
-        self::hash_update($st, self::intArrayToString($t));
494
-        self::hash_update($st, $ctx);
495
-        self::hash_update($st, self::intToChr($ctx_len));
496
-        $u0 = hash_final($st, true);
497
-
498
-        for ($i = 0; $i < $hLen; $i += 128) {
499
-            $ux = self::xorStrings($ux, $u0);
500
-            ++$t[2];
501
-            $st = hash_init('sha512');
502
-            self::hash_update($st, $ux);
503
-            self::hash_update($st, self::intToChr($t[2]));
504
-            self::hash_update($st, $ctx);
505
-            self::hash_update($st, self::intToChr($ctx_len));
506
-            $ux = hash_final($st, true);
507
-            $amount = min($hLen - $i, 128);
508
-            for ($j = 0; $j < $amount; ++$j) {
509
-                $h[$i + $j] = self::chrToInt($ux[$i]);
510
-            }
511
-        }
512
-        return self::intArrayToString(array_slice($h, 0, $hLen));
513
-    }
514
-
515
-    /**
516
-     * @param int $hLen
517
-     * @param ?string $ctx
518
-     * @param string $msg
519
-     * @param int $hash_alg
520
-     * @return string
521
-     * @throws SodiumException
522
-     */
523
-    public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg)
524
-    {
525
-        switch ($hash_alg) {
526
-            case self::CORE_H2C_SHA256:
527
-                return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg);
528
-            case self::CORE_H2C_SHA512:
529
-                return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg);
530
-            default:
531
-                throw new SodiumException('Invalid H2C hash algorithm');
532
-        }
533
-    }
534
-
535
-    /**
536
-     * @param ?string $ctx
537
-     * @param string $msg
538
-     * @param int $hash_alg
539
-     * @return string
540
-     * @throws SodiumException
541
-     */
542
-    protected static function _string_to_element($ctx, $msg, $hash_alg)
543
-    {
544
-        return self::ristretto255_from_hash(
545
-            self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg)
546
-        );
547
-    }
548
-
549
-    /**
550
-     * @return string
551
-     * @throws SodiumException
552
-     * @throws Exception
553
-     */
554
-    public static function ristretto255_random()
555
-    {
556
-        return self::ristretto255_from_hash(
557
-            ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES)
558
-        );
559
-    }
560
-
561
-    /**
562
-     * @return string
563
-     * @throws SodiumException
564
-     */
565
-    public static function ristretto255_scalar_random()
566
-    {
567
-        return self::scalar_random();
568
-    }
569
-
570
-    /**
571
-     * @param string $s
572
-     * @return string
573
-     * @throws SodiumException
574
-     */
575
-    public static function ristretto255_scalar_complement($s)
576
-    {
577
-        return self::scalar_complement($s);
578
-    }
579
-
580
-
581
-    /**
582
-     * @param string $s
583
-     * @return string
584
-     */
585
-    public static function ristretto255_scalar_invert($s)
586
-    {
587
-        return self::sc25519_invert($s);
588
-    }
589
-
590
-    /**
591
-     * @param string $s
592
-     * @return string
593
-     * @throws SodiumException
594
-     */
595
-    public static function ristretto255_scalar_negate($s)
596
-    {
597
-        return self::scalar_negate($s);
598
-    }
599
-
600
-    /**
601
-     * @param string $x
602
-     * @param string $y
603
-     * @return string
604
-     */
605
-    public static function ristretto255_scalar_add($x, $y)
606
-    {
607
-        return self::scalar_add($x, $y);
608
-    }
609
-
610
-    /**
611
-     * @param string $x
612
-     * @param string $y
613
-     * @return string
614
-     */
615
-    public static function ristretto255_scalar_sub($x, $y)
616
-    {
617
-        return self::scalar_sub($x, $y);
618
-    }
619
-
620
-    /**
621
-     * @param string $x
622
-     * @param string $y
623
-     * @return string
624
-     */
625
-    public static function ristretto255_scalar_mul($x, $y)
626
-    {
627
-        return self::sc25519_mul($x, $y);
628
-    }
629
-
630
-    /**
631
-     * @param string $ctx
632
-     * @param string $msg
633
-     * @param int $hash_alg
634
-     * @return string
635
-     * @throws SodiumException
636
-     */
637
-    public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg)
638
-    {
639
-        $h = array_fill(0, 64, 0);
640
-        $h_be = self::stringToIntArray(
641
-            self::h2c_string_to_hash(
642
-                self::HASH_SC_L, $ctx, $msg, $hash_alg
643
-            )
644
-        );
645
-
646
-        for ($i = 0; $i < self::HASH_SC_L; ++$i) {
647
-            $h[$i] = $h_be[self::HASH_SC_L - 1 - $i];
648
-        }
649
-        return self::ristretto255_scalar_reduce(self::intArrayToString($h));
650
-    }
651
-
652
-    /**
653
-     * @param string $s
654
-     * @return string
655
-     */
656
-    public static function ristretto255_scalar_reduce($s)
657
-    {
658
-        return self::sc_reduce($s);
659
-    }
660
-
661
-    /**
662
-     * @param string $n
663
-     * @param string $p
664
-     * @return string
665
-     * @throws SodiumException
666
-     */
667
-    public static function scalarmult_ristretto255($n, $p)
668
-    {
669
-        if (self::strlen($n) !== 32) {
670
-            throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.');
671
-        }
672
-        if (self::strlen($p) !== 32) {
673
-            throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.');
674
-        }
675
-        $result = self::ristretto255_frombytes($p);
676
-        if ($result['res'] !== 0) {
677
-            throw new SodiumException('Could not multiply points');
678
-        }
679
-        $P = $result['h'];
680
-
681
-        $t = self::stringToIntArray($n);
682
-        $t[31] &= 0x7f;
683
-        $Q = self::ge_scalarmult(self::intArrayToString($t), $P);
684
-        $q = self::ristretto255_p3_tobytes($Q);
685
-        if (ParagonIE_Sodium_Compat::is_zero($q)) {
686
-            throw new SodiumException('An unknown error has occurred');
687
-        }
688
-        return $q;
689
-    }
690
-
691
-    /**
692
-     * @param string $n
693
-     * @return string
694
-     * @throws SodiumException
695
-     */
696
-    public static function scalarmult_ristretto255_base($n)
697
-    {
698
-        $t = self::stringToIntArray($n);
699
-        $t[31] &= 0x7f;
700
-        $Q = self::ge_scalarmult_base(self::intArrayToString($t));
701
-        $q = self::ristretto255_p3_tobytes($Q);
702
-        if (ParagonIE_Sodium_Compat::is_zero($q)) {
703
-            throw new SodiumException('An unknown error has occurred');
704
-        }
705
-        return $q;
706
-    }
8
+	const crypto_core_ristretto255_HASHBYTES = 64;
9
+	const HASH_SC_L = 48;
10
+	const CORE_H2C_SHA256 = 1;
11
+	const CORE_H2C_SHA512 = 2;
12
+
13
+	/**
14
+	 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
15
+	 * @param int $b
16
+	 * @return ParagonIE_Sodium_Core_Curve25519_Fe
17
+	 */
18
+	public static function fe_cneg(ParagonIE_Sodium_Core_Curve25519_Fe $f, $b)
19
+	{
20
+		$negf = self::fe_neg($f);
21
+		return self::fe_cmov($f, $negf, $b);
22
+	}
23
+
24
+	/**
25
+	 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
26
+	 * @return ParagonIE_Sodium_Core_Curve25519_Fe
27
+	 * @throws SodiumException
28
+	 */
29
+	public static function fe_abs(ParagonIE_Sodium_Core_Curve25519_Fe $f)
30
+	{
31
+		return self::fe_cneg($f, self::fe_isnegative($f));
32
+	}
33
+
34
+	/**
35
+	 * Returns 0 if this field element results in all NUL bytes.
36
+	 *
37
+	 * @internal You should not use this directly from another application
38
+	 *
39
+	 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
40
+	 * @return int
41
+	 * @throws SodiumException
42
+	 */
43
+	public static function fe_iszero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
44
+	{
45
+		static $zero;
46
+		if ($zero === null) {
47
+			$zero = str_repeat("\x00", 32);
48
+		}
49
+		/** @var string $zero */
50
+		$str = self::fe_tobytes($f);
51
+
52
+		$d = 0;
53
+		for ($i = 0; $i < 32; ++$i) {
54
+			$d |= self::chrToInt($str[$i]);
55
+		}
56
+		return (($d - 1) >> 31) & 1;
57
+	}
58
+
59
+
60
+	/**
61
+	 * @param ParagonIE_Sodium_Core_Curve25519_Fe $u
62
+	 * @param ParagonIE_Sodium_Core_Curve25519_Fe $v
63
+	 * @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int}
64
+	 *
65
+	 * @throws SodiumException
66
+	 */
67
+	public static function ristretto255_sqrt_ratio_m1(
68
+		ParagonIE_Sodium_Core_Curve25519_Fe $u,
69
+		ParagonIE_Sodium_Core_Curve25519_Fe $v
70
+	) {
71
+		$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
72
+
73
+		$v3 = self::fe_mul(
74
+			self::fe_sq($v),
75
+			$v
76
+		); /* v3 = v^3 */
77
+		$x = self::fe_mul(
78
+			self::fe_mul(
79
+				self::fe_sq($v3),
80
+				$u
81
+			),
82
+			$v
83
+		); /* x = uv^7 */
84
+
85
+		$x = self::fe_mul(
86
+			self::fe_mul(
87
+				self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */
88
+				$v3
89
+			),
90
+			$u
91
+		); /* x = uv^3(uv^7)^((q-5)/8) */
92
+
93
+		$vxx = self::fe_mul(
94
+			self::fe_sq($x),
95
+			$v
96
+		); /* vx^2 */
97
+
98
+		$m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */
99
+		$p_root_check = self::fe_add($vxx, $u); /* vx^2+u */
100
+		$f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */
101
+		$f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */
102
+
103
+		$has_m_root = self::fe_iszero($m_root_check);
104
+		$has_p_root = self::fe_iszero($p_root_check);
105
+		$has_f_root = self::fe_iszero($f_root_check);
106
+
107
+		$x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */
108
+
109
+		$x = self::fe_abs(
110
+			self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root)
111
+		);
112
+		return array(
113
+			'x' => $x,
114
+			'nonsquare' => $has_m_root | $has_p_root
115
+		);
116
+	}
117
+
118
+	/**
119
+	 * @param string $s
120
+	 * @return int
121
+	 * @throws SodiumException
122
+	 */
123
+	public static function ristretto255_point_is_canonical($s)
124
+	{
125
+		$c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f;
126
+		for ($i = 30; $i > 0; --$i) {
127
+			$c |= self::chrToInt($s[$i]) ^ 0xff;
128
+		}
129
+		$c = ($c - 1) >> 8;
130
+		$d = (0xed - 1 - self::chrToInt($s[0])) >> 8;
131
+		$e = self::chrToInt($s[31]) >> 7;
132
+
133
+		return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1);
134
+	}
135
+
136
+	/**
137
+	 * @param string $s
138
+	 * @param bool $skipCanonicalCheck
139
+	 * @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int}
140
+	 * @throws SodiumException
141
+	 */
142
+	public static function ristretto255_frombytes($s, $skipCanonicalCheck = false)
143
+	{
144
+		if (!$skipCanonicalCheck) {
145
+			if (!self::ristretto255_point_is_canonical($s)) {
146
+				throw new SodiumException('S is not canonical');
147
+			}
148
+		}
149
+
150
+		$s_ = self::fe_frombytes($s);
151
+		$ss = self::fe_sq($s_); /* ss = s^2 */
152
+
153
+		$u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */
154
+		$u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */
155
+
156
+		$u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */
157
+		$u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */
158
+
159
+		$v = self::fe_mul(
160
+			ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d),
161
+			$u1u1
162
+		); /* v = d*u1^2 */
163
+		$v = self::fe_neg($v); /* v = -d*u1^2 */
164
+		$v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */
165
+		$v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */
166
+
167
+		// fe25519_1(one);
168
+		// notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2);
169
+		$one = self::fe_1();
170
+		$result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2);
171
+		$inv_sqrt = $result['x'];
172
+		$notsquare = $result['nonsquare'];
173
+
174
+		$h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();
175
+
176
+		$h->X = self::fe_mul($inv_sqrt, $u2);
177
+		$h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v);
178
+
179
+		$h->X = self::fe_mul($h->X, $s_);
180
+		$h->X = self::fe_abs(
181
+			self::fe_add($h->X, $h->X)
182
+		);
183
+		$h->Y = self::fe_mul($u1, $h->Y);
184
+		$h->Z = self::fe_1();
185
+		$h->T = self::fe_mul($h->X, $h->Y);
186
+
187
+		$res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y));
188
+		return array('h' => $h, 'res' => $res);
189
+	}
190
+
191
+	/**
192
+	 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
193
+	 * @return string
194
+	 * @throws SodiumException
195
+	 */
196
+	public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
197
+	{
198
+		$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
199
+		$invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd);
200
+
201
+		$u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */
202
+		$zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */
203
+		$u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */
204
+		$u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */
205
+
206
+		$u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */
207
+		$one = self::fe_1();
208
+
209
+		// fe25519_1(one);
210
+		// (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2);
211
+		$result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2);
212
+		$inv_sqrt = $result['x'];
213
+
214
+		$den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */
215
+		$den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */
216
+		$z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */
217
+
218
+		$ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */
219
+		$iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */
220
+		$eden = self::fe_mul($den1, $invsqrtamd);
221
+
222
+		$t_z_inv =  self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */
223
+		$rotate = self::fe_isnegative($t_z_inv);
224
+
225
+		$x_ = self::fe_copy($h->X);
226
+		$y_ = self::fe_copy($h->Y);
227
+		$den_inv = self::fe_copy($den2);
228
+
229
+		$x_ = self::fe_cmov($x_, $iy, $rotate);
230
+		$y_ = self::fe_cmov($y_, $ix, $rotate);
231
+		$den_inv = self::fe_cmov($den_inv, $eden, $rotate);
232
+
233
+		$x_z_inv = self::fe_mul($x_, $z_inv);
234
+		$y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv));
235
+
236
+
237
+		// fe25519_sub(s_, h->Z, y_);
238
+		// fe25519_mul(s_, den_inv, s_);
239
+		// fe25519_abs(s_, s_);
240
+		// fe25519_tobytes(s, s_);
241
+		return self::fe_tobytes(
242
+			self::fe_abs(
243
+				self::fe_mul(
244
+					$den_inv,
245
+					self::fe_sub($h->Z, $y_)
246
+				)
247
+			)
248
+		);
249
+	}
250
+
251
+	/**
252
+	 * @param ParagonIE_Sodium_Core_Curve25519_Fe $t
253
+	 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
254
+	 *
255
+	 * @throws SodiumException
256
+	 */
257
+	public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t)
258
+	{
259
+		$sqrtm1   = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
260
+		$onemsqd  = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd);
261
+		$d        = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
262
+		$sqdmone  = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone);
263
+		$sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1);
264
+
265
+		$one = self::fe_1();
266
+		$r   = self::fe_mul($sqrtm1, self::fe_sq($t));         /* r = sqrt(-1)*t^2 */
267
+		$u   = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */
268
+		$c   = self::fe_neg(self::fe_1());                     /* c = -1 */
269
+		$rpd = self::fe_add($r, $d);                           /* rpd = r+d */
270
+
271
+		$v = self::fe_mul(
272
+			self::fe_sub(
273
+				$c,
274
+				self::fe_mul($r, $d)
275
+			),
276
+			$rpd
277
+		); /* v = (c-r*d)*(r+d) */
278
+
279
+		$result = self::ristretto255_sqrt_ratio_m1($u, $v);
280
+		$s = $result['x'];
281
+		$wasnt_square = 1 - $result['nonsquare'];
282
+
283
+		$s_prime = self::fe_neg(
284
+			self::fe_abs(
285
+				self::fe_mul($s, $t)
286
+			)
287
+		); /* s_prime = -|s*t| */
288
+		$s = self::fe_cmov($s, $s_prime, $wasnt_square);
289
+		$c = self::fe_cmov($c, $r, $wasnt_square);
290
+
291
+		// fe25519_sub(n, r, one);            /* n = r-1 */
292
+		// fe25519_mul(n, n, c);              /* n = c*(r-1) */
293
+		// fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */
294
+		// fe25519_sub(n, n, v);              /* n =  c*(r-1)*(d-1)^2-v */
295
+		$n = self::fe_sub(
296
+			self::fe_mul(
297
+				self::fe_mul(
298
+					self::fe_sub($r, $one),
299
+					$c
300
+				),
301
+				$sqdmone
302
+			),
303
+			$v
304
+		); /* n =  c*(r-1)*(d-1)^2-v */
305
+
306
+		$w0 = self::fe_mul(
307
+			self::fe_add($s, $s),
308
+			$v
309
+		); /* w0 = 2s*v */
310
+
311
+		$w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */
312
+		$ss = self::fe_sq($s); /* ss = s^2 */
313
+		$w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */
314
+		$w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */
315
+
316
+		return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
317
+			self::fe_mul($w0, $w3),
318
+			self::fe_mul($w2, $w1),
319
+			self::fe_mul($w1, $w3),
320
+			self::fe_mul($w0, $w2)
321
+		);
322
+	}
323
+
324
+	/**
325
+	 * @param string $h
326
+	 * @return string
327
+	 * @throws SodiumException
328
+	 */
329
+	public static function ristretto255_from_hash($h)
330
+	{
331
+		if (self::strlen($h) !== 64) {
332
+			throw new SodiumException('Hash must be 64 bytes');
333
+		}
334
+		//fe25519_frombytes(r0, h);
335
+		//fe25519_frombytes(r1, h + 32);
336
+		$r0 = self::fe_frombytes(self::substr($h, 0, 32));
337
+		$r1 = self::fe_frombytes(self::substr($h, 32, 32));
338
+
339
+		//ristretto255_elligator(&p0, r0);
340
+		//ristretto255_elligator(&p1, r1);
341
+		$p0 = self::ristretto255_elligator($r0);
342
+		$p1 = self::ristretto255_elligator($r1);
343
+
344
+		//ge25519_p3_to_cached(&p1_cached, &p1);
345
+		//ge25519_add_cached(&p_p1p1, &p0, &p1_cached);
346
+		$p_p1p1 = self::ge_add(
347
+			$p0,
348
+			self::ge_p3_to_cached($p1)
349
+		);
350
+
351
+		//ge25519_p1p1_to_p3(&p, &p_p1p1);
352
+		//ristretto255_p3_tobytes(s, &p);
353
+		return self::ristretto255_p3_tobytes(
354
+			self::ge_p1p1_to_p3($p_p1p1)
355
+		);
356
+	}
357
+
358
+	/**
359
+	 * @param string $p
360
+	 * @return int
361
+	 * @throws SodiumException
362
+	 */
363
+	public static function is_valid_point($p)
364
+	{
365
+		$result = self::ristretto255_frombytes($p);
366
+		if ($result['res'] !== 0) {
367
+			return 0;
368
+		}
369
+		return 1;
370
+	}
371
+
372
+	/**
373
+	 * @param string $p
374
+	 * @param string $q
375
+	 * @return string
376
+	 * @throws SodiumException
377
+	 */
378
+	public static function ristretto255_add($p, $q)
379
+	{
380
+		$p_res = self::ristretto255_frombytes($p);
381
+		$q_res = self::ristretto255_frombytes($q);
382
+		if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
383
+			throw new SodiumException('Could not add points');
384
+		}
385
+		$p_p3 = $p_res['h'];
386
+		$q_p3 = $q_res['h'];
387
+		$q_cached = self::ge_p3_to_cached($q_p3);
388
+		$r_p1p1 = self::ge_add($p_p3, $q_cached);
389
+		$r_p3 = self::ge_p1p1_to_p3($r_p1p1);
390
+		return self::ristretto255_p3_tobytes($r_p3);
391
+	}
392
+
393
+	/**
394
+	 * @param string $p
395
+	 * @param string $q
396
+	 * @return string
397
+	 * @throws SodiumException
398
+	 */
399
+	public static function ristretto255_sub($p, $q)
400
+	{
401
+		$p_res = self::ristretto255_frombytes($p);
402
+		$q_res = self::ristretto255_frombytes($q);
403
+		if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
404
+			throw new SodiumException('Could not add points');
405
+		}
406
+		$p_p3 = $p_res['h'];
407
+		$q_p3 = $q_res['h'];
408
+		$q_cached = self::ge_p3_to_cached($q_p3);
409
+		$r_p1p1 = self::ge_sub($p_p3, $q_cached);
410
+		$r_p3 = self::ge_p1p1_to_p3($r_p1p1);
411
+		return self::ristretto255_p3_tobytes($r_p3);
412
+	}
413
+
414
+
415
+	/**
416
+	 * @param int $hLen
417
+	 * @param ?string $ctx
418
+	 * @param string $msg
419
+	 * @return string
420
+	 * @throws SodiumException
421
+	 * @psalm-suppress PossiblyInvalidArgument hash API
422
+	 */
423
+	protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg)
424
+	{
425
+		$h = array_fill(0, $hLen, 0);
426
+		$ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
427
+		if ($hLen > 0xff) {
428
+			throw new SodiumException('Hash must be less than 256 bytes');
429
+		}
430
+
431
+		if ($ctx_len > 0xff) {
432
+			$st = hash_init('sha256');
433
+			self::hash_update($st, "H2C-OVERSIZE-DST-");
434
+			self::hash_update($st, $ctx);
435
+			$ctx = hash_final($st, true);
436
+			$ctx_len = 32;
437
+		}
438
+		$t = array(0, $hLen, 0);
439
+		$ux = str_repeat("\0", 64);
440
+		$st = hash_init('sha256');
441
+		self::hash_update($st, $ux);
442
+		self::hash_update($st, $msg);
443
+		self::hash_update($st, self::intArrayToString($t));
444
+		self::hash_update($st, $ctx);
445
+		self::hash_update($st, self::intToChr($ctx_len));
446
+		$u0 = hash_final($st, true);
447
+
448
+		for ($i = 0; $i < $hLen; $i += 64) {
449
+			$ux = self::xorStrings($ux, $u0);
450
+			++$t[2];
451
+			$st = hash_init('sha256');
452
+			self::hash_update($st, $ux);
453
+			self::hash_update($st, self::intToChr($t[2]));
454
+			self::hash_update($st, $ctx);
455
+			self::hash_update($st, self::intToChr($ctx_len));
456
+			$ux = hash_final($st, true);
457
+			$amount = min($hLen - $i, 64);
458
+			for ($j = 0; $j < $amount; ++$j) {
459
+				$h[$i + $j] = self::chrToInt($ux[$i]);
460
+			}
461
+		}
462
+		return self::intArrayToString(array_slice($h, 0, $hLen));
463
+	}
464
+
465
+	/**
466
+	 * @param int $hLen
467
+	 * @param ?string $ctx
468
+	 * @param string $msg
469
+	 * @return string
470
+	 * @throws SodiumException
471
+	 * @psalm-suppress PossiblyInvalidArgument hash API
472
+	 */
473
+	protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg)
474
+	{
475
+		$h = array_fill(0, $hLen, 0);
476
+		$ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
477
+		if ($hLen > 0xff) {
478
+			throw new SodiumException('Hash must be less than 256 bytes');
479
+		}
480
+
481
+		if ($ctx_len > 0xff) {
482
+			$st = hash_init('sha256');
483
+			self::hash_update($st, "H2C-OVERSIZE-DST-");
484
+			self::hash_update($st, $ctx);
485
+			$ctx = hash_final($st, true);
486
+			$ctx_len = 32;
487
+		}
488
+		$t = array(0, $hLen, 0);
489
+		$ux = str_repeat("\0", 128);
490
+		$st = hash_init('sha512');
491
+		self::hash_update($st, $ux);
492
+		self::hash_update($st, $msg);
493
+		self::hash_update($st, self::intArrayToString($t));
494
+		self::hash_update($st, $ctx);
495
+		self::hash_update($st, self::intToChr($ctx_len));
496
+		$u0 = hash_final($st, true);
497
+
498
+		for ($i = 0; $i < $hLen; $i += 128) {
499
+			$ux = self::xorStrings($ux, $u0);
500
+			++$t[2];
501
+			$st = hash_init('sha512');
502
+			self::hash_update($st, $ux);
503
+			self::hash_update($st, self::intToChr($t[2]));
504
+			self::hash_update($st, $ctx);
505
+			self::hash_update($st, self::intToChr($ctx_len));
506
+			$ux = hash_final($st, true);
507
+			$amount = min($hLen - $i, 128);
508
+			for ($j = 0; $j < $amount; ++$j) {
509
+				$h[$i + $j] = self::chrToInt($ux[$i]);
510
+			}
511
+		}
512
+		return self::intArrayToString(array_slice($h, 0, $hLen));
513
+	}
514
+
515
+	/**
516
+	 * @param int $hLen
517
+	 * @param ?string $ctx
518
+	 * @param string $msg
519
+	 * @param int $hash_alg
520
+	 * @return string
521
+	 * @throws SodiumException
522
+	 */
523
+	public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg)
524
+	{
525
+		switch ($hash_alg) {
526
+			case self::CORE_H2C_SHA256:
527
+				return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg);
528
+			case self::CORE_H2C_SHA512:
529
+				return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg);
530
+			default:
531
+				throw new SodiumException('Invalid H2C hash algorithm');
532
+		}
533
+	}
534
+
535
+	/**
536
+	 * @param ?string $ctx
537
+	 * @param string $msg
538
+	 * @param int $hash_alg
539
+	 * @return string
540
+	 * @throws SodiumException
541
+	 */
542
+	protected static function _string_to_element($ctx, $msg, $hash_alg)
543
+	{
544
+		return self::ristretto255_from_hash(
545
+			self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg)
546
+		);
547
+	}
548
+
549
+	/**
550
+	 * @return string
551
+	 * @throws SodiumException
552
+	 * @throws Exception
553
+	 */
554
+	public static function ristretto255_random()
555
+	{
556
+		return self::ristretto255_from_hash(
557
+			ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES)
558
+		);
559
+	}
560
+
561
+	/**
562
+	 * @return string
563
+	 * @throws SodiumException
564
+	 */
565
+	public static function ristretto255_scalar_random()
566
+	{
567
+		return self::scalar_random();
568
+	}
569
+
570
+	/**
571
+	 * @param string $s
572
+	 * @return string
573
+	 * @throws SodiumException
574
+	 */
575
+	public static function ristretto255_scalar_complement($s)
576
+	{
577
+		return self::scalar_complement($s);
578
+	}
579
+
580
+
581
+	/**
582
+	 * @param string $s
583
+	 * @return string
584
+	 */
585
+	public static function ristretto255_scalar_invert($s)
586
+	{
587
+		return self::sc25519_invert($s);
588
+	}
589
+
590
+	/**
591
+	 * @param string $s
592
+	 * @return string
593
+	 * @throws SodiumException
594
+	 */
595
+	public static function ristretto255_scalar_negate($s)
596
+	{
597
+		return self::scalar_negate($s);
598
+	}
599
+
600
+	/**
601
+	 * @param string $x
602
+	 * @param string $y
603
+	 * @return string
604
+	 */
605
+	public static function ristretto255_scalar_add($x, $y)
606
+	{
607
+		return self::scalar_add($x, $y);
608
+	}
609
+
610
+	/**
611
+	 * @param string $x
612
+	 * @param string $y
613
+	 * @return string
614
+	 */
615
+	public static function ristretto255_scalar_sub($x, $y)
616
+	{
617
+		return self::scalar_sub($x, $y);
618
+	}
619
+
620
+	/**
621
+	 * @param string $x
622
+	 * @param string $y
623
+	 * @return string
624
+	 */
625
+	public static function ristretto255_scalar_mul($x, $y)
626
+	{
627
+		return self::sc25519_mul($x, $y);
628
+	}
629
+
630
+	/**
631
+	 * @param string $ctx
632
+	 * @param string $msg
633
+	 * @param int $hash_alg
634
+	 * @return string
635
+	 * @throws SodiumException
636
+	 */
637
+	public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg)
638
+	{
639
+		$h = array_fill(0, 64, 0);
640
+		$h_be = self::stringToIntArray(
641
+			self::h2c_string_to_hash(
642
+				self::HASH_SC_L, $ctx, $msg, $hash_alg
643
+			)
644
+		);
645
+
646
+		for ($i = 0; $i < self::HASH_SC_L; ++$i) {
647
+			$h[$i] = $h_be[self::HASH_SC_L - 1 - $i];
648
+		}
649
+		return self::ristretto255_scalar_reduce(self::intArrayToString($h));
650
+	}
651
+
652
+	/**
653
+	 * @param string $s
654
+	 * @return string
655
+	 */
656
+	public static function ristretto255_scalar_reduce($s)
657
+	{
658
+		return self::sc_reduce($s);
659
+	}
660
+
661
+	/**
662
+	 * @param string $n
663
+	 * @param string $p
664
+	 * @return string
665
+	 * @throws SodiumException
666
+	 */
667
+	public static function scalarmult_ristretto255($n, $p)
668
+	{
669
+		if (self::strlen($n) !== 32) {
670
+			throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.');
671
+		}
672
+		if (self::strlen($p) !== 32) {
673
+			throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.');
674
+		}
675
+		$result = self::ristretto255_frombytes($p);
676
+		if ($result['res'] !== 0) {
677
+			throw new SodiumException('Could not multiply points');
678
+		}
679
+		$P = $result['h'];
680
+
681
+		$t = self::stringToIntArray($n);
682
+		$t[31] &= 0x7f;
683
+		$Q = self::ge_scalarmult(self::intArrayToString($t), $P);
684
+		$q = self::ristretto255_p3_tobytes($Q);
685
+		if (ParagonIE_Sodium_Compat::is_zero($q)) {
686
+			throw new SodiumException('An unknown error has occurred');
687
+		}
688
+		return $q;
689
+	}
690
+
691
+	/**
692
+	 * @param string $n
693
+	 * @return string
694
+	 * @throws SodiumException
695
+	 */
696
+	public static function scalarmult_ristretto255_base($n)
697
+	{
698
+		$t = self::stringToIntArray($n);
699
+		$t[31] &= 0x7f;
700
+		$Q = self::ge_scalarmult_base(self::intArrayToString($t));
701
+		$q = self::ristretto255_p3_tobytes($Q);
702
+		if (ParagonIE_Sodium_Compat::is_zero($q)) {
703
+			throw new SodiumException('An unknown error has occurred');
704
+		}
705
+		return $q;
706
+	}
707 707
 }
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/Core/ChaCha20/Ctx.php 1 patch
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core_ChaCha20_Ctx', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,115 +9,115 @@  discard block
 block discarded – undo
9 9
  */
10 10
 class ParagonIE_Sodium_Core_ChaCha20_Ctx extends ParagonIE_Sodium_Core_Util implements ArrayAccess
11 11
 {
12
-    /**
13
-     * @var SplFixedArray internally, <int, int>
14
-     */
15
-    protected $container;
12
+	/**
13
+	 * @var SplFixedArray internally, <int, int>
14
+	 */
15
+	protected $container;
16 16
 
17
-    /**
18
-     * ParagonIE_Sodium_Core_ChaCha20_Ctx constructor.
19
-     *
20
-     * @internal You should not use this directly from another application
21
-     *
22
-     * @param string $key     ChaCha20 key.
23
-     * @param string $iv      Initialization Vector (a.k.a. nonce).
24
-     * @param string $counter The initial counter value.
25
-     *                        Defaults to 8 0x00 bytes.
26
-     * @throws InvalidArgumentException
27
-     * @throws TypeError
28
-     */
29
-    public function __construct($key = '', $iv = '', $counter = '')
30
-    {
31
-        if (self::strlen($key) !== 32) {
32
-            throw new InvalidArgumentException('ChaCha20 expects a 256-bit key.');
33
-        }
34
-        if (self::strlen($iv) !== 8) {
35
-            throw new InvalidArgumentException('ChaCha20 expects a 64-bit nonce.');
36
-        }
37
-        $this->container = new SplFixedArray(16);
17
+	/**
18
+	 * ParagonIE_Sodium_Core_ChaCha20_Ctx constructor.
19
+	 *
20
+	 * @internal You should not use this directly from another application
21
+	 *
22
+	 * @param string $key     ChaCha20 key.
23
+	 * @param string $iv      Initialization Vector (a.k.a. nonce).
24
+	 * @param string $counter The initial counter value.
25
+	 *                        Defaults to 8 0x00 bytes.
26
+	 * @throws InvalidArgumentException
27
+	 * @throws TypeError
28
+	 */
29
+	public function __construct($key = '', $iv = '', $counter = '')
30
+	{
31
+		if (self::strlen($key) !== 32) {
32
+			throw new InvalidArgumentException('ChaCha20 expects a 256-bit key.');
33
+		}
34
+		if (self::strlen($iv) !== 8) {
35
+			throw new InvalidArgumentException('ChaCha20 expects a 64-bit nonce.');
36
+		}
37
+		$this->container = new SplFixedArray(16);
38 38
 
39
-        /* "expand 32-byte k" as per ChaCha20 spec */
40
-        $this->container[0]  = 0x61707865;
41
-        $this->container[1]  = 0x3320646e;
42
-        $this->container[2]  = 0x79622d32;
43
-        $this->container[3]  = 0x6b206574;
44
-        $this->container[4]  = self::load_4(self::substr($key, 0, 4));
45
-        $this->container[5]  = self::load_4(self::substr($key, 4, 4));
46
-        $this->container[6]  = self::load_4(self::substr($key, 8, 4));
47
-        $this->container[7]  = self::load_4(self::substr($key, 12, 4));
48
-        $this->container[8]  = self::load_4(self::substr($key, 16, 4));
49
-        $this->container[9]  = self::load_4(self::substr($key, 20, 4));
50
-        $this->container[10] = self::load_4(self::substr($key, 24, 4));
51
-        $this->container[11] = self::load_4(self::substr($key, 28, 4));
39
+		/* "expand 32-byte k" as per ChaCha20 spec */
40
+		$this->container[0]  = 0x61707865;
41
+		$this->container[1]  = 0x3320646e;
42
+		$this->container[2]  = 0x79622d32;
43
+		$this->container[3]  = 0x6b206574;
44
+		$this->container[4]  = self::load_4(self::substr($key, 0, 4));
45
+		$this->container[5]  = self::load_4(self::substr($key, 4, 4));
46
+		$this->container[6]  = self::load_4(self::substr($key, 8, 4));
47
+		$this->container[7]  = self::load_4(self::substr($key, 12, 4));
48
+		$this->container[8]  = self::load_4(self::substr($key, 16, 4));
49
+		$this->container[9]  = self::load_4(self::substr($key, 20, 4));
50
+		$this->container[10] = self::load_4(self::substr($key, 24, 4));
51
+		$this->container[11] = self::load_4(self::substr($key, 28, 4));
52 52
 
53
-        if (empty($counter)) {
54
-            $this->container[12] = 0;
55
-            $this->container[13] = 0;
56
-        } else {
57
-            $this->container[12] = self::load_4(self::substr($counter, 0, 4));
58
-            $this->container[13] = self::load_4(self::substr($counter, 4, 4));
59
-        }
60
-        $this->container[14] = self::load_4(self::substr($iv, 0, 4));
61
-        $this->container[15] = self::load_4(self::substr($iv, 4, 4));
62
-    }
53
+		if (empty($counter)) {
54
+			$this->container[12] = 0;
55
+			$this->container[13] = 0;
56
+		} else {
57
+			$this->container[12] = self::load_4(self::substr($counter, 0, 4));
58
+			$this->container[13] = self::load_4(self::substr($counter, 4, 4));
59
+		}
60
+		$this->container[14] = self::load_4(self::substr($iv, 0, 4));
61
+		$this->container[15] = self::load_4(self::substr($iv, 4, 4));
62
+	}
63 63
 
64
-    /**
65
-     * @internal You should not use this directly from another application
66
-     *
67
-     * @param int $offset
68
-     * @param int $value
69
-     * @return void
70
-     * @psalm-suppress MixedArrayOffset
71
-     */
72
-    #[ReturnTypeWillChange]
73
-    public function offsetSet($offset, $value)
74
-    {
75
-        if (!is_int($offset)) {
76
-            throw new InvalidArgumentException('Expected an integer');
77
-        }
78
-        if (!is_int($value)) {
79
-            throw new InvalidArgumentException('Expected an integer');
80
-        }
81
-        $this->container[$offset] = $value;
82
-    }
64
+	/**
65
+	 * @internal You should not use this directly from another application
66
+	 *
67
+	 * @param int $offset
68
+	 * @param int $value
69
+	 * @return void
70
+	 * @psalm-suppress MixedArrayOffset
71
+	 */
72
+	#[ReturnTypeWillChange]
73
+	public function offsetSet($offset, $value)
74
+	{
75
+		if (!is_int($offset)) {
76
+			throw new InvalidArgumentException('Expected an integer');
77
+		}
78
+		if (!is_int($value)) {
79
+			throw new InvalidArgumentException('Expected an integer');
80
+		}
81
+		$this->container[$offset] = $value;
82
+	}
83 83
 
84
-    /**
85
-     * @internal You should not use this directly from another application
86
-     *
87
-     * @param int $offset
88
-     * @return bool
89
-     */
90
-    #[ReturnTypeWillChange]
91
-    public function offsetExists($offset)
92
-    {
93
-        return isset($this->container[$offset]);
94
-    }
84
+	/**
85
+	 * @internal You should not use this directly from another application
86
+	 *
87
+	 * @param int $offset
88
+	 * @return bool
89
+	 */
90
+	#[ReturnTypeWillChange]
91
+	public function offsetExists($offset)
92
+	{
93
+		return isset($this->container[$offset]);
94
+	}
95 95
 
96
-    /**
97
-     * @internal You should not use this directly from another application
98
-     *
99
-     * @param int $offset
100
-     * @return void
101
-     * @psalm-suppress MixedArrayOffset
102
-     */
103
-    #[ReturnTypeWillChange]
104
-    public function offsetUnset($offset)
105
-    {
106
-        unset($this->container[$offset]);
107
-    }
96
+	/**
97
+	 * @internal You should not use this directly from another application
98
+	 *
99
+	 * @param int $offset
100
+	 * @return void
101
+	 * @psalm-suppress MixedArrayOffset
102
+	 */
103
+	#[ReturnTypeWillChange]
104
+	public function offsetUnset($offset)
105
+	{
106
+		unset($this->container[$offset]);
107
+	}
108 108
 
109
-    /**
110
-     * @internal You should not use this directly from another application
111
-     *
112
-     * @param int $offset
113
-     * @return mixed|null
114
-     * @psalm-suppress MixedArrayOffset
115
-     */
116
-    #[ReturnTypeWillChange]
117
-    public function offsetGet($offset)
118
-    {
119
-        return isset($this->container[$offset])
120
-            ? $this->container[$offset]
121
-            : null;
122
-    }
109
+	/**
110
+	 * @internal You should not use this directly from another application
111
+	 *
112
+	 * @param int $offset
113
+	 * @return mixed|null
114
+	 * @psalm-suppress MixedArrayOffset
115
+	 */
116
+	#[ReturnTypeWillChange]
117
+	public function offsetGet($offset)
118
+	{
119
+		return isset($this->container[$offset])
120
+			? $this->container[$offset]
121
+			: null;
122
+	}
123 123
 }
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/Core/ChaCha20/IetfCtx.php 1 patch
Indentation   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core_ChaCha20_IetfCtx', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,30 +9,30 @@  discard block
 block discarded – undo
9 9
  */
10 10
 class ParagonIE_Sodium_Core_ChaCha20_IetfCtx extends ParagonIE_Sodium_Core_ChaCha20_Ctx
11 11
 {
12
-    /**
13
-     * ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor.
14
-     *
15
-     * @internal You should not use this directly from another application
16
-     *
17
-     * @param string $key     ChaCha20 key.
18
-     * @param string $iv      Initialization Vector (a.k.a. nonce).
19
-     * @param string $counter The initial counter value.
20
-     *                        Defaults to 4 0x00 bytes.
21
-     * @throws InvalidArgumentException
22
-     * @throws TypeError
23
-     */
24
-    public function __construct($key = '', $iv = '', $counter = '')
25
-    {
26
-        if (self::strlen($iv) !== 12) {
27
-            throw new InvalidArgumentException('ChaCha20 expects a 96-bit nonce in IETF mode.');
28
-        }
29
-        parent::__construct($key, self::substr($iv, 0, 8), $counter);
12
+	/**
13
+	 * ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor.
14
+	 *
15
+	 * @internal You should not use this directly from another application
16
+	 *
17
+	 * @param string $key     ChaCha20 key.
18
+	 * @param string $iv      Initialization Vector (a.k.a. nonce).
19
+	 * @param string $counter The initial counter value.
20
+	 *                        Defaults to 4 0x00 bytes.
21
+	 * @throws InvalidArgumentException
22
+	 * @throws TypeError
23
+	 */
24
+	public function __construct($key = '', $iv = '', $counter = '')
25
+	{
26
+		if (self::strlen($iv) !== 12) {
27
+			throw new InvalidArgumentException('ChaCha20 expects a 96-bit nonce in IETF mode.');
28
+		}
29
+		parent::__construct($key, self::substr($iv, 0, 8), $counter);
30 30
 
31
-        if (!empty($counter)) {
32
-            $this->container[12] = self::load_4(self::substr($counter, 0, 4));
33
-        }
34
-        $this->container[13] = self::load_4(self::substr($iv, 0, 4));
35
-        $this->container[14] = self::load_4(self::substr($iv, 4, 4));
36
-        $this->container[15] = self::load_4(self::substr($iv, 8, 4));
37
-    }
31
+		if (!empty($counter)) {
32
+			$this->container[12] = self::load_4(self::substr($counter, 0, 4));
33
+		}
34
+		$this->container[13] = self::load_4(self::substr($iv, 0, 4));
35
+		$this->container[14] = self::load_4(self::substr($iv, 4, 4));
36
+		$this->container[15] = self::load_4(self::substr($iv, 8, 4));
37
+	}
38 38
 }
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/SodiumException.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -1,11 +1,11 @@
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (!class_exists('SodiumException', false)) {
4
-    /**
5
-     * Class SodiumException
6
-     */
7
-    class SodiumException extends Exception
8
-    {
4
+	/**
5
+	 * Class SodiumException
6
+	 */
7
+	class SodiumException extends Exception
8
+	{
9 9
 
10
-    }
10
+	}
11 11
 }
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/Core32/BLAKE2b.php 1 patch
Indentation   +701 added lines, -701 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -11,709 +11,709 @@  discard block
 block discarded – undo
11 11
  */
12 12
 abstract class ParagonIE_Sodium_Core32_BLAKE2b extends ParagonIE_Sodium_Core_Util
13 13
 {
14
-    /**
15
-     * @var SplFixedArray
16
-     */
17
-    public static $iv;
18
-
19
-    /**
20
-     * @var array<int, array<int, int>>
21
-     */
22
-    public static $sigma = array(
23
-        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15),
24
-        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3),
25
-        array( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4),
26
-        array(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8),
27
-        array(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13),
28
-        array(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9),
29
-        array( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11),
30
-        array( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10),
31
-        array(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5),
32
-        array( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0),
33
-        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15),
34
-        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3)
35
-    );
36
-
37
-    const BLOCKBYTES = 128;
38
-    const OUTBYTES   = 64;
39
-    const KEYBYTES   = 64;
40
-
41
-    /**
42
-     * Turn two 32-bit integers into a fixed array representing a 64-bit integer.
43
-     *
44
-     * @internal You should not use this directly from another application
45
-     *
46
-     * @param int $high
47
-     * @param int $low
48
-     * @return ParagonIE_Sodium_Core32_Int64
49
-     * @throws SodiumException
50
-     * @throws TypeError
51
-     */
52
-    public static function new64($high, $low)
53
-    {
54
-        return ParagonIE_Sodium_Core32_Int64::fromInts($low, $high);
55
-    }
56
-
57
-    /**
58
-     * Convert an arbitrary number into an SplFixedArray of two 32-bit integers
59
-     * that represents a 64-bit integer.
60
-     *
61
-     * @internal You should not use this directly from another application
62
-     *
63
-     * @param int $num
64
-     * @return ParagonIE_Sodium_Core32_Int64
65
-     * @throws SodiumException
66
-     * @throws TypeError
67
-     */
68
-    protected static function to64($num)
69
-    {
70
-        list($hi, $lo) = self::numericTo64BitInteger($num);
71
-        return self::new64($hi, $lo);
72
-    }
73
-
74
-    /**
75
-     * Adds two 64-bit integers together, returning their sum as a SplFixedArray
76
-     * containing two 32-bit integers (representing a 64-bit integer).
77
-     *
78
-     * @internal You should not use this directly from another application
79
-     *
80
-     * @param ParagonIE_Sodium_Core32_Int64 $x
81
-     * @param ParagonIE_Sodium_Core32_Int64 $y
82
-     * @return ParagonIE_Sodium_Core32_Int64
83
-     */
84
-    protected static function add64($x, $y)
85
-    {
86
-        return $x->addInt64($y);
87
-    }
88
-
89
-    /**
90
-     * @internal You should not use this directly from another application
91
-     *
92
-     * @param ParagonIE_Sodium_Core32_Int64 $x
93
-     * @param ParagonIE_Sodium_Core32_Int64 $y
94
-     * @param ParagonIE_Sodium_Core32_Int64 $z
95
-     * @return ParagonIE_Sodium_Core32_Int64
96
-     */
97
-    public static function add364($x, $y, $z)
98
-    {
99
-        return $x->addInt64($y)->addInt64($z);
100
-    }
101
-
102
-    /**
103
-     * @internal You should not use this directly from another application
104
-     *
105
-     * @param ParagonIE_Sodium_Core32_Int64 $x
106
-     * @param ParagonIE_Sodium_Core32_Int64 $y
107
-     * @return ParagonIE_Sodium_Core32_Int64
108
-     * @throws TypeError
109
-     */
110
-    public static function xor64(ParagonIE_Sodium_Core32_Int64 $x, ParagonIE_Sodium_Core32_Int64 $y)
111
-    {
112
-        return $x->xorInt64($y);
113
-    }
114
-
115
-    /**
116
-     * @internal You should not use this directly from another application
117
-     *
118
-     * @param ParagonIE_Sodium_Core32_Int64 $x
119
-     * @param int $c
120
-     * @return ParagonIE_Sodium_Core32_Int64
121
-     * @throws SodiumException
122
-     * @throws TypeError
123
-     */
124
-    public static function rotr64(ParagonIE_Sodium_Core32_Int64 $x, $c)
125
-    {
126
-        return $x->rotateRight($c);
127
-    }
128
-
129
-    /**
130
-     * @internal You should not use this directly from another application
131
-     *
132
-     * @param SplFixedArray $x
133
-     * @param int $i
134
-     * @return ParagonIE_Sodium_Core32_Int64
135
-     * @throws SodiumException
136
-     * @throws TypeError
137
-     */
138
-    public static function load64($x, $i)
139
-    {
140
-        /** @var int $l */
141
-        $l = (int) ($x[$i])
142
-             | ((int) ($x[$i+1]) << 8)
143
-             | ((int) ($x[$i+2]) << 16)
144
-             | ((int) ($x[$i+3]) << 24);
145
-        /** @var int $h */
146
-        $h = (int) ($x[$i+4])
147
-             | ((int) ($x[$i+5]) << 8)
148
-             | ((int) ($x[$i+6]) << 16)
149
-             | ((int) ($x[$i+7]) << 24);
150
-        return self::new64($h, $l);
151
-    }
152
-
153
-    /**
154
-     * @internal You should not use this directly from another application
155
-     *
156
-     * @param SplFixedArray $x
157
-     * @param int $i
158
-     * @param ParagonIE_Sodium_Core32_Int64 $u
159
-     * @return void
160
-     * @throws TypeError
161
-     * @psalm-suppress MixedArgument
162
-     * @psalm-suppress MixedAssignment
163
-     * @psalm-suppress MixedArrayAccess
164
-     * @psalm-suppress MixedArrayAssignment
165
-     * @psalm-suppress MixedArrayOffset
166
-     */
167
-    public static function store64(SplFixedArray $x, $i, ParagonIE_Sodium_Core32_Int64 $u)
168
-    {
169
-        $v = clone $u;
170
-        $maxLength = $x->getSize() - 1;
171
-        for ($j = 0; $j < 8; ++$j) {
172
-            $k = 3 - ($j >> 1);
173
-            $x[$i] = $v->limbs[$k] & 0xff;
174
-            if (++$i > $maxLength) {
175
-                return;
176
-            }
177
-            $v->limbs[$k] >>= 8;
178
-        }
179
-    }
180
-
181
-    /**
182
-     * This just sets the $iv static variable.
183
-     *
184
-     * @internal You should not use this directly from another application
185
-     *
186
-     * @return void
187
-     * @throws SodiumException
188
-     * @throws TypeError
189
-     */
190
-    public static function pseudoConstructor()
191
-    {
192
-        static $called = false;
193
-        if ($called) {
194
-            return;
195
-        }
196
-        self::$iv = new SplFixedArray(8);
197
-        self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
198
-        self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
199
-        self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
200
-        self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
201
-        self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
202
-        self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
203
-        self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
204
-        self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);
205
-
206
-        $called = true;
207
-    }
208
-
209
-    /**
210
-     * Returns a fresh BLAKE2 context.
211
-     *
212
-     * @internal You should not use this directly from another application
213
-     *
214
-     * @return SplFixedArray
215
-     * @throws TypeError
216
-     * @psalm-suppress MixedArgument
217
-     * @psalm-suppress MixedAssignment
218
-     * @psalm-suppress MixedArrayAccess
219
-     * @psalm-suppress MixedArrayAssignment
220
-     * @psalm-suppress MixedArrayOffset
221
-     * @throws SodiumException
222
-     * @throws TypeError
223
-     */
224
-    protected static function context()
225
-    {
226
-        $ctx    = new SplFixedArray(6);
227
-        $ctx[0] = new SplFixedArray(8);   // h
228
-        $ctx[1] = new SplFixedArray(2);   // t
229
-        $ctx[2] = new SplFixedArray(2);   // f
230
-        $ctx[3] = new SplFixedArray(256); // buf
231
-        $ctx[4] = 0;                      // buflen
232
-        $ctx[5] = 0;                      // last_node (uint8_t)
233
-
234
-        for ($i = 8; $i--;) {
235
-            $ctx[0][$i] = self::$iv[$i];
236
-        }
237
-        for ($i = 256; $i--;) {
238
-            $ctx[3][$i] = 0;
239
-        }
240
-
241
-        $zero = self::new64(0, 0);
242
-        $ctx[1][0] = $zero;
243
-        $ctx[1][1] = $zero;
244
-        $ctx[2][0] = $zero;
245
-        $ctx[2][1] = $zero;
246
-
247
-        return $ctx;
248
-    }
249
-
250
-    /**
251
-     * @internal You should not use this directly from another application
252
-     *
253
-     * @param SplFixedArray $ctx
254
-     * @param SplFixedArray $buf
255
-     * @return void
256
-     * @throws SodiumException
257
-     * @throws TypeError
258
-     * @psalm-suppress MixedArgument
259
-     * @psalm-suppress MixedArrayAccess
260
-     * @psalm-suppress MixedArrayAssignment
261
-     * @psalm-suppress MixedAssignment
262
-     */
263
-    protected static function compress(SplFixedArray $ctx, SplFixedArray $buf)
264
-    {
265
-        $m = new SplFixedArray(16);
266
-        $v = new SplFixedArray(16);
267
-
268
-        for ($i = 16; $i--;) {
269
-            $m[$i] = self::load64($buf, $i << 3);
270
-        }
271
-
272
-        for ($i = 8; $i--;) {
273
-            $v[$i] = $ctx[0][$i];
274
-        }
275
-
276
-        $v[ 8] = self::$iv[0];
277
-        $v[ 9] = self::$iv[1];
278
-        $v[10] = self::$iv[2];
279
-        $v[11] = self::$iv[3];
280
-
281
-        $v[12] = self::xor64($ctx[1][0], self::$iv[4]);
282
-        $v[13] = self::xor64($ctx[1][1], self::$iv[5]);
283
-        $v[14] = self::xor64($ctx[2][0], self::$iv[6]);
284
-        $v[15] = self::xor64($ctx[2][1], self::$iv[7]);
285
-
286
-        for ($r = 0; $r < 12; ++$r) {
287
-            $v = self::G($r, 0, 0, 4, 8, 12, $v, $m);
288
-            $v = self::G($r, 1, 1, 5, 9, 13, $v, $m);
289
-            $v = self::G($r, 2, 2, 6, 10, 14, $v, $m);
290
-            $v = self::G($r, 3, 3, 7, 11, 15, $v, $m);
291
-            $v = self::G($r, 4, 0, 5, 10, 15, $v, $m);
292
-            $v = self::G($r, 5, 1, 6, 11, 12, $v, $m);
293
-            $v = self::G($r, 6, 2, 7, 8, 13, $v, $m);
294
-            $v = self::G($r, 7, 3, 4, 9, 14, $v, $m);
295
-        }
296
-
297
-        for ($i = 8; $i--;) {
298
-            $ctx[0][$i] = self::xor64(
299
-                $ctx[0][$i], self::xor64($v[$i], $v[$i+8])
300
-            );
301
-        }
302
-    }
303
-
304
-    /**
305
-     * @internal You should not use this directly from another application
306
-     *
307
-     * @param int $r
308
-     * @param int $i
309
-     * @param int $a
310
-     * @param int $b
311
-     * @param int $c
312
-     * @param int $d
313
-     * @param SplFixedArray $v
314
-     * @param SplFixedArray $m
315
-     * @return SplFixedArray
316
-     * @throws SodiumException
317
-     * @throws TypeError
318
-     * @psalm-suppress MixedArgument
319
-     * @psalm-suppress MixedArrayOffset
320
-     */
321
-    public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m)
322
-    {
323
-        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i << 1]]);
324
-        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
325
-        $v[$c] = self::add64($v[$c], $v[$d]);
326
-        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
327
-        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i << 1) + 1]]);
328
-        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
329
-        $v[$c] = self::add64($v[$c], $v[$d]);
330
-        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
331
-        return $v;
332
-    }
333
-
334
-    /**
335
-     * @internal You should not use this directly from another application
336
-     *
337
-     * @param SplFixedArray $ctx
338
-     * @param int $inc
339
-     * @return void
340
-     * @throws SodiumException
341
-     * @throws TypeError
342
-     * @psalm-suppress MixedArgument
343
-     * @psalm-suppress MixedArrayAccess
344
-     * @psalm-suppress MixedArrayAssignment
345
-     */
346
-    public static function increment_counter($ctx, $inc)
347
-    {
348
-        if ($inc < 0) {
349
-            throw new SodiumException('Increasing by a negative number makes no sense.');
350
-        }
351
-        $t = self::to64($inc);
352
-        # S->t is $ctx[1] in our implementation
353
-
354
-        # S->t[0] = ( uint64_t )( t >> 0 );
355
-        $ctx[1][0] = self::add64($ctx[1][0], $t);
356
-
357
-        # S->t[1] += ( S->t[0] < inc );
358
-        if (!($ctx[1][0] instanceof ParagonIE_Sodium_Core32_Int64)) {
359
-            throw new TypeError('Not an int64');
360
-        }
361
-        /** @var ParagonIE_Sodium_Core32_Int64 $c*/
362
-        $c = $ctx[1][0];
363
-        if ($c->isLessThanInt($inc)) {
364
-            $ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
365
-        }
366
-    }
367
-
368
-    /**
369
-     * @internal You should not use this directly from another application
370
-     *
371
-     * @param SplFixedArray $ctx
372
-     * @param SplFixedArray $p
373
-     * @param int $plen
374
-     * @return void
375
-     * @throws SodiumException
376
-     * @throws TypeError
377
-     * @psalm-suppress MixedArgument
378
-     * @psalm-suppress MixedAssignment
379
-     * @psalm-suppress MixedArrayAccess
380
-     * @psalm-suppress MixedArrayAssignment
381
-     * @psalm-suppress MixedArrayOffset
382
-     * @psalm-suppress MixedMethodCall
383
-     * @psalm-suppress MixedOperand
384
-     */
385
-    public static function update(SplFixedArray $ctx, SplFixedArray $p, $plen)
386
-    {
387
-        self::pseudoConstructor();
388
-
389
-        $offset = 0;
390
-        while ($plen > 0) {
391
-            $left = $ctx[4];
392
-            $fill = 256 - $left;
393
-
394
-            if ($plen > $fill) {
395
-                # memcpy( S->buf + left, in, fill ); /* Fill buffer */
396
-                for ($i = $fill; $i--;) {
397
-                    $ctx[3][$i + $left] = $p[$i + $offset];
398
-                }
399
-
400
-                # S->buflen += fill;
401
-                $ctx[4] += $fill;
402
-
403
-                # blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
404
-                self::increment_counter($ctx, 128);
405
-
406
-                # blake2b_compress( S, S->buf ); /* Compress */
407
-                self::compress($ctx, $ctx[3]);
408
-
409
-                # memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
410
-                for ($i = 128; $i--;) {
411
-                    $ctx[3][$i] = $ctx[3][$i + 128];
412
-                }
413
-
414
-                # S->buflen -= BLAKE2B_BLOCKBYTES;
415
-                $ctx[4] -= 128;
416
-
417
-                # in += fill;
418
-                $offset += $fill;
419
-
420
-                # inlen -= fill;
421
-                $plen -= $fill;
422
-            } else {
423
-                for ($i = $plen; $i--;) {
424
-                    $ctx[3][$i + $left] = $p[$i + $offset];
425
-                }
426
-                $ctx[4] += $plen;
427
-                $offset += $plen;
428
-                $plen -= $plen;
429
-            }
430
-        }
431
-    }
432
-
433
-    /**
434
-     * @internal You should not use this directly from another application
435
-     *
436
-     * @param SplFixedArray $ctx
437
-     * @param SplFixedArray $out
438
-     * @return SplFixedArray
439
-     * @throws SodiumException
440
-     * @throws TypeError
441
-     * @psalm-suppress MixedArgument
442
-     * @psalm-suppress MixedAssignment
443
-     * @psalm-suppress MixedArrayAccess
444
-     * @psalm-suppress MixedArrayAssignment
445
-     * @psalm-suppress MixedArrayOffset
446
-     * @psalm-suppress MixedMethodCall
447
-     * @psalm-suppress MixedOperand
448
-     */
449
-    public static function finish(SplFixedArray $ctx, SplFixedArray $out)
450
-    {
451
-        self::pseudoConstructor();
452
-        if ($ctx[4] > 128) {
453
-            self::increment_counter($ctx, 128);
454
-            self::compress($ctx, $ctx[3]);
455
-            $ctx[4] -= 128;
456
-            if ($ctx[4] > 128) {
457
-                throw new SodiumException('Failed to assert that buflen <= 128 bytes');
458
-            }
459
-            for ($i = $ctx[4]; $i--;) {
460
-                $ctx[3][$i] = $ctx[3][$i + 128];
461
-            }
462
-        }
463
-
464
-        self::increment_counter($ctx, $ctx[4]);
465
-        $ctx[2][0] = self::new64(0xffffffff, 0xffffffff);
466
-
467
-        for ($i = 256 - $ctx[4]; $i--;) {
468
-            /** @var int $i */
469
-            $ctx[3][$i + $ctx[4]] = 0;
470
-        }
471
-
472
-        self::compress($ctx, $ctx[3]);
473
-
474
-        $i = (int) (($out->getSize() - 1) / 8);
475
-        for (; $i >= 0; --$i) {
476
-            self::store64($out, $i << 3, $ctx[0][$i]);
477
-        }
478
-        return $out;
479
-    }
480
-
481
-    /**
482
-     * @internal You should not use this directly from another application
483
-     *
484
-     * @param SplFixedArray|null $key
485
-     * @param int $outlen
486
-     * @param SplFixedArray|null $salt
487
-     * @param SplFixedArray|null $personal
488
-     * @return SplFixedArray
489
-     * @throws SodiumException
490
-     * @throws TypeError
491
-     * @psalm-suppress MixedArgument
492
-     * @psalm-suppress MixedAssignment
493
-     * @psalm-suppress MixedArrayAccess
494
-     * @psalm-suppress MixedArrayAssignment
495
-     * @psalm-suppress MixedMethodCall
496
-     */
497
-    public static function init(
498
-        $key = null,
499
-        $outlen = 64,
500
-        $salt = null,
501
-        $personal = null
502
-    ) {
503
-        self::pseudoConstructor();
504
-        $klen = 0;
505
-
506
-        if ($key !== null) {
507
-            if (count($key) > 64) {
508
-                throw new SodiumException('Invalid key size');
509
-            }
510
-            $klen = count($key);
511
-        }
512
-
513
-        if ($outlen > 64) {
514
-            throw new SodiumException('Invalid output size');
515
-        }
516
-
517
-        $ctx = self::context();
518
-
519
-        $p = new SplFixedArray(64);
520
-        // Zero our param buffer...
521
-        for ($i = 64; --$i;) {
522
-            $p[$i] = 0;
523
-        }
524
-
525
-        $p[0] = $outlen; // digest_length
526
-        $p[1] = $klen;   // key_length
527
-        $p[2] = 1;       // fanout
528
-        $p[3] = 1;       // depth
529
-
530
-        if ($salt instanceof SplFixedArray) {
531
-            // salt: [32] through [47]
532
-            for ($i = 0; $i < 16; ++$i) {
533
-                $p[32 + $i] = (int) $salt[$i];
534
-            }
535
-        }
536
-        if ($personal instanceof SplFixedArray) {
537
-            // personal: [48] through [63]
538
-            for ($i = 0; $i < 16; ++$i) {
539
-                $p[48 + $i] = (int) $personal[$i];
540
-            }
541
-        }
542
-
543
-        $ctx[0][0] = self::xor64(
544
-            $ctx[0][0],
545
-            self::load64($p, 0)
546
-        );
547
-
548
-        if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) {
549
-            // We need to do what blake2b_init_param() does:
550
-            for ($i = 1; $i < 8; ++$i) {
551
-                $ctx[0][$i] = self::xor64(
552
-                    $ctx[0][$i],
553
-                    self::load64($p, $i << 3)
554
-                );
555
-            }
556
-        }
557
-
558
-        if ($klen > 0 && $key instanceof SplFixedArray) {
559
-            $block = new SplFixedArray(128);
560
-            for ($i = 128; $i--;) {
561
-                $block[$i] = 0;
562
-            }
563
-            for ($i = $klen; $i--;) {
564
-                $block[$i] = $key[$i];
565
-            }
566
-            self::update($ctx, $block, 128);
567
-            $ctx[4] = 128;
568
-        }
569
-
570
-        return $ctx;
571
-    }
572
-
573
-    /**
574
-     * Convert a string into an SplFixedArray of integers
575
-     *
576
-     * @internal You should not use this directly from another application
577
-     *
578
-     * @param string $str
579
-     * @return SplFixedArray
580
-     * @psalm-suppress MixedArgumentTypeCoercion
581
-     */
582
-    public static function stringToSplFixedArray($str = '')
583
-    {
584
-        $values = unpack('C*', $str);
585
-        return SplFixedArray::fromArray(array_values($values));
586
-    }
587
-
588
-    /**
589
-     * Convert an SplFixedArray of integers into a string
590
-     *
591
-     * @internal You should not use this directly from another application
592
-     *
593
-     * @param SplFixedArray $a
594
-     * @return string
595
-     */
596
-    public static function SplFixedArrayToString(SplFixedArray $a)
597
-    {
598
-        /**
599
-         * @var array<int, string|int>
600
-         */
601
-        $arr = $a->toArray();
602
-        $c = $a->count();
603
-        array_unshift($arr, str_repeat('C', $c));
604
-        return (string) (call_user_func_array('pack', $arr));
605
-    }
606
-
607
-    /**
608
-     * @internal You should not use this directly from another application
609
-     *
610
-     * @param SplFixedArray $ctx
611
-     * @return string
612
-     * @throws TypeError
613
-     * @psalm-suppress MixedArgument
614
-     * @psalm-suppress MixedArrayAccess
615
-     * @psalm-suppress MixedArrayAssignment
616
-     * @psalm-suppress MixedMethodCall
617
-     */
618
-    public static function contextToString(SplFixedArray $ctx)
619
-    {
620
-        $str = '';
621
-        /** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */
622
-        $ctxA = $ctx[0]->toArray();
623
-
624
-        # uint64_t h[8];
625
-        for ($i = 0; $i < 8; ++$i) {
626
-            if (!($ctxA[$i] instanceof ParagonIE_Sodium_Core32_Int64)) {
627
-                throw new TypeError('Not an instance of Int64');
628
-            }
629
-            /** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */
630
-            $ctxAi = $ctxA[$i];
631
-            $str .= $ctxAi->toReverseString();
632
-        }
633
-
634
-        # uint64_t t[2];
635
-        # uint64_t f[2];
636
-        for ($i = 1; $i < 3; ++$i) {
637
-            /** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */
638
-            $ctxA = $ctx[$i]->toArray();
639
-            /** @var ParagonIE_Sodium_Core32_Int64 $ctxA1 */
640
-            $ctxA1 = $ctxA[0];
641
-            /** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */
642
-            $ctxA2 = $ctxA[1];
643
-
644
-            $str .= $ctxA1->toReverseString();
645
-            $str .= $ctxA2->toReverseString();
646
-        }
647
-
648
-        # uint8_t buf[2 * 128];
649
-        $str .= self::SplFixedArrayToString($ctx[3]);
650
-
651
-        /** @var int $ctx4 */
652
-        $ctx4 = $ctx[4];
653
-
654
-        # size_t buflen;
655
-        $str .= implode('', array(
656
-            self::intToChr($ctx4 & 0xff),
657
-            self::intToChr(($ctx4 >> 8) & 0xff),
658
-            self::intToChr(($ctx4 >> 16) & 0xff),
659
-            self::intToChr(($ctx4 >> 24) & 0xff),
660
-            "\x00\x00\x00\x00"
661
-            /*
14
+	/**
15
+	 * @var SplFixedArray
16
+	 */
17
+	public static $iv;
18
+
19
+	/**
20
+	 * @var array<int, array<int, int>>
21
+	 */
22
+	public static $sigma = array(
23
+		array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15),
24
+		array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3),
25
+		array( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4),
26
+		array(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8),
27
+		array(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13),
28
+		array(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9),
29
+		array( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11),
30
+		array( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10),
31
+		array(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5),
32
+		array( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0),
33
+		array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15),
34
+		array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3)
35
+	);
36
+
37
+	const BLOCKBYTES = 128;
38
+	const OUTBYTES   = 64;
39
+	const KEYBYTES   = 64;
40
+
41
+	/**
42
+	 * Turn two 32-bit integers into a fixed array representing a 64-bit integer.
43
+	 *
44
+	 * @internal You should not use this directly from another application
45
+	 *
46
+	 * @param int $high
47
+	 * @param int $low
48
+	 * @return ParagonIE_Sodium_Core32_Int64
49
+	 * @throws SodiumException
50
+	 * @throws TypeError
51
+	 */
52
+	public static function new64($high, $low)
53
+	{
54
+		return ParagonIE_Sodium_Core32_Int64::fromInts($low, $high);
55
+	}
56
+
57
+	/**
58
+	 * Convert an arbitrary number into an SplFixedArray of two 32-bit integers
59
+	 * that represents a 64-bit integer.
60
+	 *
61
+	 * @internal You should not use this directly from another application
62
+	 *
63
+	 * @param int $num
64
+	 * @return ParagonIE_Sodium_Core32_Int64
65
+	 * @throws SodiumException
66
+	 * @throws TypeError
67
+	 */
68
+	protected static function to64($num)
69
+	{
70
+		list($hi, $lo) = self::numericTo64BitInteger($num);
71
+		return self::new64($hi, $lo);
72
+	}
73
+
74
+	/**
75
+	 * Adds two 64-bit integers together, returning their sum as a SplFixedArray
76
+	 * containing two 32-bit integers (representing a 64-bit integer).
77
+	 *
78
+	 * @internal You should not use this directly from another application
79
+	 *
80
+	 * @param ParagonIE_Sodium_Core32_Int64 $x
81
+	 * @param ParagonIE_Sodium_Core32_Int64 $y
82
+	 * @return ParagonIE_Sodium_Core32_Int64
83
+	 */
84
+	protected static function add64($x, $y)
85
+	{
86
+		return $x->addInt64($y);
87
+	}
88
+
89
+	/**
90
+	 * @internal You should not use this directly from another application
91
+	 *
92
+	 * @param ParagonIE_Sodium_Core32_Int64 $x
93
+	 * @param ParagonIE_Sodium_Core32_Int64 $y
94
+	 * @param ParagonIE_Sodium_Core32_Int64 $z
95
+	 * @return ParagonIE_Sodium_Core32_Int64
96
+	 */
97
+	public static function add364($x, $y, $z)
98
+	{
99
+		return $x->addInt64($y)->addInt64($z);
100
+	}
101
+
102
+	/**
103
+	 * @internal You should not use this directly from another application
104
+	 *
105
+	 * @param ParagonIE_Sodium_Core32_Int64 $x
106
+	 * @param ParagonIE_Sodium_Core32_Int64 $y
107
+	 * @return ParagonIE_Sodium_Core32_Int64
108
+	 * @throws TypeError
109
+	 */
110
+	public static function xor64(ParagonIE_Sodium_Core32_Int64 $x, ParagonIE_Sodium_Core32_Int64 $y)
111
+	{
112
+		return $x->xorInt64($y);
113
+	}
114
+
115
+	/**
116
+	 * @internal You should not use this directly from another application
117
+	 *
118
+	 * @param ParagonIE_Sodium_Core32_Int64 $x
119
+	 * @param int $c
120
+	 * @return ParagonIE_Sodium_Core32_Int64
121
+	 * @throws SodiumException
122
+	 * @throws TypeError
123
+	 */
124
+	public static function rotr64(ParagonIE_Sodium_Core32_Int64 $x, $c)
125
+	{
126
+		return $x->rotateRight($c);
127
+	}
128
+
129
+	/**
130
+	 * @internal You should not use this directly from another application
131
+	 *
132
+	 * @param SplFixedArray $x
133
+	 * @param int $i
134
+	 * @return ParagonIE_Sodium_Core32_Int64
135
+	 * @throws SodiumException
136
+	 * @throws TypeError
137
+	 */
138
+	public static function load64($x, $i)
139
+	{
140
+		/** @var int $l */
141
+		$l = (int) ($x[$i])
142
+			 | ((int) ($x[$i+1]) << 8)
143
+			 | ((int) ($x[$i+2]) << 16)
144
+			 | ((int) ($x[$i+3]) << 24);
145
+		/** @var int $h */
146
+		$h = (int) ($x[$i+4])
147
+			 | ((int) ($x[$i+5]) << 8)
148
+			 | ((int) ($x[$i+6]) << 16)
149
+			 | ((int) ($x[$i+7]) << 24);
150
+		return self::new64($h, $l);
151
+	}
152
+
153
+	/**
154
+	 * @internal You should not use this directly from another application
155
+	 *
156
+	 * @param SplFixedArray $x
157
+	 * @param int $i
158
+	 * @param ParagonIE_Sodium_Core32_Int64 $u
159
+	 * @return void
160
+	 * @throws TypeError
161
+	 * @psalm-suppress MixedArgument
162
+	 * @psalm-suppress MixedAssignment
163
+	 * @psalm-suppress MixedArrayAccess
164
+	 * @psalm-suppress MixedArrayAssignment
165
+	 * @psalm-suppress MixedArrayOffset
166
+	 */
167
+	public static function store64(SplFixedArray $x, $i, ParagonIE_Sodium_Core32_Int64 $u)
168
+	{
169
+		$v = clone $u;
170
+		$maxLength = $x->getSize() - 1;
171
+		for ($j = 0; $j < 8; ++$j) {
172
+			$k = 3 - ($j >> 1);
173
+			$x[$i] = $v->limbs[$k] & 0xff;
174
+			if (++$i > $maxLength) {
175
+				return;
176
+			}
177
+			$v->limbs[$k] >>= 8;
178
+		}
179
+	}
180
+
181
+	/**
182
+	 * This just sets the $iv static variable.
183
+	 *
184
+	 * @internal You should not use this directly from another application
185
+	 *
186
+	 * @return void
187
+	 * @throws SodiumException
188
+	 * @throws TypeError
189
+	 */
190
+	public static function pseudoConstructor()
191
+	{
192
+		static $called = false;
193
+		if ($called) {
194
+			return;
195
+		}
196
+		self::$iv = new SplFixedArray(8);
197
+		self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
198
+		self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
199
+		self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
200
+		self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
201
+		self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
202
+		self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
203
+		self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
204
+		self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);
205
+
206
+		$called = true;
207
+	}
208
+
209
+	/**
210
+	 * Returns a fresh BLAKE2 context.
211
+	 *
212
+	 * @internal You should not use this directly from another application
213
+	 *
214
+	 * @return SplFixedArray
215
+	 * @throws TypeError
216
+	 * @psalm-suppress MixedArgument
217
+	 * @psalm-suppress MixedAssignment
218
+	 * @psalm-suppress MixedArrayAccess
219
+	 * @psalm-suppress MixedArrayAssignment
220
+	 * @psalm-suppress MixedArrayOffset
221
+	 * @throws SodiumException
222
+	 * @throws TypeError
223
+	 */
224
+	protected static function context()
225
+	{
226
+		$ctx    = new SplFixedArray(6);
227
+		$ctx[0] = new SplFixedArray(8);   // h
228
+		$ctx[1] = new SplFixedArray(2);   // t
229
+		$ctx[2] = new SplFixedArray(2);   // f
230
+		$ctx[3] = new SplFixedArray(256); // buf
231
+		$ctx[4] = 0;                      // buflen
232
+		$ctx[5] = 0;                      // last_node (uint8_t)
233
+
234
+		for ($i = 8; $i--;) {
235
+			$ctx[0][$i] = self::$iv[$i];
236
+		}
237
+		for ($i = 256; $i--;) {
238
+			$ctx[3][$i] = 0;
239
+		}
240
+
241
+		$zero = self::new64(0, 0);
242
+		$ctx[1][0] = $zero;
243
+		$ctx[1][1] = $zero;
244
+		$ctx[2][0] = $zero;
245
+		$ctx[2][1] = $zero;
246
+
247
+		return $ctx;
248
+	}
249
+
250
+	/**
251
+	 * @internal You should not use this directly from another application
252
+	 *
253
+	 * @param SplFixedArray $ctx
254
+	 * @param SplFixedArray $buf
255
+	 * @return void
256
+	 * @throws SodiumException
257
+	 * @throws TypeError
258
+	 * @psalm-suppress MixedArgument
259
+	 * @psalm-suppress MixedArrayAccess
260
+	 * @psalm-suppress MixedArrayAssignment
261
+	 * @psalm-suppress MixedAssignment
262
+	 */
263
+	protected static function compress(SplFixedArray $ctx, SplFixedArray $buf)
264
+	{
265
+		$m = new SplFixedArray(16);
266
+		$v = new SplFixedArray(16);
267
+
268
+		for ($i = 16; $i--;) {
269
+			$m[$i] = self::load64($buf, $i << 3);
270
+		}
271
+
272
+		for ($i = 8; $i--;) {
273
+			$v[$i] = $ctx[0][$i];
274
+		}
275
+
276
+		$v[ 8] = self::$iv[0];
277
+		$v[ 9] = self::$iv[1];
278
+		$v[10] = self::$iv[2];
279
+		$v[11] = self::$iv[3];
280
+
281
+		$v[12] = self::xor64($ctx[1][0], self::$iv[4]);
282
+		$v[13] = self::xor64($ctx[1][1], self::$iv[5]);
283
+		$v[14] = self::xor64($ctx[2][0], self::$iv[6]);
284
+		$v[15] = self::xor64($ctx[2][1], self::$iv[7]);
285
+
286
+		for ($r = 0; $r < 12; ++$r) {
287
+			$v = self::G($r, 0, 0, 4, 8, 12, $v, $m);
288
+			$v = self::G($r, 1, 1, 5, 9, 13, $v, $m);
289
+			$v = self::G($r, 2, 2, 6, 10, 14, $v, $m);
290
+			$v = self::G($r, 3, 3, 7, 11, 15, $v, $m);
291
+			$v = self::G($r, 4, 0, 5, 10, 15, $v, $m);
292
+			$v = self::G($r, 5, 1, 6, 11, 12, $v, $m);
293
+			$v = self::G($r, 6, 2, 7, 8, 13, $v, $m);
294
+			$v = self::G($r, 7, 3, 4, 9, 14, $v, $m);
295
+		}
296
+
297
+		for ($i = 8; $i--;) {
298
+			$ctx[0][$i] = self::xor64(
299
+				$ctx[0][$i], self::xor64($v[$i], $v[$i+8])
300
+			);
301
+		}
302
+	}
303
+
304
+	/**
305
+	 * @internal You should not use this directly from another application
306
+	 *
307
+	 * @param int $r
308
+	 * @param int $i
309
+	 * @param int $a
310
+	 * @param int $b
311
+	 * @param int $c
312
+	 * @param int $d
313
+	 * @param SplFixedArray $v
314
+	 * @param SplFixedArray $m
315
+	 * @return SplFixedArray
316
+	 * @throws SodiumException
317
+	 * @throws TypeError
318
+	 * @psalm-suppress MixedArgument
319
+	 * @psalm-suppress MixedArrayOffset
320
+	 */
321
+	public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m)
322
+	{
323
+		$v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i << 1]]);
324
+		$v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
325
+		$v[$c] = self::add64($v[$c], $v[$d]);
326
+		$v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
327
+		$v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i << 1) + 1]]);
328
+		$v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
329
+		$v[$c] = self::add64($v[$c], $v[$d]);
330
+		$v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
331
+		return $v;
332
+	}
333
+
334
+	/**
335
+	 * @internal You should not use this directly from another application
336
+	 *
337
+	 * @param SplFixedArray $ctx
338
+	 * @param int $inc
339
+	 * @return void
340
+	 * @throws SodiumException
341
+	 * @throws TypeError
342
+	 * @psalm-suppress MixedArgument
343
+	 * @psalm-suppress MixedArrayAccess
344
+	 * @psalm-suppress MixedArrayAssignment
345
+	 */
346
+	public static function increment_counter($ctx, $inc)
347
+	{
348
+		if ($inc < 0) {
349
+			throw new SodiumException('Increasing by a negative number makes no sense.');
350
+		}
351
+		$t = self::to64($inc);
352
+		# S->t is $ctx[1] in our implementation
353
+
354
+		# S->t[0] = ( uint64_t )( t >> 0 );
355
+		$ctx[1][0] = self::add64($ctx[1][0], $t);
356
+
357
+		# S->t[1] += ( S->t[0] < inc );
358
+		if (!($ctx[1][0] instanceof ParagonIE_Sodium_Core32_Int64)) {
359
+			throw new TypeError('Not an int64');
360
+		}
361
+		/** @var ParagonIE_Sodium_Core32_Int64 $c*/
362
+		$c = $ctx[1][0];
363
+		if ($c->isLessThanInt($inc)) {
364
+			$ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
365
+		}
366
+	}
367
+
368
+	/**
369
+	 * @internal You should not use this directly from another application
370
+	 *
371
+	 * @param SplFixedArray $ctx
372
+	 * @param SplFixedArray $p
373
+	 * @param int $plen
374
+	 * @return void
375
+	 * @throws SodiumException
376
+	 * @throws TypeError
377
+	 * @psalm-suppress MixedArgument
378
+	 * @psalm-suppress MixedAssignment
379
+	 * @psalm-suppress MixedArrayAccess
380
+	 * @psalm-suppress MixedArrayAssignment
381
+	 * @psalm-suppress MixedArrayOffset
382
+	 * @psalm-suppress MixedMethodCall
383
+	 * @psalm-suppress MixedOperand
384
+	 */
385
+	public static function update(SplFixedArray $ctx, SplFixedArray $p, $plen)
386
+	{
387
+		self::pseudoConstructor();
388
+
389
+		$offset = 0;
390
+		while ($plen > 0) {
391
+			$left = $ctx[4];
392
+			$fill = 256 - $left;
393
+
394
+			if ($plen > $fill) {
395
+				# memcpy( S->buf + left, in, fill ); /* Fill buffer */
396
+				for ($i = $fill; $i--;) {
397
+					$ctx[3][$i + $left] = $p[$i + $offset];
398
+				}
399
+
400
+				# S->buflen += fill;
401
+				$ctx[4] += $fill;
402
+
403
+				# blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
404
+				self::increment_counter($ctx, 128);
405
+
406
+				# blake2b_compress( S, S->buf ); /* Compress */
407
+				self::compress($ctx, $ctx[3]);
408
+
409
+				# memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
410
+				for ($i = 128; $i--;) {
411
+					$ctx[3][$i] = $ctx[3][$i + 128];
412
+				}
413
+
414
+				# S->buflen -= BLAKE2B_BLOCKBYTES;
415
+				$ctx[4] -= 128;
416
+
417
+				# in += fill;
418
+				$offset += $fill;
419
+
420
+				# inlen -= fill;
421
+				$plen -= $fill;
422
+			} else {
423
+				for ($i = $plen; $i--;) {
424
+					$ctx[3][$i + $left] = $p[$i + $offset];
425
+				}
426
+				$ctx[4] += $plen;
427
+				$offset += $plen;
428
+				$plen -= $plen;
429
+			}
430
+		}
431
+	}
432
+
433
+	/**
434
+	 * @internal You should not use this directly from another application
435
+	 *
436
+	 * @param SplFixedArray $ctx
437
+	 * @param SplFixedArray $out
438
+	 * @return SplFixedArray
439
+	 * @throws SodiumException
440
+	 * @throws TypeError
441
+	 * @psalm-suppress MixedArgument
442
+	 * @psalm-suppress MixedAssignment
443
+	 * @psalm-suppress MixedArrayAccess
444
+	 * @psalm-suppress MixedArrayAssignment
445
+	 * @psalm-suppress MixedArrayOffset
446
+	 * @psalm-suppress MixedMethodCall
447
+	 * @psalm-suppress MixedOperand
448
+	 */
449
+	public static function finish(SplFixedArray $ctx, SplFixedArray $out)
450
+	{
451
+		self::pseudoConstructor();
452
+		if ($ctx[4] > 128) {
453
+			self::increment_counter($ctx, 128);
454
+			self::compress($ctx, $ctx[3]);
455
+			$ctx[4] -= 128;
456
+			if ($ctx[4] > 128) {
457
+				throw new SodiumException('Failed to assert that buflen <= 128 bytes');
458
+			}
459
+			for ($i = $ctx[4]; $i--;) {
460
+				$ctx[3][$i] = $ctx[3][$i + 128];
461
+			}
462
+		}
463
+
464
+		self::increment_counter($ctx, $ctx[4]);
465
+		$ctx[2][0] = self::new64(0xffffffff, 0xffffffff);
466
+
467
+		for ($i = 256 - $ctx[4]; $i--;) {
468
+			/** @var int $i */
469
+			$ctx[3][$i + $ctx[4]] = 0;
470
+		}
471
+
472
+		self::compress($ctx, $ctx[3]);
473
+
474
+		$i = (int) (($out->getSize() - 1) / 8);
475
+		for (; $i >= 0; --$i) {
476
+			self::store64($out, $i << 3, $ctx[0][$i]);
477
+		}
478
+		return $out;
479
+	}
480
+
481
+	/**
482
+	 * @internal You should not use this directly from another application
483
+	 *
484
+	 * @param SplFixedArray|null $key
485
+	 * @param int $outlen
486
+	 * @param SplFixedArray|null $salt
487
+	 * @param SplFixedArray|null $personal
488
+	 * @return SplFixedArray
489
+	 * @throws SodiumException
490
+	 * @throws TypeError
491
+	 * @psalm-suppress MixedArgument
492
+	 * @psalm-suppress MixedAssignment
493
+	 * @psalm-suppress MixedArrayAccess
494
+	 * @psalm-suppress MixedArrayAssignment
495
+	 * @psalm-suppress MixedMethodCall
496
+	 */
497
+	public static function init(
498
+		$key = null,
499
+		$outlen = 64,
500
+		$salt = null,
501
+		$personal = null
502
+	) {
503
+		self::pseudoConstructor();
504
+		$klen = 0;
505
+
506
+		if ($key !== null) {
507
+			if (count($key) > 64) {
508
+				throw new SodiumException('Invalid key size');
509
+			}
510
+			$klen = count($key);
511
+		}
512
+
513
+		if ($outlen > 64) {
514
+			throw new SodiumException('Invalid output size');
515
+		}
516
+
517
+		$ctx = self::context();
518
+
519
+		$p = new SplFixedArray(64);
520
+		// Zero our param buffer...
521
+		for ($i = 64; --$i;) {
522
+			$p[$i] = 0;
523
+		}
524
+
525
+		$p[0] = $outlen; // digest_length
526
+		$p[1] = $klen;   // key_length
527
+		$p[2] = 1;       // fanout
528
+		$p[3] = 1;       // depth
529
+
530
+		if ($salt instanceof SplFixedArray) {
531
+			// salt: [32] through [47]
532
+			for ($i = 0; $i < 16; ++$i) {
533
+				$p[32 + $i] = (int) $salt[$i];
534
+			}
535
+		}
536
+		if ($personal instanceof SplFixedArray) {
537
+			// personal: [48] through [63]
538
+			for ($i = 0; $i < 16; ++$i) {
539
+				$p[48 + $i] = (int) $personal[$i];
540
+			}
541
+		}
542
+
543
+		$ctx[0][0] = self::xor64(
544
+			$ctx[0][0],
545
+			self::load64($p, 0)
546
+		);
547
+
548
+		if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) {
549
+			// We need to do what blake2b_init_param() does:
550
+			for ($i = 1; $i < 8; ++$i) {
551
+				$ctx[0][$i] = self::xor64(
552
+					$ctx[0][$i],
553
+					self::load64($p, $i << 3)
554
+				);
555
+			}
556
+		}
557
+
558
+		if ($klen > 0 && $key instanceof SplFixedArray) {
559
+			$block = new SplFixedArray(128);
560
+			for ($i = 128; $i--;) {
561
+				$block[$i] = 0;
562
+			}
563
+			for ($i = $klen; $i--;) {
564
+				$block[$i] = $key[$i];
565
+			}
566
+			self::update($ctx, $block, 128);
567
+			$ctx[4] = 128;
568
+		}
569
+
570
+		return $ctx;
571
+	}
572
+
573
+	/**
574
+	 * Convert a string into an SplFixedArray of integers
575
+	 *
576
+	 * @internal You should not use this directly from another application
577
+	 *
578
+	 * @param string $str
579
+	 * @return SplFixedArray
580
+	 * @psalm-suppress MixedArgumentTypeCoercion
581
+	 */
582
+	public static function stringToSplFixedArray($str = '')
583
+	{
584
+		$values = unpack('C*', $str);
585
+		return SplFixedArray::fromArray(array_values($values));
586
+	}
587
+
588
+	/**
589
+	 * Convert an SplFixedArray of integers into a string
590
+	 *
591
+	 * @internal You should not use this directly from another application
592
+	 *
593
+	 * @param SplFixedArray $a
594
+	 * @return string
595
+	 */
596
+	public static function SplFixedArrayToString(SplFixedArray $a)
597
+	{
598
+		/**
599
+		 * @var array<int, string|int>
600
+		 */
601
+		$arr = $a->toArray();
602
+		$c = $a->count();
603
+		array_unshift($arr, str_repeat('C', $c));
604
+		return (string) (call_user_func_array('pack', $arr));
605
+	}
606
+
607
+	/**
608
+	 * @internal You should not use this directly from another application
609
+	 *
610
+	 * @param SplFixedArray $ctx
611
+	 * @return string
612
+	 * @throws TypeError
613
+	 * @psalm-suppress MixedArgument
614
+	 * @psalm-suppress MixedArrayAccess
615
+	 * @psalm-suppress MixedArrayAssignment
616
+	 * @psalm-suppress MixedMethodCall
617
+	 */
618
+	public static function contextToString(SplFixedArray $ctx)
619
+	{
620
+		$str = '';
621
+		/** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */
622
+		$ctxA = $ctx[0]->toArray();
623
+
624
+		# uint64_t h[8];
625
+		for ($i = 0; $i < 8; ++$i) {
626
+			if (!($ctxA[$i] instanceof ParagonIE_Sodium_Core32_Int64)) {
627
+				throw new TypeError('Not an instance of Int64');
628
+			}
629
+			/** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */
630
+			$ctxAi = $ctxA[$i];
631
+			$str .= $ctxAi->toReverseString();
632
+		}
633
+
634
+		# uint64_t t[2];
635
+		# uint64_t f[2];
636
+		for ($i = 1; $i < 3; ++$i) {
637
+			/** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */
638
+			$ctxA = $ctx[$i]->toArray();
639
+			/** @var ParagonIE_Sodium_Core32_Int64 $ctxA1 */
640
+			$ctxA1 = $ctxA[0];
641
+			/** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */
642
+			$ctxA2 = $ctxA[1];
643
+
644
+			$str .= $ctxA1->toReverseString();
645
+			$str .= $ctxA2->toReverseString();
646
+		}
647
+
648
+		# uint8_t buf[2 * 128];
649
+		$str .= self::SplFixedArrayToString($ctx[3]);
650
+
651
+		/** @var int $ctx4 */
652
+		$ctx4 = $ctx[4];
653
+
654
+		# size_t buflen;
655
+		$str .= implode('', array(
656
+			self::intToChr($ctx4 & 0xff),
657
+			self::intToChr(($ctx4 >> 8) & 0xff),
658
+			self::intToChr(($ctx4 >> 16) & 0xff),
659
+			self::intToChr(($ctx4 >> 24) & 0xff),
660
+			"\x00\x00\x00\x00"
661
+			/*
662 662
             self::intToChr(($ctx4 >> 32) & 0xff),
663 663
             self::intToChr(($ctx4 >> 40) & 0xff),
664 664
             self::intToChr(($ctx4 >> 48) & 0xff),
665 665
             self::intToChr(($ctx4 >> 56) & 0xff)
666 666
             */
667
-        ));
668
-        # uint8_t last_node;
669
-        return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23);
670
-    }
671
-
672
-    /**
673
-     * Creates an SplFixedArray containing other SplFixedArray elements, from
674
-     * a string (compatible with \Sodium\crypto_generichash_{init, update, final})
675
-     *
676
-     * @internal You should not use this directly from another application
677
-     *
678
-     * @param string $string
679
-     * @return SplFixedArray
680
-     * @throws SodiumException
681
-     * @throws TypeError
682
-     * @psalm-suppress MixedArrayAccess
683
-     * @psalm-suppress MixedArrayAssignment
684
-     */
685
-    public static function stringToContext($string)
686
-    {
687
-        $ctx = self::context();
688
-
689
-        # uint64_t h[8];
690
-        for ($i = 0; $i < 8; ++$i) {
691
-            $ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
692
-                self::substr($string, (($i << 3) + 0), 8)
693
-            );
694
-        }
695
-
696
-        # uint64_t t[2];
697
-        # uint64_t f[2];
698
-        for ($i = 1; $i < 3; ++$i) {
699
-            $ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
700
-                self::substr($string, 72 + (($i - 1) << 4), 8)
701
-            );
702
-            $ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
703
-                self::substr($string, 64 + (($i - 1) << 4), 8)
704
-            );
705
-        }
706
-
707
-        # uint8_t buf[2 * 128];
708
-        $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256));
709
-
710
-        # uint8_t buf[2 * 128];
711
-        $int = 0;
712
-        for ($i = 0; $i < 8; ++$i) {
713
-            $int |= self::chrToInt($string[352 + $i]) << ($i << 3);
714
-        }
715
-        $ctx[4] = $int;
716
-
717
-        return $ctx;
718
-    }
667
+		));
668
+		# uint8_t last_node;
669
+		return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23);
670
+	}
671
+
672
+	/**
673
+	 * Creates an SplFixedArray containing other SplFixedArray elements, from
674
+	 * a string (compatible with \Sodium\crypto_generichash_{init, update, final})
675
+	 *
676
+	 * @internal You should not use this directly from another application
677
+	 *
678
+	 * @param string $string
679
+	 * @return SplFixedArray
680
+	 * @throws SodiumException
681
+	 * @throws TypeError
682
+	 * @psalm-suppress MixedArrayAccess
683
+	 * @psalm-suppress MixedArrayAssignment
684
+	 */
685
+	public static function stringToContext($string)
686
+	{
687
+		$ctx = self::context();
688
+
689
+		# uint64_t h[8];
690
+		for ($i = 0; $i < 8; ++$i) {
691
+			$ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
692
+				self::substr($string, (($i << 3) + 0), 8)
693
+			);
694
+		}
695
+
696
+		# uint64_t t[2];
697
+		# uint64_t f[2];
698
+		for ($i = 1; $i < 3; ++$i) {
699
+			$ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
700
+				self::substr($string, 72 + (($i - 1) << 4), 8)
701
+			);
702
+			$ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
703
+				self::substr($string, 64 + (($i - 1) << 4), 8)
704
+			);
705
+		}
706
+
707
+		# uint8_t buf[2 * 128];
708
+		$ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256));
709
+
710
+		# uint8_t buf[2 * 128];
711
+		$int = 0;
712
+		for ($i = 0; $i < 8; ++$i) {
713
+			$int |= self::chrToInt($string[352 + $i]) << ($i << 3);
714
+		}
715
+		$ctx[4] = $int;
716
+
717
+		return $ctx;
718
+	}
719 719
 }
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/Core32/Ed25519.php 1 patch
Indentation   +471 added lines, -471 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_Ed25519', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,474 +9,474 @@  discard block
 block discarded – undo
9 9
  */
10 10
 abstract class ParagonIE_Sodium_Core32_Ed25519 extends ParagonIE_Sodium_Core32_Curve25519
11 11
 {
12
-    const KEYPAIR_BYTES = 96;
13
-    const SEED_BYTES = 32;
14
-
15
-    /**
16
-     * @internal You should not use this directly from another application
17
-     *
18
-     * @return string (96 bytes)
19
-     * @throws Exception
20
-     * @throws SodiumException
21
-     * @throws TypeError
22
-     */
23
-    public static function keypair()
24
-    {
25
-        $seed = random_bytes(self::SEED_BYTES);
26
-        $pk = '';
27
-        $sk = '';
28
-        self::seed_keypair($pk, $sk, $seed);
29
-        return $sk . $pk;
30
-    }
31
-
32
-    /**
33
-     * @internal You should not use this directly from another application
34
-     *
35
-     * @param string $pk
36
-     * @param string $sk
37
-     * @param string $seed
38
-     * @return string
39
-     * @throws SodiumException
40
-     * @throws TypeError
41
-     */
42
-    public static function seed_keypair(&$pk, &$sk, $seed)
43
-    {
44
-        if (self::strlen($seed) !== self::SEED_BYTES) {
45
-            throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
46
-        }
47
-
48
-        /** @var string $pk */
49
-        $pk = self::publickey_from_secretkey($seed);
50
-        $sk = $seed . $pk;
51
-        return $sk;
52
-    }
53
-
54
-    /**
55
-     * @internal You should not use this directly from another application
56
-     *
57
-     * @param string $keypair
58
-     * @return string
59
-     * @throws TypeError
60
-     */
61
-    public static function secretkey($keypair)
62
-    {
63
-        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
64
-            throw new RangeException('crypto_sign keypair must be 96 bytes long');
65
-        }
66
-        return self::substr($keypair, 0, 64);
67
-    }
68
-
69
-    /**
70
-     * @internal You should not use this directly from another application
71
-     *
72
-     * @param string $keypair
73
-     * @return string
74
-     * @throws RangeException
75
-     * @throws TypeError
76
-     */
77
-    public static function publickey($keypair)
78
-    {
79
-        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
80
-            throw new RangeException('crypto_sign keypair must be 96 bytes long');
81
-        }
82
-        return self::substr($keypair, 64, 32);
83
-    }
84
-
85
-    /**
86
-     * @internal You should not use this directly from another application
87
-     *
88
-     * @param string $sk
89
-     * @return string
90
-     * @throws SodiumException
91
-     * @throws TypeError
92
-     */
93
-    public static function publickey_from_secretkey($sk)
94
-    {
95
-        /** @var string $sk */
96
-        $sk = hash('sha512', self::substr($sk, 0, 32), true);
97
-        $sk[0] = self::intToChr(
98
-            self::chrToInt($sk[0]) & 248
99
-        );
100
-        $sk[31] = self::intToChr(
101
-            (self::chrToInt($sk[31]) & 63) | 64
102
-        );
103
-        return self::sk_to_pk($sk);
104
-    }
105
-
106
-    /**
107
-     * @param string $pk
108
-     * @return string
109
-     * @throws SodiumException
110
-     * @throws TypeError
111
-     */
112
-    public static function pk_to_curve25519($pk)
113
-    {
114
-        if (self::small_order($pk)) {
115
-            throw new SodiumException('Public key is on a small order');
116
-        }
117
-        $A = self::ge_frombytes_negate_vartime($pk);
118
-        $p1 = self::ge_mul_l($A);
119
-        if (!self::fe_isnonzero($p1->X)) {
120
-            throw new SodiumException('Unexpected zero result');
121
-        }
122
-
123
-        # fe_1(one_minus_y);
124
-        # fe_sub(one_minus_y, one_minus_y, A.Y);
125
-        # fe_invert(one_minus_y, one_minus_y);
126
-        $one_minux_y = self::fe_invert(
127
-            self::fe_sub(
128
-                self::fe_1(),
129
-                $A->Y
130
-            )
131
-        );
132
-
133
-
134
-        # fe_1(x);
135
-        # fe_add(x, x, A.Y);
136
-        # fe_mul(x, x, one_minus_y);
137
-        $x = self::fe_mul(
138
-            self::fe_add(self::fe_1(), $A->Y),
139
-            $one_minux_y
140
-        );
141
-
142
-        # fe_tobytes(curve25519_pk, x);
143
-        return self::fe_tobytes($x);
144
-    }
145
-
146
-    /**
147
-     * @internal You should not use this directly from another application
148
-     *
149
-     * @param string $sk
150
-     * @return string
151
-     * @throws SodiumException
152
-     * @throws TypeError
153
-     */
154
-    public static function sk_to_pk($sk)
155
-    {
156
-        return self::ge_p3_tobytes(
157
-            self::ge_scalarmult_base(
158
-                self::substr($sk, 0, 32)
159
-            )
160
-        );
161
-    }
162
-
163
-    /**
164
-     * @internal You should not use this directly from another application
165
-     *
166
-     * @param string $message
167
-     * @param string $sk
168
-     * @return string
169
-     * @throws SodiumException
170
-     * @throws TypeError
171
-     */
172
-    public static function sign($message, $sk)
173
-    {
174
-        /** @var string $signature */
175
-        $signature = self::sign_detached($message, $sk);
176
-        return $signature . $message;
177
-    }
178
-
179
-    /**
180
-     * @internal You should not use this directly from another application
181
-     *
182
-     * @param string $message A signed message
183
-     * @param string $pk      Public key
184
-     * @return string         Message (without signature)
185
-     * @throws SodiumException
186
-     * @throws TypeError
187
-     */
188
-    public static function sign_open($message, $pk)
189
-    {
190
-        /** @var string $signature */
191
-        $signature = self::substr($message, 0, 64);
192
-
193
-        /** @var string $message */
194
-        $message = self::substr($message, 64);
195
-
196
-        if (self::verify_detached($signature, $message, $pk)) {
197
-            return $message;
198
-        }
199
-        throw new SodiumException('Invalid signature');
200
-    }
201
-
202
-    /**
203
-     * @internal You should not use this directly from another application
204
-     *
205
-     * @param string $message
206
-     * @param string $sk
207
-     * @return string
208
-     * @throws SodiumException
209
-     * @throws TypeError
210
-     * @psalm-suppress PossiblyInvalidArgument
211
-     */
212
-    public static function sign_detached($message, $sk)
213
-    {
214
-        # crypto_hash_sha512(az, sk, 32);
215
-        $az =  hash('sha512', self::substr($sk, 0, 32), true);
216
-
217
-        # az[0] &= 248;
218
-        # az[31] &= 63;
219
-        # az[31] |= 64;
220
-        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
221
-        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
222
-
223
-        # crypto_hash_sha512_init(&hs);
224
-        # crypto_hash_sha512_update(&hs, az + 32, 32);
225
-        # crypto_hash_sha512_update(&hs, m, mlen);
226
-        # crypto_hash_sha512_final(&hs, nonce);
227
-        $hs = hash_init('sha512');
228
-        self::hash_update($hs, self::substr($az, 32, 32));
229
-        self::hash_update($hs, $message);
230
-        $nonceHash = hash_final($hs, true);
231
-
232
-        # memmove(sig + 32, sk + 32, 32);
233
-        $pk = self::substr($sk, 32, 32);
234
-
235
-        # sc_reduce(nonce);
236
-        # ge_scalarmult_base(&R, nonce);
237
-        # ge_p3_tobytes(sig, &R);
238
-        $nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
239
-        $sig = self::ge_p3_tobytes(
240
-            self::ge_scalarmult_base($nonce)
241
-        );
242
-
243
-        # crypto_hash_sha512_init(&hs);
244
-        # crypto_hash_sha512_update(&hs, sig, 64);
245
-        # crypto_hash_sha512_update(&hs, m, mlen);
246
-        # crypto_hash_sha512_final(&hs, hram);
247
-        $hs = hash_init('sha512');
248
-        self::hash_update($hs, self::substr($sig, 0, 32));
249
-        self::hash_update($hs, self::substr($pk, 0, 32));
250
-        self::hash_update($hs, $message);
251
-        $hramHash = hash_final($hs, true);
252
-
253
-        # sc_reduce(hram);
254
-        # sc_muladd(sig + 32, hram, az, nonce);
255
-        $hram = self::sc_reduce($hramHash);
256
-        $sigAfter = self::sc_muladd($hram, $az, $nonce);
257
-        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
258
-
259
-        try {
260
-            ParagonIE_Sodium_Compat::memzero($az);
261
-        } catch (SodiumException $ex) {
262
-            $az = null;
263
-        }
264
-        return $sig;
265
-    }
266
-
267
-    /**
268
-     * @internal You should not use this directly from another application
269
-     *
270
-     * @param string $sig
271
-     * @param string $message
272
-     * @param string $pk
273
-     * @return bool
274
-     * @throws SodiumException
275
-     * @throws TypeError
276
-     */
277
-    public static function verify_detached($sig, $message, $pk)
278
-    {
279
-        if (self::strlen($sig) < 64) {
280
-            throw new SodiumException('Signature is too short');
281
-        }
282
-        if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) {
283
-            throw new SodiumException('S < L - Invalid signature');
284
-        }
285
-        if (self::small_order($sig)) {
286
-            throw new SodiumException('Signature is on too small of an order');
287
-        }
288
-        if ((self::chrToInt($sig[63]) & 224) !== 0) {
289
-            throw new SodiumException('Invalid signature');
290
-        }
291
-        $d = 0;
292
-        for ($i = 0; $i < 32; ++$i) {
293
-            $d |= self::chrToInt($pk[$i]);
294
-        }
295
-        if ($d === 0) {
296
-            throw new SodiumException('All zero public key');
297
-        }
298
-
299
-        /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
300
-        $orig = ParagonIE_Sodium_Compat::$fastMult;
301
-
302
-        // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
303
-        ParagonIE_Sodium_Compat::$fastMult = true;
304
-
305
-        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */
306
-        $A = self::ge_frombytes_negate_vartime($pk);
307
-
308
-        /** @var string $hDigest */
309
-        $hDigest = hash(
310
-            'sha512',
311
-            self::substr($sig, 0, 32) .
312
-            self::substr($pk, 0, 32) .
313
-            $message,
314
-            true
315
-        );
316
-
317
-        /** @var string $h */
318
-        $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);
319
-
320
-        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */
321
-        $R = self::ge_double_scalarmult_vartime(
322
-            $h,
323
-            $A,
324
-            self::substr($sig, 32)
325
-        );
326
-
327
-        /** @var string $rcheck */
328
-        $rcheck = self::ge_tobytes($R);
329
-
330
-        // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
331
-        ParagonIE_Sodium_Compat::$fastMult = $orig;
332
-
333
-        return self::verify_32($rcheck, self::substr($sig, 0, 32));
334
-    }
335
-
336
-    /**
337
-     * @internal You should not use this directly from another application
338
-     *
339
-     * @param string $S
340
-     * @return bool
341
-     * @throws SodiumException
342
-     * @throws TypeError
343
-     */
344
-    public static function check_S_lt_L($S)
345
-    {
346
-        if (self::strlen($S) < 32) {
347
-            throw new SodiumException('Signature must be 32 bytes');
348
-        }
349
-        static $L = array(
350
-            0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
351
-            0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
352
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
354
-        );
355
-        /** @var array<int, int> $L */
356
-        $c = 0;
357
-        $n = 1;
358
-        $i = 32;
359
-
360
-        do {
361
-            --$i;
362
-            $x = self::chrToInt($S[$i]);
363
-            $c |= (
364
-                (($x - $L[$i]) >> 8) & $n
365
-            );
366
-            $n &= (
367
-                (($x ^ $L[$i]) - 1) >> 8
368
-            );
369
-        } while ($i !== 0);
370
-
371
-        return $c === 0;
372
-    }
373
-
374
-    /**
375
-     * @param string $R
376
-     * @return bool
377
-     * @throws SodiumException
378
-     * @throws TypeError
379
-     */
380
-    public static function small_order($R)
381
-    {
382
-        static $blocklist = array(
383
-            /* 0 (order 4) */
384
-            array(
385
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
389
-            ),
390
-            /* 1 (order 1) */
391
-            array(
392
-                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
396
-            ),
397
-            /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
398
-            array(
399
-                0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
400
-                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
401
-                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
402
-                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
403
-            ),
404
-            /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
405
-            array(
406
-                0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
407
-                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
408
-                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
409
-                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
410
-            ),
411
-            /* p-1 (order 2) */
412
-            array(
413
-                0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
414
-                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
415
-                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
416
-                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
417
-            ),
418
-            /* p (order 4) */
419
-            array(
420
-                0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
421
-                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
422
-                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
423
-                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
424
-            ),
425
-            /* p+1 (order 1) */
426
-            array(
427
-                0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
428
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
429
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
430
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
431
-            ),
432
-            /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
433
-            array(
434
-                0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
435
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
436
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
437
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
438
-            ),
439
-            /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
440
-            array(
441
-                0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
442
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
443
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
444
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
445
-            ),
446
-            /* 2p-1 (order 2) */
447
-            array(
448
-                0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
449
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
450
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
451
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
452
-            ),
453
-            /* 2p (order 4) */
454
-            array(
455
-                0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
456
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
457
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
458
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
459
-            ),
460
-            /* 2p+1 (order 1) */
461
-            array(
462
-                0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
463
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
464
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
465
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
466
-            )
467
-        );
468
-        /** @var array<int, array<int, int>> $blocklist */
469
-        $countBlocklist = count($blocklist);
470
-
471
-        for ($i = 0; $i < $countBlocklist; ++$i) {
472
-            $c = 0;
473
-            for ($j = 0; $j < 32; ++$j) {
474
-                $c |= self::chrToInt($R[$j]) ^ $blocklist[$i][$j];
475
-            }
476
-            if ($c === 0) {
477
-                return true;
478
-            }
479
-        }
480
-        return false;
481
-    }
12
+	const KEYPAIR_BYTES = 96;
13
+	const SEED_BYTES = 32;
14
+
15
+	/**
16
+	 * @internal You should not use this directly from another application
17
+	 *
18
+	 * @return string (96 bytes)
19
+	 * @throws Exception
20
+	 * @throws SodiumException
21
+	 * @throws TypeError
22
+	 */
23
+	public static function keypair()
24
+	{
25
+		$seed = random_bytes(self::SEED_BYTES);
26
+		$pk = '';
27
+		$sk = '';
28
+		self::seed_keypair($pk, $sk, $seed);
29
+		return $sk . $pk;
30
+	}
31
+
32
+	/**
33
+	 * @internal You should not use this directly from another application
34
+	 *
35
+	 * @param string $pk
36
+	 * @param string $sk
37
+	 * @param string $seed
38
+	 * @return string
39
+	 * @throws SodiumException
40
+	 * @throws TypeError
41
+	 */
42
+	public static function seed_keypair(&$pk, &$sk, $seed)
43
+	{
44
+		if (self::strlen($seed) !== self::SEED_BYTES) {
45
+			throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
46
+		}
47
+
48
+		/** @var string $pk */
49
+		$pk = self::publickey_from_secretkey($seed);
50
+		$sk = $seed . $pk;
51
+		return $sk;
52
+	}
53
+
54
+	/**
55
+	 * @internal You should not use this directly from another application
56
+	 *
57
+	 * @param string $keypair
58
+	 * @return string
59
+	 * @throws TypeError
60
+	 */
61
+	public static function secretkey($keypair)
62
+	{
63
+		if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
64
+			throw new RangeException('crypto_sign keypair must be 96 bytes long');
65
+		}
66
+		return self::substr($keypair, 0, 64);
67
+	}
68
+
69
+	/**
70
+	 * @internal You should not use this directly from another application
71
+	 *
72
+	 * @param string $keypair
73
+	 * @return string
74
+	 * @throws RangeException
75
+	 * @throws TypeError
76
+	 */
77
+	public static function publickey($keypair)
78
+	{
79
+		if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
80
+			throw new RangeException('crypto_sign keypair must be 96 bytes long');
81
+		}
82
+		return self::substr($keypair, 64, 32);
83
+	}
84
+
85
+	/**
86
+	 * @internal You should not use this directly from another application
87
+	 *
88
+	 * @param string $sk
89
+	 * @return string
90
+	 * @throws SodiumException
91
+	 * @throws TypeError
92
+	 */
93
+	public static function publickey_from_secretkey($sk)
94
+	{
95
+		/** @var string $sk */
96
+		$sk = hash('sha512', self::substr($sk, 0, 32), true);
97
+		$sk[0] = self::intToChr(
98
+			self::chrToInt($sk[0]) & 248
99
+		);
100
+		$sk[31] = self::intToChr(
101
+			(self::chrToInt($sk[31]) & 63) | 64
102
+		);
103
+		return self::sk_to_pk($sk);
104
+	}
105
+
106
+	/**
107
+	 * @param string $pk
108
+	 * @return string
109
+	 * @throws SodiumException
110
+	 * @throws TypeError
111
+	 */
112
+	public static function pk_to_curve25519($pk)
113
+	{
114
+		if (self::small_order($pk)) {
115
+			throw new SodiumException('Public key is on a small order');
116
+		}
117
+		$A = self::ge_frombytes_negate_vartime($pk);
118
+		$p1 = self::ge_mul_l($A);
119
+		if (!self::fe_isnonzero($p1->X)) {
120
+			throw new SodiumException('Unexpected zero result');
121
+		}
122
+
123
+		# fe_1(one_minus_y);
124
+		# fe_sub(one_minus_y, one_minus_y, A.Y);
125
+		# fe_invert(one_minus_y, one_minus_y);
126
+		$one_minux_y = self::fe_invert(
127
+			self::fe_sub(
128
+				self::fe_1(),
129
+				$A->Y
130
+			)
131
+		);
132
+
133
+
134
+		# fe_1(x);
135
+		# fe_add(x, x, A.Y);
136
+		# fe_mul(x, x, one_minus_y);
137
+		$x = self::fe_mul(
138
+			self::fe_add(self::fe_1(), $A->Y),
139
+			$one_minux_y
140
+		);
141
+
142
+		# fe_tobytes(curve25519_pk, x);
143
+		return self::fe_tobytes($x);
144
+	}
145
+
146
+	/**
147
+	 * @internal You should not use this directly from another application
148
+	 *
149
+	 * @param string $sk
150
+	 * @return string
151
+	 * @throws SodiumException
152
+	 * @throws TypeError
153
+	 */
154
+	public static function sk_to_pk($sk)
155
+	{
156
+		return self::ge_p3_tobytes(
157
+			self::ge_scalarmult_base(
158
+				self::substr($sk, 0, 32)
159
+			)
160
+		);
161
+	}
162
+
163
+	/**
164
+	 * @internal You should not use this directly from another application
165
+	 *
166
+	 * @param string $message
167
+	 * @param string $sk
168
+	 * @return string
169
+	 * @throws SodiumException
170
+	 * @throws TypeError
171
+	 */
172
+	public static function sign($message, $sk)
173
+	{
174
+		/** @var string $signature */
175
+		$signature = self::sign_detached($message, $sk);
176
+		return $signature . $message;
177
+	}
178
+
179
+	/**
180
+	 * @internal You should not use this directly from another application
181
+	 *
182
+	 * @param string $message A signed message
183
+	 * @param string $pk      Public key
184
+	 * @return string         Message (without signature)
185
+	 * @throws SodiumException
186
+	 * @throws TypeError
187
+	 */
188
+	public static function sign_open($message, $pk)
189
+	{
190
+		/** @var string $signature */
191
+		$signature = self::substr($message, 0, 64);
192
+
193
+		/** @var string $message */
194
+		$message = self::substr($message, 64);
195
+
196
+		if (self::verify_detached($signature, $message, $pk)) {
197
+			return $message;
198
+		}
199
+		throw new SodiumException('Invalid signature');
200
+	}
201
+
202
+	/**
203
+	 * @internal You should not use this directly from another application
204
+	 *
205
+	 * @param string $message
206
+	 * @param string $sk
207
+	 * @return string
208
+	 * @throws SodiumException
209
+	 * @throws TypeError
210
+	 * @psalm-suppress PossiblyInvalidArgument
211
+	 */
212
+	public static function sign_detached($message, $sk)
213
+	{
214
+		# crypto_hash_sha512(az, sk, 32);
215
+		$az =  hash('sha512', self::substr($sk, 0, 32), true);
216
+
217
+		# az[0] &= 248;
218
+		# az[31] &= 63;
219
+		# az[31] |= 64;
220
+		$az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
221
+		$az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
222
+
223
+		# crypto_hash_sha512_init(&hs);
224
+		# crypto_hash_sha512_update(&hs, az + 32, 32);
225
+		# crypto_hash_sha512_update(&hs, m, mlen);
226
+		# crypto_hash_sha512_final(&hs, nonce);
227
+		$hs = hash_init('sha512');
228
+		self::hash_update($hs, self::substr($az, 32, 32));
229
+		self::hash_update($hs, $message);
230
+		$nonceHash = hash_final($hs, true);
231
+
232
+		# memmove(sig + 32, sk + 32, 32);
233
+		$pk = self::substr($sk, 32, 32);
234
+
235
+		# sc_reduce(nonce);
236
+		# ge_scalarmult_base(&R, nonce);
237
+		# ge_p3_tobytes(sig, &R);
238
+		$nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
239
+		$sig = self::ge_p3_tobytes(
240
+			self::ge_scalarmult_base($nonce)
241
+		);
242
+
243
+		# crypto_hash_sha512_init(&hs);
244
+		# crypto_hash_sha512_update(&hs, sig, 64);
245
+		# crypto_hash_sha512_update(&hs, m, mlen);
246
+		# crypto_hash_sha512_final(&hs, hram);
247
+		$hs = hash_init('sha512');
248
+		self::hash_update($hs, self::substr($sig, 0, 32));
249
+		self::hash_update($hs, self::substr($pk, 0, 32));
250
+		self::hash_update($hs, $message);
251
+		$hramHash = hash_final($hs, true);
252
+
253
+		# sc_reduce(hram);
254
+		# sc_muladd(sig + 32, hram, az, nonce);
255
+		$hram = self::sc_reduce($hramHash);
256
+		$sigAfter = self::sc_muladd($hram, $az, $nonce);
257
+		$sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
258
+
259
+		try {
260
+			ParagonIE_Sodium_Compat::memzero($az);
261
+		} catch (SodiumException $ex) {
262
+			$az = null;
263
+		}
264
+		return $sig;
265
+	}
266
+
267
+	/**
268
+	 * @internal You should not use this directly from another application
269
+	 *
270
+	 * @param string $sig
271
+	 * @param string $message
272
+	 * @param string $pk
273
+	 * @return bool
274
+	 * @throws SodiumException
275
+	 * @throws TypeError
276
+	 */
277
+	public static function verify_detached($sig, $message, $pk)
278
+	{
279
+		if (self::strlen($sig) < 64) {
280
+			throw new SodiumException('Signature is too short');
281
+		}
282
+		if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) {
283
+			throw new SodiumException('S < L - Invalid signature');
284
+		}
285
+		if (self::small_order($sig)) {
286
+			throw new SodiumException('Signature is on too small of an order');
287
+		}
288
+		if ((self::chrToInt($sig[63]) & 224) !== 0) {
289
+			throw new SodiumException('Invalid signature');
290
+		}
291
+		$d = 0;
292
+		for ($i = 0; $i < 32; ++$i) {
293
+			$d |= self::chrToInt($pk[$i]);
294
+		}
295
+		if ($d === 0) {
296
+			throw new SodiumException('All zero public key');
297
+		}
298
+
299
+		/** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
300
+		$orig = ParagonIE_Sodium_Compat::$fastMult;
301
+
302
+		// Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
303
+		ParagonIE_Sodium_Compat::$fastMult = true;
304
+
305
+		/** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */
306
+		$A = self::ge_frombytes_negate_vartime($pk);
307
+
308
+		/** @var string $hDigest */
309
+		$hDigest = hash(
310
+			'sha512',
311
+			self::substr($sig, 0, 32) .
312
+			self::substr($pk, 0, 32) .
313
+			$message,
314
+			true
315
+		);
316
+
317
+		/** @var string $h */
318
+		$h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);
319
+
320
+		/** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */
321
+		$R = self::ge_double_scalarmult_vartime(
322
+			$h,
323
+			$A,
324
+			self::substr($sig, 32)
325
+		);
326
+
327
+		/** @var string $rcheck */
328
+		$rcheck = self::ge_tobytes($R);
329
+
330
+		// Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
331
+		ParagonIE_Sodium_Compat::$fastMult = $orig;
332
+
333
+		return self::verify_32($rcheck, self::substr($sig, 0, 32));
334
+	}
335
+
336
+	/**
337
+	 * @internal You should not use this directly from another application
338
+	 *
339
+	 * @param string $S
340
+	 * @return bool
341
+	 * @throws SodiumException
342
+	 * @throws TypeError
343
+	 */
344
+	public static function check_S_lt_L($S)
345
+	{
346
+		if (self::strlen($S) < 32) {
347
+			throw new SodiumException('Signature must be 32 bytes');
348
+		}
349
+		static $L = array(
350
+			0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
351
+			0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
352
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
354
+		);
355
+		/** @var array<int, int> $L */
356
+		$c = 0;
357
+		$n = 1;
358
+		$i = 32;
359
+
360
+		do {
361
+			--$i;
362
+			$x = self::chrToInt($S[$i]);
363
+			$c |= (
364
+				(($x - $L[$i]) >> 8) & $n
365
+			);
366
+			$n &= (
367
+				(($x ^ $L[$i]) - 1) >> 8
368
+			);
369
+		} while ($i !== 0);
370
+
371
+		return $c === 0;
372
+	}
373
+
374
+	/**
375
+	 * @param string $R
376
+	 * @return bool
377
+	 * @throws SodiumException
378
+	 * @throws TypeError
379
+	 */
380
+	public static function small_order($R)
381
+	{
382
+		static $blocklist = array(
383
+			/* 0 (order 4) */
384
+			array(
385
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
389
+			),
390
+			/* 1 (order 1) */
391
+			array(
392
+				0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
396
+			),
397
+			/* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
398
+			array(
399
+				0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
400
+				0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
401
+				0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
402
+				0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
403
+			),
404
+			/* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
405
+			array(
406
+				0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
407
+				0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
408
+				0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
409
+				0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
410
+			),
411
+			/* p-1 (order 2) */
412
+			array(
413
+				0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
414
+				0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
415
+				0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
416
+				0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
417
+			),
418
+			/* p (order 4) */
419
+			array(
420
+				0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
421
+				0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
422
+				0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
423
+				0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
424
+			),
425
+			/* p+1 (order 1) */
426
+			array(
427
+				0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
428
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
429
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
430
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
431
+			),
432
+			/* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
433
+			array(
434
+				0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
435
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
436
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
437
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
438
+			),
439
+			/* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
440
+			array(
441
+				0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
442
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
443
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
444
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
445
+			),
446
+			/* 2p-1 (order 2) */
447
+			array(
448
+				0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
449
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
450
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
451
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
452
+			),
453
+			/* 2p (order 4) */
454
+			array(
455
+				0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
456
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
457
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
458
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
459
+			),
460
+			/* 2p+1 (order 1) */
461
+			array(
462
+				0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
463
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
464
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
465
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
466
+			)
467
+		);
468
+		/** @var array<int, array<int, int>> $blocklist */
469
+		$countBlocklist = count($blocklist);
470
+
471
+		for ($i = 0; $i < $countBlocklist; ++$i) {
472
+			$c = 0;
473
+			for ($j = 0; $j < 32; ++$j) {
474
+				$c |= self::chrToInt($R[$j]) ^ $blocklist[$i][$j];
475
+			}
476
+			if ($c === 0) {
477
+				return true;
478
+			}
479
+		}
480
+		return false;
481
+	}
482 482
 }
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/Core32/Util.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_Util', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/Core32/SipHash.php 1 patch
Indentation   +225 added lines, -225 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_SipHash', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -11,228 +11,228 @@  discard block
 block discarded – undo
11 11
  */
12 12
 class ParagonIE_Sodium_Core32_SipHash extends ParagonIE_Sodium_Core32_Util
13 13
 {
14
-    /**
15
-     * @internal You should not use this directly from another application
16
-     *
17
-     * @param array<int, ParagonIE_Sodium_Core32_Int64> $v
18
-     * @return array<int, ParagonIE_Sodium_Core32_Int64>
19
-     */
20
-    public static function sipRound(array $v)
21
-    {
22
-        # v0 += v1;
23
-        $v[0] = $v[0]->addInt64($v[1]);
24
-
25
-        # v1 = ROTL(v1, 13);
26
-        $v[1] = $v[1]->rotateLeft(13);
27
-
28
-        #  v1 ^= v0;
29
-        $v[1] = $v[1]->xorInt64($v[0]);
30
-
31
-        #  v0=ROTL(v0,32);
32
-        $v[0] = $v[0]->rotateLeft(32);
33
-
34
-        # v2 += v3;
35
-        $v[2] = $v[2]->addInt64($v[3]);
36
-
37
-        # v3=ROTL(v3,16);
38
-        $v[3] = $v[3]->rotateLeft(16);
39
-
40
-        #  v3 ^= v2;
41
-        $v[3] = $v[3]->xorInt64($v[2]);
42
-
43
-        # v0 += v3;
44
-        $v[0] = $v[0]->addInt64($v[3]);
45
-
46
-        # v3=ROTL(v3,21);
47
-        $v[3] = $v[3]->rotateLeft(21);
48
-
49
-        # v3 ^= v0;
50
-        $v[3] = $v[3]->xorInt64($v[0]);
51
-
52
-        # v2 += v1;
53
-        $v[2] = $v[2]->addInt64($v[1]);
54
-
55
-        # v1=ROTL(v1,17);
56
-        $v[1] = $v[1]->rotateLeft(17);
57
-
58
-        #  v1 ^= v2;
59
-        $v[1] = $v[1]->xorInt64($v[2]);
60
-
61
-        # v2=ROTL(v2,32)
62
-        $v[2] = $v[2]->rotateLeft(32);
63
-
64
-        return $v;
65
-    }
66
-
67
-    /**
68
-     * @internal You should not use this directly from another application
69
-     *
70
-     * @param string $in
71
-     * @param string $key
72
-     * @return string
73
-     * @throws SodiumException
74
-     * @throws TypeError
75
-     */
76
-    public static function sipHash24($in, $key)
77
-    {
78
-        $inlen = self::strlen($in);
79
-
80
-        # /* "somepseudorandomlygeneratedbytes" */
81
-        # u64 v0 = 0x736f6d6570736575ULL;
82
-        # u64 v1 = 0x646f72616e646f6dULL;
83
-        # u64 v2 = 0x6c7967656e657261ULL;
84
-        # u64 v3 = 0x7465646279746573ULL;
85
-        $v = array(
86
-            new ParagonIE_Sodium_Core32_Int64(
87
-                array(0x736f, 0x6d65, 0x7073, 0x6575)
88
-            ),
89
-            new ParagonIE_Sodium_Core32_Int64(
90
-                array(0x646f, 0x7261, 0x6e64, 0x6f6d)
91
-            ),
92
-            new ParagonIE_Sodium_Core32_Int64(
93
-                array(0x6c79, 0x6765, 0x6e65, 0x7261)
94
-            ),
95
-            new ParagonIE_Sodium_Core32_Int64(
96
-                array(0x7465, 0x6462, 0x7974, 0x6573)
97
-            )
98
-        );
99
-
100
-        # u64 k0 = LOAD64_LE( k );
101
-        # u64 k1 = LOAD64_LE( k + 8 );
102
-        $k = array(
103
-            ParagonIE_Sodium_Core32_Int64::fromReverseString(
104
-                self::substr($key, 0, 8)
105
-            ),
106
-            ParagonIE_Sodium_Core32_Int64::fromReverseString(
107
-                self::substr($key, 8, 8)
108
-            )
109
-        );
110
-
111
-        # b = ( ( u64 )inlen ) << 56;
112
-        $b = new ParagonIE_Sodium_Core32_Int64(
113
-            array(($inlen << 8) & 0xffff, 0, 0, 0)
114
-        );
115
-
116
-        # v3 ^= k1;
117
-        $v[3] = $v[3]->xorInt64($k[1]);
118
-        # v2 ^= k0;
119
-        $v[2] = $v[2]->xorInt64($k[0]);
120
-        # v1 ^= k1;
121
-        $v[1] = $v[1]->xorInt64($k[1]);
122
-        # v0 ^= k0;
123
-        $v[0] = $v[0]->xorInt64($k[0]);
124
-
125
-        $left = $inlen;
126
-        # for ( ; in != end; in += 8 )
127
-        while ($left >= 8) {
128
-            # m = LOAD64_LE( in );
129
-            $m = ParagonIE_Sodium_Core32_Int64::fromReverseString(
130
-                self::substr($in, 0, 8)
131
-            );
132
-
133
-            # v3 ^= m;
134
-            $v[3] = $v[3]->xorInt64($m);
135
-
136
-            # SIPROUND;
137
-            # SIPROUND;
138
-            $v = self::sipRound($v);
139
-            $v = self::sipRound($v);
140
-
141
-            # v0 ^= m;
142
-            $v[0] = $v[0]->xorInt64($m);
143
-
144
-            $in = self::substr($in, 8);
145
-            $left -= 8;
146
-        }
147
-
148
-        # switch( left )
149
-        #  {
150
-        #     case 7: b |= ( ( u64 )in[ 6] )  << 48;
151
-        #     case 6: b |= ( ( u64 )in[ 5] )  << 40;
152
-        #     case 5: b |= ( ( u64 )in[ 4] )  << 32;
153
-        #     case 4: b |= ( ( u64 )in[ 3] )  << 24;
154
-        #     case 3: b |= ( ( u64 )in[ 2] )  << 16;
155
-        #     case 2: b |= ( ( u64 )in[ 1] )  <<  8;
156
-        #     case 1: b |= ( ( u64 )in[ 0] ); break;
157
-        #     case 0: break;
158
-        # }
159
-        switch ($left) {
160
-            case 7:
161
-                $b = $b->orInt64(
162
-                    ParagonIE_Sodium_Core32_Int64::fromInts(
163
-                        0, self::chrToInt($in[6]) << 16
164
-                    )
165
-                );
166
-            case 6:
167
-                $b = $b->orInt64(
168
-                    ParagonIE_Sodium_Core32_Int64::fromInts(
169
-                        0, self::chrToInt($in[5]) << 8
170
-                    )
171
-                );
172
-            case 5:
173
-                $b = $b->orInt64(
174
-                    ParagonIE_Sodium_Core32_Int64::fromInts(
175
-                        0, self::chrToInt($in[4])
176
-                    )
177
-                );
178
-            case 4:
179
-                $b = $b->orInt64(
180
-                    ParagonIE_Sodium_Core32_Int64::fromInts(
181
-                        self::chrToInt($in[3]) << 24, 0
182
-                    )
183
-                );
184
-            case 3:
185
-                $b = $b->orInt64(
186
-                    ParagonIE_Sodium_Core32_Int64::fromInts(
187
-                        self::chrToInt($in[2]) << 16, 0
188
-                    )
189
-                );
190
-            case 2:
191
-                $b = $b->orInt64(
192
-                    ParagonIE_Sodium_Core32_Int64::fromInts(
193
-                        self::chrToInt($in[1]) << 8, 0
194
-                    )
195
-                );
196
-            case 1:
197
-                $b = $b->orInt64(
198
-                    ParagonIE_Sodium_Core32_Int64::fromInts(
199
-                        self::chrToInt($in[0]), 0
200
-                    )
201
-                );
202
-            case 0:
203
-                break;
204
-        }
205
-
206
-        # v3 ^= b;
207
-        $v[3] = $v[3]->xorInt64($b);
208
-
209
-        # SIPROUND;
210
-        # SIPROUND;
211
-        $v = self::sipRound($v);
212
-        $v = self::sipRound($v);
213
-
214
-        # v0 ^= b;
215
-        $v[0] = $v[0]->xorInt64($b);
216
-
217
-        // Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation
218
-        # v2 ^= 0xff;
219
-        $v[2]->limbs[3] ^= 0xff;
220
-
221
-        # SIPROUND;
222
-        # SIPROUND;
223
-        # SIPROUND;
224
-        # SIPROUND;
225
-        $v = self::sipRound($v);
226
-        $v = self::sipRound($v);
227
-        $v = self::sipRound($v);
228
-        $v = self::sipRound($v);
229
-
230
-        # b = v0 ^ v1 ^ v2 ^ v3;
231
-        # STORE64_LE( out, b );
232
-        return $v[0]
233
-            ->xorInt64($v[1])
234
-            ->xorInt64($v[2])
235
-            ->xorInt64($v[3])
236
-            ->toReverseString();
237
-    }
14
+	/**
15
+	 * @internal You should not use this directly from another application
16
+	 *
17
+	 * @param array<int, ParagonIE_Sodium_Core32_Int64> $v
18
+	 * @return array<int, ParagonIE_Sodium_Core32_Int64>
19
+	 */
20
+	public static function sipRound(array $v)
21
+	{
22
+		# v0 += v1;
23
+		$v[0] = $v[0]->addInt64($v[1]);
24
+
25
+		# v1 = ROTL(v1, 13);
26
+		$v[1] = $v[1]->rotateLeft(13);
27
+
28
+		#  v1 ^= v0;
29
+		$v[1] = $v[1]->xorInt64($v[0]);
30
+
31
+		#  v0=ROTL(v0,32);
32
+		$v[0] = $v[0]->rotateLeft(32);
33
+
34
+		# v2 += v3;
35
+		$v[2] = $v[2]->addInt64($v[3]);
36
+
37
+		# v3=ROTL(v3,16);
38
+		$v[3] = $v[3]->rotateLeft(16);
39
+
40
+		#  v3 ^= v2;
41
+		$v[3] = $v[3]->xorInt64($v[2]);
42
+
43
+		# v0 += v3;
44
+		$v[0] = $v[0]->addInt64($v[3]);
45
+
46
+		# v3=ROTL(v3,21);
47
+		$v[3] = $v[3]->rotateLeft(21);
48
+
49
+		# v3 ^= v0;
50
+		$v[3] = $v[3]->xorInt64($v[0]);
51
+
52
+		# v2 += v1;
53
+		$v[2] = $v[2]->addInt64($v[1]);
54
+
55
+		# v1=ROTL(v1,17);
56
+		$v[1] = $v[1]->rotateLeft(17);
57
+
58
+		#  v1 ^= v2;
59
+		$v[1] = $v[1]->xorInt64($v[2]);
60
+
61
+		# v2=ROTL(v2,32)
62
+		$v[2] = $v[2]->rotateLeft(32);
63
+
64
+		return $v;
65
+	}
66
+
67
+	/**
68
+	 * @internal You should not use this directly from another application
69
+	 *
70
+	 * @param string $in
71
+	 * @param string $key
72
+	 * @return string
73
+	 * @throws SodiumException
74
+	 * @throws TypeError
75
+	 */
76
+	public static function sipHash24($in, $key)
77
+	{
78
+		$inlen = self::strlen($in);
79
+
80
+		# /* "somepseudorandomlygeneratedbytes" */
81
+		# u64 v0 = 0x736f6d6570736575ULL;
82
+		# u64 v1 = 0x646f72616e646f6dULL;
83
+		# u64 v2 = 0x6c7967656e657261ULL;
84
+		# u64 v3 = 0x7465646279746573ULL;
85
+		$v = array(
86
+			new ParagonIE_Sodium_Core32_Int64(
87
+				array(0x736f, 0x6d65, 0x7073, 0x6575)
88
+			),
89
+			new ParagonIE_Sodium_Core32_Int64(
90
+				array(0x646f, 0x7261, 0x6e64, 0x6f6d)
91
+			),
92
+			new ParagonIE_Sodium_Core32_Int64(
93
+				array(0x6c79, 0x6765, 0x6e65, 0x7261)
94
+			),
95
+			new ParagonIE_Sodium_Core32_Int64(
96
+				array(0x7465, 0x6462, 0x7974, 0x6573)
97
+			)
98
+		);
99
+
100
+		# u64 k0 = LOAD64_LE( k );
101
+		# u64 k1 = LOAD64_LE( k + 8 );
102
+		$k = array(
103
+			ParagonIE_Sodium_Core32_Int64::fromReverseString(
104
+				self::substr($key, 0, 8)
105
+			),
106
+			ParagonIE_Sodium_Core32_Int64::fromReverseString(
107
+				self::substr($key, 8, 8)
108
+			)
109
+		);
110
+
111
+		# b = ( ( u64 )inlen ) << 56;
112
+		$b = new ParagonIE_Sodium_Core32_Int64(
113
+			array(($inlen << 8) & 0xffff, 0, 0, 0)
114
+		);
115
+
116
+		# v3 ^= k1;
117
+		$v[3] = $v[3]->xorInt64($k[1]);
118
+		# v2 ^= k0;
119
+		$v[2] = $v[2]->xorInt64($k[0]);
120
+		# v1 ^= k1;
121
+		$v[1] = $v[1]->xorInt64($k[1]);
122
+		# v0 ^= k0;
123
+		$v[0] = $v[0]->xorInt64($k[0]);
124
+
125
+		$left = $inlen;
126
+		# for ( ; in != end; in += 8 )
127
+		while ($left >= 8) {
128
+			# m = LOAD64_LE( in );
129
+			$m = ParagonIE_Sodium_Core32_Int64::fromReverseString(
130
+				self::substr($in, 0, 8)
131
+			);
132
+
133
+			# v3 ^= m;
134
+			$v[3] = $v[3]->xorInt64($m);
135
+
136
+			# SIPROUND;
137
+			# SIPROUND;
138
+			$v = self::sipRound($v);
139
+			$v = self::sipRound($v);
140
+
141
+			# v0 ^= m;
142
+			$v[0] = $v[0]->xorInt64($m);
143
+
144
+			$in = self::substr($in, 8);
145
+			$left -= 8;
146
+		}
147
+
148
+		# switch( left )
149
+		#  {
150
+		#     case 7: b |= ( ( u64 )in[ 6] )  << 48;
151
+		#     case 6: b |= ( ( u64 )in[ 5] )  << 40;
152
+		#     case 5: b |= ( ( u64 )in[ 4] )  << 32;
153
+		#     case 4: b |= ( ( u64 )in[ 3] )  << 24;
154
+		#     case 3: b |= ( ( u64 )in[ 2] )  << 16;
155
+		#     case 2: b |= ( ( u64 )in[ 1] )  <<  8;
156
+		#     case 1: b |= ( ( u64 )in[ 0] ); break;
157
+		#     case 0: break;
158
+		# }
159
+		switch ($left) {
160
+			case 7:
161
+				$b = $b->orInt64(
162
+					ParagonIE_Sodium_Core32_Int64::fromInts(
163
+						0, self::chrToInt($in[6]) << 16
164
+					)
165
+				);
166
+			case 6:
167
+				$b = $b->orInt64(
168
+					ParagonIE_Sodium_Core32_Int64::fromInts(
169
+						0, self::chrToInt($in[5]) << 8
170
+					)
171
+				);
172
+			case 5:
173
+				$b = $b->orInt64(
174
+					ParagonIE_Sodium_Core32_Int64::fromInts(
175
+						0, self::chrToInt($in[4])
176
+					)
177
+				);
178
+			case 4:
179
+				$b = $b->orInt64(
180
+					ParagonIE_Sodium_Core32_Int64::fromInts(
181
+						self::chrToInt($in[3]) << 24, 0
182
+					)
183
+				);
184
+			case 3:
185
+				$b = $b->orInt64(
186
+					ParagonIE_Sodium_Core32_Int64::fromInts(
187
+						self::chrToInt($in[2]) << 16, 0
188
+					)
189
+				);
190
+			case 2:
191
+				$b = $b->orInt64(
192
+					ParagonIE_Sodium_Core32_Int64::fromInts(
193
+						self::chrToInt($in[1]) << 8, 0
194
+					)
195
+				);
196
+			case 1:
197
+				$b = $b->orInt64(
198
+					ParagonIE_Sodium_Core32_Int64::fromInts(
199
+						self::chrToInt($in[0]), 0
200
+					)
201
+				);
202
+			case 0:
203
+				break;
204
+		}
205
+
206
+		# v3 ^= b;
207
+		$v[3] = $v[3]->xorInt64($b);
208
+
209
+		# SIPROUND;
210
+		# SIPROUND;
211
+		$v = self::sipRound($v);
212
+		$v = self::sipRound($v);
213
+
214
+		# v0 ^= b;
215
+		$v[0] = $v[0]->xorInt64($b);
216
+
217
+		// Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation
218
+		# v2 ^= 0xff;
219
+		$v[2]->limbs[3] ^= 0xff;
220
+
221
+		# SIPROUND;
222
+		# SIPROUND;
223
+		# SIPROUND;
224
+		# SIPROUND;
225
+		$v = self::sipRound($v);
226
+		$v = self::sipRound($v);
227
+		$v = self::sipRound($v);
228
+		$v = self::sipRound($v);
229
+
230
+		# b = v0 ^ v1 ^ v2 ^ v3;
231
+		# STORE64_LE( out, b );
232
+		return $v[0]
233
+			->xorInt64($v[1])
234
+			->xorInt64($v[2])
235
+			->xorInt64($v[3])
236
+			->toReverseString();
237
+	}
238 238
 }
Please login to merge, or discard this patch.
vendor/paragonie/sodium_compat/src/Core32/XChaCha20.php 1 patch
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_XChaCha20', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,56 +9,56 @@  discard block
 block discarded – undo
9 9
  */
10 10
 class ParagonIE_Sodium_Core32_XChaCha20 extends ParagonIE_Sodium_Core32_HChaCha20
11 11
 {
12
-    /**
13
-     * @internal You should not use this directly from another application
14
-     *
15
-     * @param int $len
16
-     * @param string $nonce
17
-     * @param string $key
18
-     * @return string
19
-     * @throws SodiumException
20
-     * @throws TypeError
21
-     */
22
-    public static function stream($len = 64, $nonce = '', $key = '')
23
-    {
24
-        if (self::strlen($nonce) !== 24) {
25
-            throw new SodiumException('Nonce must be 24 bytes long');
26
-        }
27
-        return self::encryptBytes(
28
-            new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
29
-                self::hChaCha20(
30
-                    self::substr($nonce, 0, 16),
31
-                    $key
32
-                ),
33
-                self::substr($nonce, 16, 8)
34
-            ),
35
-            str_repeat("\x00", $len)
36
-        );
37
-    }
12
+	/**
13
+	 * @internal You should not use this directly from another application
14
+	 *
15
+	 * @param int $len
16
+	 * @param string $nonce
17
+	 * @param string $key
18
+	 * @return string
19
+	 * @throws SodiumException
20
+	 * @throws TypeError
21
+	 */
22
+	public static function stream($len = 64, $nonce = '', $key = '')
23
+	{
24
+		if (self::strlen($nonce) !== 24) {
25
+			throw new SodiumException('Nonce must be 24 bytes long');
26
+		}
27
+		return self::encryptBytes(
28
+			new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
29
+				self::hChaCha20(
30
+					self::substr($nonce, 0, 16),
31
+					$key
32
+				),
33
+				self::substr($nonce, 16, 8)
34
+			),
35
+			str_repeat("\x00", $len)
36
+		);
37
+	}
38 38
 
39
-    /**
40
-     * @internal You should not use this directly from another application
41
-     *
42
-     * @param string $message
43
-     * @param string $nonce
44
-     * @param string $key
45
-     * @param string $ic
46
-     * @return string
47
-     * @throws SodiumException
48
-     * @throws TypeError
49
-     */
50
-    public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
51
-    {
52
-        if (self::strlen($nonce) !== 24) {
53
-            throw new SodiumException('Nonce must be 24 bytes long');
54
-        }
55
-        return self::encryptBytes(
56
-            new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
57
-                self::hChaCha20(self::substr($nonce, 0, 16), $key),
58
-                self::substr($nonce, 16, 8),
59
-                $ic
60
-            ),
61
-            $message
62
-        );
63
-    }
39
+	/**
40
+	 * @internal You should not use this directly from another application
41
+	 *
42
+	 * @param string $message
43
+	 * @param string $nonce
44
+	 * @param string $key
45
+	 * @param string $ic
46
+	 * @return string
47
+	 * @throws SodiumException
48
+	 * @throws TypeError
49
+	 */
50
+	public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
51
+	{
52
+		if (self::strlen($nonce) !== 24) {
53
+			throw new SodiumException('Nonce must be 24 bytes long');
54
+		}
55
+		return self::encryptBytes(
56
+			new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
57
+				self::hChaCha20(self::substr($nonce, 0, 16), $key),
58
+				self::substr($nonce, 16, 8),
59
+				$ic
60
+			),
61
+			$message
62
+		);
63
+	}
64 64
 }
Please login to merge, or discard this patch.