Diff: STRATO-apps/wordpress_03/app/wp-includes/sodium_compat/src/Core/Ristretto255.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
3
+
/**
4
+
* Class ParagonIE_Sodium_Core_Ristretto255
5
+
*/
6
+
class ParagonIE_Sodium_Core_Ristretto255 extends ParagonIE_Sodium_Core_Ed25519
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
+
}
707
+
}
708
+