[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/sodium_compat/src/Core/ -> Ristretto255.php (source)

   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  }


Generated: Thu Sep 23 01:00:04 2021 Cross-referenced by PHPXref 0.7.1