[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Dec 22 01:00:02 2024 | Cross-referenced by PHPXref 0.7.1 |