[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/sodium_compat/src/Core32/ -> Curve25519.php (source)

   1  <?php
   2  
   3  if (class_exists('ParagonIE_Sodium_Core32_Curve25519', false)) {
   4      return;
   5  }
   6  
   7  /**
   8   * Class ParagonIE_Sodium_Core32_Curve25519
   9   *
  10   * Implements Curve25519 core functions
  11   *
  12   * Based on the ref10 curve25519 code provided by libsodium
  13   *
  14   * @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
  15   */
  16  abstract class ParagonIE_Sodium_Core32_Curve25519 extends ParagonIE_Sodium_Core32_Curve25519_H
  17  {
  18      /**
  19       * Get a field element of size 10 with a value of 0
  20       *
  21       * @internal You should not use this directly from another application
  22       *
  23       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  24       * @throws SodiumException
  25       * @throws TypeError
  26       */
  27      public static function fe_0()
  28      {
  29          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  30              array(
  31                  new ParagonIE_Sodium_Core32_Int32(),
  32                  new ParagonIE_Sodium_Core32_Int32(),
  33                  new ParagonIE_Sodium_Core32_Int32(),
  34                  new ParagonIE_Sodium_Core32_Int32(),
  35                  new ParagonIE_Sodium_Core32_Int32(),
  36                  new ParagonIE_Sodium_Core32_Int32(),
  37                  new ParagonIE_Sodium_Core32_Int32(),
  38                  new ParagonIE_Sodium_Core32_Int32(),
  39                  new ParagonIE_Sodium_Core32_Int32(),
  40                  new ParagonIE_Sodium_Core32_Int32()
  41              )
  42          );
  43      }
  44  
  45      /**
  46       * Get a field element of size 10 with a value of 1
  47       *
  48       * @internal You should not use this directly from another application
  49       *
  50       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  51       * @throws SodiumException
  52       * @throws TypeError
  53       */
  54      public static function fe_1()
  55      {
  56          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  57              array(
  58                  ParagonIE_Sodium_Core32_Int32::fromInt(1),
  59                  new ParagonIE_Sodium_Core32_Int32(),
  60                  new ParagonIE_Sodium_Core32_Int32(),
  61                  new ParagonIE_Sodium_Core32_Int32(),
  62                  new ParagonIE_Sodium_Core32_Int32(),
  63                  new ParagonIE_Sodium_Core32_Int32(),
  64                  new ParagonIE_Sodium_Core32_Int32(),
  65                  new ParagonIE_Sodium_Core32_Int32(),
  66                  new ParagonIE_Sodium_Core32_Int32(),
  67                  new ParagonIE_Sodium_Core32_Int32()
  68              )
  69          );
  70      }
  71  
  72      /**
  73       * Add two field elements.
  74       *
  75       * @internal You should not use this directly from another application
  76       *
  77       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  78       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
  79       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  80       * @throws SodiumException
  81       * @throws TypeError
  82       * @psalm-suppress MixedAssignment
  83       * @psalm-suppress MixedMethodCall
  84       */
  85      public static function fe_add(
  86          ParagonIE_Sodium_Core32_Curve25519_Fe $f,
  87          ParagonIE_Sodium_Core32_Curve25519_Fe $g
  88      ) {
  89          $arr = array();
  90          for ($i = 0; $i < 10; ++$i) {
  91              $arr[$i] = $f[$i]->addInt32($g[$i]);
  92          }
  93          /** @var array<int, ParagonIE_Sodium_Core32_Int32> $arr */
  94          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($arr);
  95      }
  96  
  97      /**
  98       * Constant-time conditional move.
  99       *
 100       * @internal You should not use this directly from another application
 101       *
 102       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 103       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
 104       * @param int $b
 105       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
 106       * @throws SodiumException
 107       * @throws TypeError
 108       * @psalm-suppress MixedAssignment
 109       * @psalm-suppress MixedMethodCall
 110       */
 111      public static function fe_cmov(
 112          ParagonIE_Sodium_Core32_Curve25519_Fe $f,
 113          ParagonIE_Sodium_Core32_Curve25519_Fe $g,
 114          $b = 0
 115      ) {
 116          /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
 117          $h = array();
 118          for ($i = 0; $i < 10; ++$i) {
 119              if (!($f[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
 120                  throw new TypeError('Expected Int32');
 121              }
 122              if (!($g[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
 123                  throw new TypeError('Expected Int32');
 124              }
 125              $h[$i] = $f[$i]->xorInt32(
 126                  $f[$i]->xorInt32($g[$i])->mask($b)
 127              );
 128          }
 129          /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
 130          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h);
 131      }
 132  
 133      /**
 134       * Create a copy of a field element.
 135       *
 136       * @internal You should not use this directly from another application
 137       *
 138       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 139       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
 140       */
 141      public static function fe_copy(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
 142      {
 143          $h = clone $f;
 144          return $h;
 145      }
 146  
 147      /**
 148       * Give: 32-byte string.
 149       * Receive: A field element object to use for internal calculations.
 150       *
 151       * @internal You should not use this directly from another application
 152       *
 153       * @param string $s
 154       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
 155       * @throws RangeException
 156       * @throws SodiumException
 157       * @throws TypeError
 158       * @psalm-suppress MixedMethodCall
 159       */
 160      public static function fe_frombytes($s)
 161      {
 162          if (self::strlen($s) !== 32) {
 163              throw new RangeException('Expected a 32-byte string.');
 164          }
 165          /** @var ParagonIE_Sodium_Core32_Int32 $h0 */
 166          $h0 = ParagonIE_Sodium_Core32_Int32::fromInt(
 167              self::load_4($s)
 168          );
 169          /** @var ParagonIE_Sodium_Core32_Int32 $h1 */
 170          $h1 = ParagonIE_Sodium_Core32_Int32::fromInt(
 171              self::load_3(self::substr($s, 4, 3)) << 6
 172          );
 173          /** @var ParagonIE_Sodium_Core32_Int32 $h2 */
 174          $h2 = ParagonIE_Sodium_Core32_Int32::fromInt(
 175              self::load_3(self::substr($s, 7, 3)) << 5
 176          );
 177          /** @var ParagonIE_Sodium_Core32_Int32 $h3 */
 178          $h3 = ParagonIE_Sodium_Core32_Int32::fromInt(
 179              self::load_3(self::substr($s, 10, 3)) << 3
 180          );
 181          /** @var ParagonIE_Sodium_Core32_Int32 $h4 */
 182          $h4 = ParagonIE_Sodium_Core32_Int32::fromInt(
 183              self::load_3(self::substr($s, 13, 3)) << 2
 184          );
 185          /** @var ParagonIE_Sodium_Core32_Int32 $h5 */
 186          $h5 = ParagonIE_Sodium_Core32_Int32::fromInt(
 187              self::load_4(self::substr($s, 16, 4))
 188          );
 189          /** @var ParagonIE_Sodium_Core32_Int32 $h6 */
 190          $h6 = ParagonIE_Sodium_Core32_Int32::fromInt(
 191              self::load_3(self::substr($s, 20, 3)) << 7
 192          );
 193          /** @var ParagonIE_Sodium_Core32_Int32 $h7 */
 194          $h7 = ParagonIE_Sodium_Core32_Int32::fromInt(
 195              self::load_3(self::substr($s, 23, 3)) << 5
 196          );
 197          /** @var ParagonIE_Sodium_Core32_Int32 $h8 */
 198          $h8 = ParagonIE_Sodium_Core32_Int32::fromInt(
 199              self::load_3(self::substr($s, 26, 3)) << 4
 200          );
 201          /** @var ParagonIE_Sodium_Core32_Int32 $h9 */
 202          $h9 = ParagonIE_Sodium_Core32_Int32::fromInt(
 203              (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2
 204          );
 205  
 206          $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
 207          $h0 = $h0->addInt32($carry9->mulInt(19, 5));
 208          $h9 = $h9->subInt32($carry9->shiftLeft(25));
 209  
 210          $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
 211          $h2 = $h2->addInt32($carry1);
 212          $h1 = $h1->subInt32($carry1->shiftLeft(25));
 213  
 214          $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
 215          $h4 = $h4->addInt32($carry3);
 216          $h3 = $h3->subInt32($carry3->shiftLeft(25));
 217  
 218          $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
 219          $h6 = $h6->addInt32($carry5);
 220          $h5 = $h5->subInt32($carry5->shiftLeft(25));
 221  
 222          $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
 223          $h8 = $h8->addInt32($carry7);
 224          $h7 = $h7->subInt32($carry7->shiftLeft(25));
 225  
 226          $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
 227          $h1 = $h1->addInt32($carry0);
 228          $h0 = $h0->subInt32($carry0->shiftLeft(26));
 229  
 230          $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
 231          $h3 = $h3->addInt32($carry2);
 232          $h2 = $h2->subInt32($carry2->shiftLeft(26));
 233  
 234          $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
 235          $h5 = $h5->addInt32($carry4);
 236          $h4 = $h4->subInt32($carry4->shiftLeft(26));
 237  
 238          $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
 239          $h7 = $h7->addInt32($carry6);
 240          $h6 = $h6->subInt32($carry6->shiftLeft(26));
 241  
 242          $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
 243          $h9 = $h9->addInt32($carry8);
 244          $h8 = $h8->subInt32($carry8->shiftLeft(26));
 245  
 246          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
 247              array($h0, $h1, $h2,$h3, $h4, $h5, $h6, $h7, $h8, $h9)
 248          );
 249      }
 250  
 251      /**
 252       * Convert a field element to a byte string.
 253       *
 254       * @internal You should not use this directly from another application
 255       *
 256       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $h
 257       * @return string
 258       * @throws SodiumException
 259       * @throws TypeError
 260       * @psalm-suppress MixedAssignment
 261       * @psalm-suppress MixedMethodCall
 262       */
 263      public static function fe_tobytes(ParagonIE_Sodium_Core32_Curve25519_Fe $h)
 264      {
 265          /**
 266           * @var ParagonIE_Sodium_Core32_Int64[] $f
 267           * @var ParagonIE_Sodium_Core32_Int64 $q
 268           */
 269          $f = array();
 270  
 271          for ($i = 0; $i < 10; ++$i) {
 272              $f[$i] = $h[$i]->toInt64();
 273          }
 274  
 275          $q = $f[9]->mulInt(19, 5)->addInt(1 << 14)->shiftRight(25)
 276              ->addInt64($f[0])->shiftRight(26)
 277              ->addInt64($f[1])->shiftRight(25)
 278              ->addInt64($f[2])->shiftRight(26)
 279              ->addInt64($f[3])->shiftRight(25)
 280              ->addInt64($f[4])->shiftRight(26)
 281              ->addInt64($f[5])->shiftRight(25)
 282              ->addInt64($f[6])->shiftRight(26)
 283              ->addInt64($f[7])->shiftRight(25)
 284              ->addInt64($f[8])->shiftRight(26)
 285              ->addInt64($f[9])->shiftRight(25);
 286  
 287          $f[0] = $f[0]->addInt64($q->mulInt(19, 5));
 288  
 289          $carry0 = $f[0]->shiftRight(26);
 290          $f[1] = $f[1]->addInt64($carry0);
 291          $f[0] = $f[0]->subInt64($carry0->shiftLeft(26));
 292  
 293          $carry1 = $f[1]->shiftRight(25);
 294          $f[2] = $f[2]->addInt64($carry1);
 295          $f[1] = $f[1]->subInt64($carry1->shiftLeft(25));
 296  
 297          $carry2 = $f[2]->shiftRight(26);
 298          $f[3] = $f[3]->addInt64($carry2);
 299          $f[2] = $f[2]->subInt64($carry2->shiftLeft(26));
 300  
 301          $carry3 = $f[3]->shiftRight(25);
 302          $f[4] = $f[4]->addInt64($carry3);
 303          $f[3] = $f[3]->subInt64($carry3->shiftLeft(25));
 304  
 305          $carry4 = $f[4]->shiftRight(26);
 306          $f[5] = $f[5]->addInt64($carry4);
 307          $f[4] = $f[4]->subInt64($carry4->shiftLeft(26));
 308  
 309          $carry5 = $f[5]->shiftRight(25);
 310          $f[6] = $f[6]->addInt64($carry5);
 311          $f[5] = $f[5]->subInt64($carry5->shiftLeft(25));
 312  
 313          $carry6 = $f[6]->shiftRight(26);
 314          $f[7] = $f[7]->addInt64($carry6);
 315          $f[6] = $f[6]->subInt64($carry6->shiftLeft(26));
 316  
 317          $carry7 = $f[7]->shiftRight(25);
 318          $f[8] = $f[8]->addInt64($carry7);
 319          $f[7] = $f[7]->subInt64($carry7->shiftLeft(25));
 320  
 321          $carry8 = $f[8]->shiftRight(26);
 322          $f[9] = $f[9]->addInt64($carry8);
 323          $f[8] = $f[8]->subInt64($carry8->shiftLeft(26));
 324  
 325          $carry9 = $f[9]->shiftRight(25);
 326          $f[9] = $f[9]->subInt64($carry9->shiftLeft(25));
 327  
 328          $h0 = $f[0]->toInt32()->toInt();
 329          $h1 = $f[1]->toInt32()->toInt();
 330          $h2 = $f[2]->toInt32()->toInt();
 331          $h3 = $f[3]->toInt32()->toInt();
 332          $h4 = $f[4]->toInt32()->toInt();
 333          $h5 = $f[5]->toInt32()->toInt();
 334          $h6 = $f[6]->toInt32()->toInt();
 335          $h7 = $f[7]->toInt32()->toInt();
 336          $h8 = $f[8]->toInt32()->toInt();
 337          $h9 = $f[9]->toInt32()->toInt();
 338  
 339          /**
 340           * @var array<int, int>
 341           */
 342          $s = array(
 343              (int) (($h0 >> 0) & 0xff),
 344              (int) (($h0 >> 8) & 0xff),
 345              (int) (($h0 >> 16) & 0xff),
 346              (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
 347              (int) (($h1 >> 6) & 0xff),
 348              (int) (($h1 >> 14) & 0xff),
 349              (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
 350              (int) (($h2 >> 5) & 0xff),
 351              (int) (($h2 >> 13) & 0xff),
 352              (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
 353              (int) (($h3 >> 3) & 0xff),
 354              (int) (($h3 >> 11) & 0xff),
 355              (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
 356              (int) (($h4 >> 2) & 0xff),
 357              (int) (($h4 >> 10) & 0xff),
 358              (int) (($h4 >> 18) & 0xff),
 359              (int) (($h5 >> 0) & 0xff),
 360              (int) (($h5 >> 8) & 0xff),
 361              (int) (($h5 >> 16) & 0xff),
 362              (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
 363              (int) (($h6 >> 7) & 0xff),
 364              (int) (($h6 >> 15) & 0xff),
 365              (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
 366              (int) (($h7 >> 5) & 0xff),
 367              (int) (($h7 >> 13) & 0xff),
 368              (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
 369              (int) (($h8 >> 4) & 0xff),
 370              (int) (($h8 >> 12) & 0xff),
 371              (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
 372              (int) (($h9 >> 2) & 0xff),
 373              (int) (($h9 >> 10) & 0xff),
 374              (int) (($h9 >> 18) & 0xff)
 375          );
 376          return self::intArrayToString($s);
 377      }
 378  
 379      /**
 380       * Is a field element negative? (1 = yes, 0 = no. Used in calculations.)
 381       *
 382       * @internal You should not use this directly from another application
 383       *
 384       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 385       * @return int
 386       * @throws SodiumException
 387       * @throws TypeError
 388       */
 389      public static function fe_isnegative(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
 390      {
 391          $str = self::fe_tobytes($f);
 392          return (int) (self::chrToInt($str[0]) & 1);
 393      }
 394  
 395      /**
 396       * Returns 0 if this field element results in all NUL bytes.
 397       *
 398       * @internal You should not use this directly from another application
 399       *
 400       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 401       * @return bool
 402       * @throws SodiumException
 403       * @throws TypeError
 404       */
 405      public static function fe_isnonzero(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
 406      {
 407          static $zero;
 408          if ($zero === null) {
 409              $zero = str_repeat("\x00", 32);
 410          }
 411          $str = self::fe_tobytes($f);
 412          /** @var string $zero */
 413          return !self::verify_32($str, $zero);
 414      }
 415  
 416      /**
 417       * Multiply two field elements
 418       *
 419       * h = f * g
 420       *
 421       * @internal You should not use this directly from another application
 422       *
 423       * @security Is multiplication a source of timing leaks? If so, can we do
 424       *           anything to prevent that from happening?
 425       *
 426       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 427       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
 428       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
 429       * @throws SodiumException
 430       * @throws TypeError
 431       */
 432      public static function fe_mul(
 433          ParagonIE_Sodium_Core32_Curve25519_Fe $f,
 434          ParagonIE_Sodium_Core32_Curve25519_Fe $g
 435      ) {
 436          /**
 437           * @var ParagonIE_Sodium_Core32_Int32[] $f
 438           * @var ParagonIE_Sodium_Core32_Int32[] $g
 439           * @var ParagonIE_Sodium_Core32_Int64 $f0
 440           * @var ParagonIE_Sodium_Core32_Int64 $f1
 441           * @var ParagonIE_Sodium_Core32_Int64 $f2
 442           * @var ParagonIE_Sodium_Core32_Int64 $f3
 443           * @var ParagonIE_Sodium_Core32_Int64 $f4
 444           * @var ParagonIE_Sodium_Core32_Int64 $f5
 445           * @var ParagonIE_Sodium_Core32_Int64 $f6
 446           * @var ParagonIE_Sodium_Core32_Int64 $f7
 447           * @var ParagonIE_Sodium_Core32_Int64 $f8
 448           * @var ParagonIE_Sodium_Core32_Int64 $f9
 449           * @var ParagonIE_Sodium_Core32_Int64 $g0
 450           * @var ParagonIE_Sodium_Core32_Int64 $g1
 451           * @var ParagonIE_Sodium_Core32_Int64 $g2
 452           * @var ParagonIE_Sodium_Core32_Int64 $g3
 453           * @var ParagonIE_Sodium_Core32_Int64 $g4
 454           * @var ParagonIE_Sodium_Core32_Int64 $g5
 455           * @var ParagonIE_Sodium_Core32_Int64 $g6
 456           * @var ParagonIE_Sodium_Core32_Int64 $g7
 457           * @var ParagonIE_Sodium_Core32_Int64 $g8
 458           * @var ParagonIE_Sodium_Core32_Int64 $g9
 459           */
 460          $f0 = $f[0]->toInt64();
 461          $f1 = $f[1]->toInt64();
 462          $f2 = $f[2]->toInt64();
 463          $f3 = $f[3]->toInt64();
 464          $f4 = $f[4]->toInt64();
 465          $f5 = $f[5]->toInt64();
 466          $f6 = $f[6]->toInt64();
 467          $f7 = $f[7]->toInt64();
 468          $f8 = $f[8]->toInt64();
 469          $f9 = $f[9]->toInt64();
 470          $g0 = $g[0]->toInt64();
 471          $g1 = $g[1]->toInt64();
 472          $g2 = $g[2]->toInt64();
 473          $g3 = $g[3]->toInt64();
 474          $g4 = $g[4]->toInt64();
 475          $g5 = $g[5]->toInt64();
 476          $g6 = $g[6]->toInt64();
 477          $g7 = $g[7]->toInt64();
 478          $g8 = $g[8]->toInt64();
 479          $g9 = $g[9]->toInt64();
 480          $g1_19 = $g1->mulInt(19, 5); /* 2^4 <= 19 <= 2^5, but we only want 5 bits */
 481          $g2_19 = $g2->mulInt(19, 5);
 482          $g3_19 = $g3->mulInt(19, 5);
 483          $g4_19 = $g4->mulInt(19, 5);
 484          $g5_19 = $g5->mulInt(19, 5);
 485          $g6_19 = $g6->mulInt(19, 5);
 486          $g7_19 = $g7->mulInt(19, 5);
 487          $g8_19 = $g8->mulInt(19, 5);
 488          $g9_19 = $g9->mulInt(19, 5);
 489          $f1_2 = $f1->shiftLeft(1);
 490          $f3_2 = $f3->shiftLeft(1);
 491          $f5_2 = $f5->shiftLeft(1);
 492          $f7_2 = $f7->shiftLeft(1);
 493          $f9_2 = $f9->shiftLeft(1);
 494          $f0g0    = $f0->mulInt64($g0, 27);
 495          $f0g1    = $f0->mulInt64($g1, 27);
 496          $f0g2    = $f0->mulInt64($g2, 27);
 497          $f0g3    = $f0->mulInt64($g3, 27);
 498          $f0g4    = $f0->mulInt64($g4, 27);
 499          $f0g5    = $f0->mulInt64($g5, 27);
 500          $f0g6    = $f0->mulInt64($g6, 27);
 501          $f0g7    = $f0->mulInt64($g7, 27);
 502          $f0g8    = $f0->mulInt64($g8, 27);
 503          $f0g9    = $f0->mulInt64($g9, 27);
 504          $f1g0    = $f1->mulInt64($g0, 27);
 505          $f1g1_2  = $f1_2->mulInt64($g1, 27);
 506          $f1g2    = $f1->mulInt64($g2, 27);
 507          $f1g3_2  = $f1_2->mulInt64($g3, 27);
 508          $f1g4    = $f1->mulInt64($g4, 30);
 509          $f1g5_2  = $f1_2->mulInt64($g5, 30);
 510          $f1g6    = $f1->mulInt64($g6, 30);
 511          $f1g7_2  = $f1_2->mulInt64($g7, 30);
 512          $f1g8    = $f1->mulInt64($g8, 30);
 513          $f1g9_38 = $g9_19->mulInt64($f1_2, 30);
 514          $f2g0    = $f2->mulInt64($g0, 30);
 515          $f2g1    = $f2->mulInt64($g1, 29);
 516          $f2g2    = $f2->mulInt64($g2, 30);
 517          $f2g3    = $f2->mulInt64($g3, 29);
 518          $f2g4    = $f2->mulInt64($g4, 30);
 519          $f2g5    = $f2->mulInt64($g5, 29);
 520          $f2g6    = $f2->mulInt64($g6, 30);
 521          $f2g7    = $f2->mulInt64($g7, 29);
 522          $f2g8_19 = $g8_19->mulInt64($f2, 30);
 523          $f2g9_19 = $g9_19->mulInt64($f2, 30);
 524          $f3g0    = $f3->mulInt64($g0, 30);
 525          $f3g1_2  = $f3_2->mulInt64($g1, 30);
 526          $f3g2    = $f3->mulInt64($g2, 30);
 527          $f3g3_2  = $f3_2->mulInt64($g3, 30);
 528          $f3g4    = $f3->mulInt64($g4, 30);
 529          $f3g5_2  = $f3_2->mulInt64($g5, 30);
 530          $f3g6    = $f3->mulInt64($g6, 30);
 531          $f3g7_38 = $g7_19->mulInt64($f3_2, 30);
 532          $f3g8_19 = $g8_19->mulInt64($f3, 30);
 533          $f3g9_38 = $g9_19->mulInt64($f3_2, 30);
 534          $f4g0    = $f4->mulInt64($g0, 30);
 535          $f4g1    = $f4->mulInt64($g1, 30);
 536          $f4g2    = $f4->mulInt64($g2, 30);
 537          $f4g3    = $f4->mulInt64($g3, 30);
 538          $f4g4    = $f4->mulInt64($g4, 30);
 539          $f4g5    = $f4->mulInt64($g5, 30);
 540          $f4g6_19 = $g6_19->mulInt64($f4, 30);
 541          $f4g7_19 = $g7_19->mulInt64($f4, 30);
 542          $f4g8_19 = $g8_19->mulInt64($f4, 30);
 543          $f4g9_19 = $g9_19->mulInt64($f4, 30);
 544          $f5g0    = $f5->mulInt64($g0, 30);
 545          $f5g1_2  = $f5_2->mulInt64($g1, 30);
 546          $f5g2    = $f5->mulInt64($g2, 30);
 547          $f5g3_2  = $f5_2->mulInt64($g3, 30);
 548          $f5g4    = $f5->mulInt64($g4, 30);
 549          $f5g5_38 = $g5_19->mulInt64($f5_2, 30);
 550          $f5g6_19 = $g6_19->mulInt64($f5, 30);
 551          $f5g7_38 = $g7_19->mulInt64($f5_2, 30);
 552          $f5g8_19 = $g8_19->mulInt64($f5, 30);
 553          $f5g9_38 = $g9_19->mulInt64($f5_2, 30);
 554          $f6g0    = $f6->mulInt64($g0, 30);
 555          $f6g1    = $f6->mulInt64($g1, 30);
 556          $f6g2    = $f6->mulInt64($g2, 30);
 557          $f6g3    = $f6->mulInt64($g3, 30);
 558          $f6g4_19 = $g4_19->mulInt64($f6, 30);
 559          $f6g5_19 = $g5_19->mulInt64($f6, 30);
 560          $f6g6_19 = $g6_19->mulInt64($f6, 30);
 561          $f6g7_19 = $g7_19->mulInt64($f6, 30);
 562          $f6g8_19 = $g8_19->mulInt64($f6, 30);
 563          $f6g9_19 = $g9_19->mulInt64($f6, 30);
 564          $f7g0    = $f7->mulInt64($g0, 30);
 565          $f7g1_2  = $g1->mulInt64($f7_2, 30);
 566          $f7g2    = $f7->mulInt64($g2, 30);
 567          $f7g3_38 = $g3_19->mulInt64($f7_2, 30);
 568          $f7g4_19 = $g4_19->mulInt64($f7, 30);
 569          $f7g5_38 = $g5_19->mulInt64($f7_2, 30);
 570          $f7g6_19 = $g6_19->mulInt64($f7, 30);
 571          $f7g7_38 = $g7_19->mulInt64($f7_2, 30);
 572          $f7g8_19 = $g8_19->mulInt64($f7, 30);
 573          $f7g9_38 = $g9_19->mulInt64($f7_2, 30);
 574          $f8g0    = $f8->mulInt64($g0, 30);
 575          $f8g1    = $f8->mulInt64($g1, 29);
 576          $f8g2_19 = $g2_19->mulInt64($f8, 30);
 577          $f8g3_19 = $g3_19->mulInt64($f8, 30);
 578          $f8g4_19 = $g4_19->mulInt64($f8, 30);
 579          $f8g5_19 = $g5_19->mulInt64($f8, 30);
 580          $f8g6_19 = $g6_19->mulInt64($f8, 30);
 581          $f8g7_19 = $g7_19->mulInt64($f8, 30);
 582          $f8g8_19 = $g8_19->mulInt64($f8, 30);
 583          $f8g9_19 = $g9_19->mulInt64($f8, 30);
 584          $f9g0    = $f9->mulInt64($g0, 30);
 585          $f9g1_38 = $g1_19->mulInt64($f9_2, 30);
 586          $f9g2_19 = $g2_19->mulInt64($f9, 30);
 587          $f9g3_38 = $g3_19->mulInt64($f9_2, 30);
 588          $f9g4_19 = $g4_19->mulInt64($f9, 30);
 589          $f9g5_38 = $g5_19->mulInt64($f9_2, 30);
 590          $f9g6_19 = $g6_19->mulInt64($f9, 30);
 591          $f9g7_38 = $g7_19->mulInt64($f9_2, 30);
 592          $f9g8_19 = $g8_19->mulInt64($f9, 30);
 593          $f9g9_38 = $g9_19->mulInt64($f9_2, 30);
 594  
 595          // $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
 596          $h0 = $f0g0->addInt64($f1g9_38)->addInt64($f2g8_19)->addInt64($f3g7_38)
 597              ->addInt64($f4g6_19)->addInt64($f5g5_38)->addInt64($f6g4_19)
 598              ->addInt64($f7g3_38)->addInt64($f8g2_19)->addInt64($f9g1_38);
 599  
 600          // $h1 = $f0g1 + $f1g0    + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
 601          $h1 = $f0g1->addInt64($f1g0)->addInt64($f2g9_19)->addInt64($f3g8_19)
 602              ->addInt64($f4g7_19)->addInt64($f5g6_19)->addInt64($f6g5_19)
 603              ->addInt64($f7g4_19)->addInt64($f8g3_19)->addInt64($f9g2_19);
 604  
 605          // $h2 = $f0g2 + $f1g1_2  + $f2g0    + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
 606          $h2 = $f0g2->addInt64($f1g1_2)->addInt64($f2g0)->addInt64($f3g9_38)
 607              ->addInt64($f4g8_19)->addInt64($f5g7_38)->addInt64($f6g6_19)
 608              ->addInt64($f7g5_38)->addInt64($f8g4_19)->addInt64($f9g3_38);
 609  
 610          // $h3 = $f0g3 + $f1g2    + $f2g1    + $f3g0    + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
 611          $h3 = $f0g3->addInt64($f1g2)->addInt64($f2g1)->addInt64($f3g0)
 612              ->addInt64($f4g9_19)->addInt64($f5g8_19)->addInt64($f6g7_19)
 613              ->addInt64($f7g6_19)->addInt64($f8g5_19)->addInt64($f9g4_19);
 614  
 615          // $h4 = $f0g4 + $f1g3_2  + $f2g2    + $f3g1_2  + $f4g0    + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
 616          $h4 = $f0g4->addInt64($f1g3_2)->addInt64($f2g2)->addInt64($f3g1_2)
 617              ->addInt64($f4g0)->addInt64($f5g9_38)->addInt64($f6g8_19)
 618              ->addInt64($f7g7_38)->addInt64($f8g6_19)->addInt64($f9g5_38);
 619  
 620          // $h5 = $f0g5 + $f1g4    + $f2g3    + $f3g2    + $f4g1    + $f5g0    + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
 621          $h5 = $f0g5->addInt64($f1g4)->addInt64($f2g3)->addInt64($f3g2)
 622              ->addInt64($f4g1)->addInt64($f5g0)->addInt64($f6g9_19)
 623              ->addInt64($f7g8_19)->addInt64($f8g7_19)->addInt64($f9g6_19);
 624  
 625          // $h6 = $f0g6 + $f1g5_2  + $f2g4    + $f3g3_2  + $f4g2    + $f5g1_2  + $f6g0    + $f7g9_38 + $f8g8_19 + $f9g7_38;
 626          $h6 = $f0g6->addInt64($f1g5_2)->addInt64($f2g4)->addInt64($f3g3_2)
 627              ->addInt64($f4g2)->addInt64($f5g1_2)->addInt64($f6g0)
 628              ->addInt64($f7g9_38)->addInt64($f8g8_19)->addInt64($f9g7_38);
 629  
 630          // $h7 = $f0g7 + $f1g6    + $f2g5    + $f3g4    + $f4g3    + $f5g2    + $f6g1    + $f7g0    + $f8g9_19 + $f9g8_19;
 631          $h7 = $f0g7->addInt64($f1g6)->addInt64($f2g5)->addInt64($f3g4)
 632              ->addInt64($f4g3)->addInt64($f5g2)->addInt64($f6g1)
 633              ->addInt64($f7g0)->addInt64($f8g9_19)->addInt64($f9g8_19);
 634  
 635          // $h8 = $f0g8 + $f1g7_2  + $f2g6    + $f3g5_2  + $f4g4    + $f5g3_2  + $f6g2    + $f7g1_2  + $f8g0    + $f9g9_38;
 636          $h8 = $f0g8->addInt64($f1g7_2)->addInt64($f2g6)->addInt64($f3g5_2)
 637              ->addInt64($f4g4)->addInt64($f5g3_2)->addInt64($f6g2)
 638              ->addInt64($f7g1_2)->addInt64($f8g0)->addInt64($f9g9_38);
 639  
 640          // $h9 = $f0g9 + $f1g8    + $f2g7    + $f3g6    + $f4g5    + $f5g4    + $f6g3    + $f7g2    + $f8g1    + $f9g0   ;
 641          $h9 = $f0g9->addInt64($f1g8)->addInt64($f2g7)->addInt64($f3g6)
 642              ->addInt64($f4g5)->addInt64($f5g4)->addInt64($f6g3)
 643              ->addInt64($f7g2)->addInt64($f8g1)->addInt64($f9g0);
 644  
 645          /**
 646           * @var ParagonIE_Sodium_Core32_Int64 $h0
 647           * @var ParagonIE_Sodium_Core32_Int64 $h1
 648           * @var ParagonIE_Sodium_Core32_Int64 $h2
 649           * @var ParagonIE_Sodium_Core32_Int64 $h3
 650           * @var ParagonIE_Sodium_Core32_Int64 $h4
 651           * @var ParagonIE_Sodium_Core32_Int64 $h5
 652           * @var ParagonIE_Sodium_Core32_Int64 $h6
 653           * @var ParagonIE_Sodium_Core32_Int64 $h7
 654           * @var ParagonIE_Sodium_Core32_Int64 $h8
 655           * @var ParagonIE_Sodium_Core32_Int64 $h9
 656           * @var ParagonIE_Sodium_Core32_Int64 $carry0
 657           * @var ParagonIE_Sodium_Core32_Int64 $carry1
 658           * @var ParagonIE_Sodium_Core32_Int64 $carry2
 659           * @var ParagonIE_Sodium_Core32_Int64 $carry3
 660           * @var ParagonIE_Sodium_Core32_Int64 $carry4
 661           * @var ParagonIE_Sodium_Core32_Int64 $carry5
 662           * @var ParagonIE_Sodium_Core32_Int64 $carry6
 663           * @var ParagonIE_Sodium_Core32_Int64 $carry7
 664           * @var ParagonIE_Sodium_Core32_Int64 $carry8
 665           * @var ParagonIE_Sodium_Core32_Int64 $carry9
 666           */
 667          $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
 668          $h1 = $h1->addInt64($carry0);
 669          $h0 = $h0->subInt64($carry0->shiftLeft(26));
 670          $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
 671          $h5 = $h5->addInt64($carry4);
 672          $h4 = $h4->subInt64($carry4->shiftLeft(26));
 673  
 674          $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
 675          $h2 = $h2->addInt64($carry1);
 676          $h1 = $h1->subInt64($carry1->shiftLeft(25));
 677          $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
 678          $h6 = $h6->addInt64($carry5);
 679          $h5 = $h5->subInt64($carry5->shiftLeft(25));
 680  
 681          $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
 682          $h3 = $h3->addInt64($carry2);
 683          $h2 = $h2->subInt64($carry2->shiftLeft(26));
 684          $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
 685          $h7 = $h7->addInt64($carry6);
 686          $h6 = $h6->subInt64($carry6->shiftLeft(26));
 687  
 688          $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
 689          $h4 = $h4->addInt64($carry3);
 690          $h3 = $h3->subInt64($carry3->shiftLeft(25));
 691          $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
 692          $h8 = $h8->addInt64($carry7);
 693          $h7 = $h7->subInt64($carry7->shiftLeft(25));
 694  
 695          $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
 696          $h5 = $h5->addInt64($carry4);
 697          $h4 = $h4->subInt64($carry4->shiftLeft(26));
 698          $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
 699          $h9 = $h9->addInt64($carry8);
 700          $h8 = $h8->subInt64($carry8->shiftLeft(26));
 701  
 702          $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
 703          $h0 = $h0->addInt64($carry9->mulInt(19, 5));
 704          $h9 = $h9->subInt64($carry9->shiftLeft(25));
 705  
 706          $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
 707          $h1 = $h1->addInt64($carry0);
 708          $h0 = $h0->subInt64($carry0->shiftLeft(26));
 709  
 710          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
 711              array(
 712                  $h0->toInt32(),
 713                  $h1->toInt32(),
 714                  $h2->toInt32(),
 715                  $h3->toInt32(),
 716                  $h4->toInt32(),
 717                  $h5->toInt32(),
 718                  $h6->toInt32(),
 719                  $h7->toInt32(),
 720                  $h8->toInt32(),
 721                  $h9->toInt32()
 722              )
 723          );
 724      }
 725  
 726      /**
 727       * Get the negative values for each piece of the field element.
 728       *
 729       * h = -f
 730       *
 731       * @internal You should not use this directly from another application
 732       *
 733       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 734       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
 735       * @psalm-suppress MixedAssignment
 736       * @psalm-suppress MixedMethodCall
 737       */
 738      public static function fe_neg(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
 739      {
 740          $h = new ParagonIE_Sodium_Core32_Curve25519_Fe();
 741          for ($i = 0; $i < 10; ++$i) {
 742              $h[$i] = $h[$i]->subInt32($f[$i]);
 743          }
 744          return $h;
 745      }
 746  
 747      /**
 748       * Square a field element
 749       *
 750       * h = f * f
 751       *
 752       * @internal You should not use this directly from another application
 753       *
 754       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 755       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
 756       * @throws SodiumException
 757       * @throws TypeError
 758       * @psalm-suppress MixedMethodCall
 759       */
 760      public static function fe_sq(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
 761      {
 762          $f0 = $f[0]->toInt64();
 763          $f1 = $f[1]->toInt64();
 764          $f2 = $f[2]->toInt64();
 765          $f3 = $f[3]->toInt64();
 766          $f4 = $f[4]->toInt64();
 767          $f5 = $f[5]->toInt64();
 768          $f6 = $f[6]->toInt64();
 769          $f7 = $f[7]->toInt64();
 770          $f8 = $f[8]->toInt64();
 771          $f9 = $f[9]->toInt64();
 772  
 773          $f0_2 = $f0->shiftLeft(1);
 774          $f1_2 = $f1->shiftLeft(1);
 775          $f2_2 = $f2->shiftLeft(1);
 776          $f3_2 = $f3->shiftLeft(1);
 777          $f4_2 = $f4->shiftLeft(1);
 778          $f5_2 = $f5->shiftLeft(1);
 779          $f6_2 = $f6->shiftLeft(1);
 780          $f7_2 = $f7->shiftLeft(1);
 781          $f5_38 = $f5->mulInt(38, 6);
 782          $f6_19 = $f6->mulInt(19, 5);
 783          $f7_38 = $f7->mulInt(38, 6);
 784          $f8_19 = $f8->mulInt(19, 5);
 785          $f9_38 = $f9->mulInt(38, 6);
 786  
 787          $f0f0    = $f0->mulInt64($f0, 28);
 788          $f0f1_2  = $f0_2->mulInt64($f1, 28);
 789          $f0f2_2 =  $f0_2->mulInt64($f2, 28);
 790          $f0f3_2 =  $f0_2->mulInt64($f3, 28);
 791          $f0f4_2 =  $f0_2->mulInt64($f4, 28);
 792          $f0f5_2 =  $f0_2->mulInt64($f5, 28);
 793          $f0f6_2 =  $f0_2->mulInt64($f6, 28);
 794          $f0f7_2 =  $f0_2->mulInt64($f7, 28);
 795          $f0f8_2 =  $f0_2->mulInt64($f8, 28);
 796          $f0f9_2 =  $f0_2->mulInt64($f9, 28);
 797  
 798          $f1f1_2 = $f1_2->mulInt64($f1, 28);
 799          $f1f2_2 = $f1_2->mulInt64($f2, 28);
 800          $f1f3_4 = $f1_2->mulInt64($f3_2, 28);
 801          $f1f4_2 = $f1_2->mulInt64($f4, 28);
 802          $f1f5_4 = $f1_2->mulInt64($f5_2, 30);
 803          $f1f6_2 = $f1_2->mulInt64($f6, 28);
 804          $f1f7_4 = $f1_2->mulInt64($f7_2, 28);
 805          $f1f8_2 = $f1_2->mulInt64($f8, 28);
 806          $f1f9_76 = $f9_38->mulInt64($f1_2, 30);
 807  
 808          $f2f2 = $f2->mulInt64($f2, 28);
 809          $f2f3_2 = $f2_2->mulInt64($f3, 28);
 810          $f2f4_2 = $f2_2->mulInt64($f4, 28);
 811          $f2f5_2 = $f2_2->mulInt64($f5, 28);
 812          $f2f6_2 = $f2_2->mulInt64($f6, 28);
 813          $f2f7_2 = $f2_2->mulInt64($f7, 28);
 814          $f2f8_38 = $f8_19->mulInt64($f2_2, 30);
 815          $f2f9_38 = $f9_38->mulInt64($f2, 30);
 816  
 817          $f3f3_2 = $f3_2->mulInt64($f3, 28);
 818          $f3f4_2 = $f3_2->mulInt64($f4, 28);
 819          $f3f5_4 = $f3_2->mulInt64($f5_2, 30);
 820          $f3f6_2 = $f3_2->mulInt64($f6, 28);
 821          $f3f7_76 = $f7_38->mulInt64($f3_2, 30);
 822          $f3f8_38 = $f8_19->mulInt64($f3_2, 30);
 823          $f3f9_76 = $f9_38->mulInt64($f3_2, 30);
 824  
 825          $f4f4 = $f4->mulInt64($f4, 28);
 826          $f4f5_2 = $f4_2->mulInt64($f5, 28);
 827          $f4f6_38 = $f6_19->mulInt64($f4_2, 30);
 828          $f4f7_38 = $f7_38->mulInt64($f4, 30);
 829          $f4f8_38 = $f8_19->mulInt64($f4_2, 30);
 830          $f4f9_38 = $f9_38->mulInt64($f4, 30);
 831  
 832          $f5f5_38 = $f5_38->mulInt64($f5, 30);
 833          $f5f6_38 = $f6_19->mulInt64($f5_2, 30);
 834          $f5f7_76 = $f7_38->mulInt64($f5_2, 30);
 835          $f5f8_38 = $f8_19->mulInt64($f5_2, 30);
 836          $f5f9_76 = $f9_38->mulInt64($f5_2, 30);
 837  
 838          $f6f6_19 = $f6_19->mulInt64($f6, 30);
 839          $f6f7_38 = $f7_38->mulInt64($f6, 30);
 840          $f6f8_38 = $f8_19->mulInt64($f6_2, 30);
 841          $f6f9_38 = $f9_38->mulInt64($f6, 30);
 842  
 843          $f7f7_38 = $f7_38->mulInt64($f7, 28);
 844          $f7f8_38 = $f8_19->mulInt64($f7_2, 30);
 845          $f7f9_76 = $f9_38->mulInt64($f7_2, 30);
 846  
 847          $f8f8_19 = $f8_19->mulInt64($f8, 30);
 848          $f8f9_38 = $f9_38->mulInt64($f8, 30);
 849  
 850          $f9f9_38 = $f9_38->mulInt64($f9, 28);
 851  
 852          $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
 853          $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
 854          $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
 855          $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
 856          $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
 857          $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
 858          $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
 859          $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
 860          $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
 861          $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
 862  
 863          /**
 864           * @var ParagonIE_Sodium_Core32_Int64 $h0
 865           * @var ParagonIE_Sodium_Core32_Int64 $h1
 866           * @var ParagonIE_Sodium_Core32_Int64 $h2
 867           * @var ParagonIE_Sodium_Core32_Int64 $h3
 868           * @var ParagonIE_Sodium_Core32_Int64 $h4
 869           * @var ParagonIE_Sodium_Core32_Int64 $h5
 870           * @var ParagonIE_Sodium_Core32_Int64 $h6
 871           * @var ParagonIE_Sodium_Core32_Int64 $h7
 872           * @var ParagonIE_Sodium_Core32_Int64 $h8
 873           * @var ParagonIE_Sodium_Core32_Int64 $h9
 874           */
 875  
 876          $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
 877          $h1 = $h1->addInt64($carry0);
 878          $h0 = $h0->subInt64($carry0->shiftLeft(26));
 879  
 880          $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
 881          $h5 = $h5->addInt64($carry4);
 882          $h4 = $h4->subInt64($carry4->shiftLeft(26));
 883  
 884          $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
 885          $h2 = $h2->addInt64($carry1);
 886          $h1 = $h1->subInt64($carry1->shiftLeft(25));
 887  
 888          $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
 889          $h6 = $h6->addInt64($carry5);
 890          $h5 = $h5->subInt64($carry5->shiftLeft(25));
 891  
 892          $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
 893          $h3 = $h3->addInt64($carry2);
 894          $h2 = $h2->subInt64($carry2->shiftLeft(26));
 895  
 896          $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
 897          $h7 = $h7->addInt64($carry6);
 898          $h6 = $h6->subInt64($carry6->shiftLeft(26));
 899  
 900          $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
 901          $h4 = $h4->addInt64($carry3);
 902          $h3 = $h3->subInt64($carry3->shiftLeft(25));
 903  
 904          $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
 905          $h8 = $h8->addInt64($carry7);
 906          $h7 = $h7->subInt64($carry7->shiftLeft(25));
 907  
 908          $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
 909          $h5 = $h5->addInt64($carry4);
 910          $h4 = $h4->subInt64($carry4->shiftLeft(26));
 911  
 912          $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
 913          $h9 = $h9->addInt64($carry8);
 914          $h8 = $h8->subInt64($carry8->shiftLeft(26));
 915  
 916          $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
 917          $h0 = $h0->addInt64($carry9->mulInt(19, 5));
 918          $h9 = $h9->subInt64($carry9->shiftLeft(25));
 919  
 920          $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
 921          $h1 = $h1->addInt64($carry0);
 922          $h0 = $h0->subInt64($carry0->shiftLeft(26));
 923  
 924          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
 925              array(
 926                  $h0->toInt32(),
 927                  $h1->toInt32(),
 928                  $h2->toInt32(),
 929                  $h3->toInt32(),
 930                  $h4->toInt32(),
 931                  $h5->toInt32(),
 932                  $h6->toInt32(),
 933                  $h7->toInt32(),
 934                  $h8->toInt32(),
 935                  $h9->toInt32()
 936              )
 937          );
 938      }
 939  
 940      /**
 941       * Square and double a field element
 942       *
 943       * h = 2 * f * f
 944       *
 945       * @internal You should not use this directly from another application
 946       *
 947       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
 948       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
 949       * @throws SodiumException
 950       * @throws TypeError
 951       * @psalm-suppress MixedMethodCall
 952       */
 953      public static function fe_sq2(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
 954      {
 955          $f0 = $f[0]->toInt64();
 956          $f1 = $f[1]->toInt64();
 957          $f2 = $f[2]->toInt64();
 958          $f3 = $f[3]->toInt64();
 959          $f4 = $f[4]->toInt64();
 960          $f5 = $f[5]->toInt64();
 961          $f6 = $f[6]->toInt64();
 962          $f7 = $f[7]->toInt64();
 963          $f8 = $f[8]->toInt64();
 964          $f9 = $f[9]->toInt64();
 965  
 966          $f0_2 = $f0->shiftLeft(1);
 967          $f1_2 = $f1->shiftLeft(1);
 968          $f2_2 = $f2->shiftLeft(1);
 969          $f3_2 = $f3->shiftLeft(1);
 970          $f4_2 = $f4->shiftLeft(1);
 971          $f5_2 = $f5->shiftLeft(1);
 972          $f6_2 = $f6->shiftLeft(1);
 973          $f7_2 = $f7->shiftLeft(1);
 974          $f5_38 = $f5->mulInt(38, 6); /* 1.959375*2^30 */
 975          $f6_19 = $f6->mulInt(19, 5); /* 1.959375*2^30 */
 976          $f7_38 = $f7->mulInt(38, 6); /* 1.959375*2^30 */
 977          $f8_19 = $f8->mulInt(19, 5); /* 1.959375*2^30 */
 978          $f9_38 = $f9->mulInt(38, 6); /* 1.959375*2^30 */
 979          $f0f0 = $f0->mulInt64($f0, 28);
 980          $f0f1_2 = $f0_2->mulInt64($f1, 28);
 981          $f0f2_2 = $f0_2->mulInt64($f2, 28);
 982          $f0f3_2 = $f0_2->mulInt64($f3, 28);
 983          $f0f4_2 = $f0_2->mulInt64($f4, 28);
 984          $f0f5_2 = $f0_2->mulInt64($f5, 28);
 985          $f0f6_2 = $f0_2->mulInt64($f6, 28);
 986          $f0f7_2 = $f0_2->mulInt64($f7, 28);
 987          $f0f8_2 = $f0_2->mulInt64($f8, 28);
 988          $f0f9_2 = $f0_2->mulInt64($f9, 28);
 989          $f1f1_2 = $f1_2->mulInt64($f1, 28);
 990          $f1f2_2 = $f1_2->mulInt64($f2, 28);
 991          $f1f3_4 = $f1_2->mulInt64($f3_2, 29);
 992          $f1f4_2 = $f1_2->mulInt64($f4, 28);
 993          $f1f5_4 = $f1_2->mulInt64($f5_2, 29);
 994          $f1f6_2 = $f1_2->mulInt64($f6, 28);
 995          $f1f7_4 = $f1_2->mulInt64($f7_2, 29);
 996          $f1f8_2 = $f1_2->mulInt64($f8, 28);
 997          $f1f9_76 = $f9_38->mulInt64($f1_2, 29);
 998          $f2f2 = $f2->mulInt64($f2, 28);
 999          $f2f3_2 = $f2_2->mulInt64($f3, 28);
1000          $f2f4_2 = $f2_2->mulInt64($f4, 28);
1001          $f2f5_2 = $f2_2->mulInt64($f5, 28);
1002          $f2f6_2 = $f2_2->mulInt64($f6, 28);
1003          $f2f7_2 = $f2_2->mulInt64($f7, 28);
1004          $f2f8_38 = $f8_19->mulInt64($f2_2, 29);
1005          $f2f9_38 = $f9_38->mulInt64($f2, 29);
1006          $f3f3_2 = $f3_2->mulInt64($f3, 28);
1007          $f3f4_2 = $f3_2->mulInt64($f4, 28);
1008          $f3f5_4 = $f3_2->mulInt64($f5_2, 28);
1009          $f3f6_2 = $f3_2->mulInt64($f6, 28);
1010          $f3f7_76 = $f7_38->mulInt64($f3_2, 29);
1011          $f3f8_38 = $f8_19->mulInt64($f3_2, 29);
1012          $f3f9_76 = $f9_38->mulInt64($f3_2, 29);
1013          $f4f4 = $f4->mulInt64($f4, 28);
1014          $f4f5_2 = $f4_2->mulInt64($f5, 28);
1015          $f4f6_38 = $f6_19->mulInt64($f4_2, 29);
1016          $f4f7_38 = $f7_38->mulInt64($f4, 29);
1017          $f4f8_38 = $f8_19->mulInt64($f4_2, 29);
1018          $f4f9_38 = $f9_38->mulInt64($f4, 29);
1019          $f5f5_38 = $f5_38->mulInt64($f5, 29);
1020          $f5f6_38 = $f6_19->mulInt64($f5_2, 29);
1021          $f5f7_76 = $f7_38->mulInt64($f5_2, 29);
1022          $f5f8_38 = $f8_19->mulInt64($f5_2, 29);
1023          $f5f9_76 = $f9_38->mulInt64($f5_2, 29);
1024          $f6f6_19 = $f6_19->mulInt64($f6, 29);
1025          $f6f7_38 = $f7_38->mulInt64($f6, 29);
1026          $f6f8_38 = $f8_19->mulInt64($f6_2, 29);
1027          $f6f9_38 = $f9_38->mulInt64($f6, 29);
1028          $f7f7_38 = $f7_38->mulInt64($f7, 29);
1029          $f7f8_38 = $f8_19->mulInt64($f7_2, 29);
1030          $f7f9_76 = $f9_38->mulInt64($f7_2, 29);
1031          $f8f8_19 = $f8_19->mulInt64($f8, 29);
1032          $f8f9_38 = $f9_38->mulInt64($f8, 29);
1033          $f9f9_38 = $f9_38->mulInt64($f9, 29);
1034  
1035          $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
1036          $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
1037          $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
1038          $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
1039          $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
1040          $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
1041          $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
1042          $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
1043          $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
1044          $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
1045  
1046          /**
1047           * @var ParagonIE_Sodium_Core32_Int64 $h0
1048           * @var ParagonIE_Sodium_Core32_Int64 $h1
1049           * @var ParagonIE_Sodium_Core32_Int64 $h2
1050           * @var ParagonIE_Sodium_Core32_Int64 $h3
1051           * @var ParagonIE_Sodium_Core32_Int64 $h4
1052           * @var ParagonIE_Sodium_Core32_Int64 $h5
1053           * @var ParagonIE_Sodium_Core32_Int64 $h6
1054           * @var ParagonIE_Sodium_Core32_Int64 $h7
1055           * @var ParagonIE_Sodium_Core32_Int64 $h8
1056           * @var ParagonIE_Sodium_Core32_Int64 $h9
1057           */
1058          $h0 = $h0->shiftLeft(1);
1059          $h1 = $h1->shiftLeft(1);
1060          $h2 = $h2->shiftLeft(1);
1061          $h3 = $h3->shiftLeft(1);
1062          $h4 = $h4->shiftLeft(1);
1063          $h5 = $h5->shiftLeft(1);
1064          $h6 = $h6->shiftLeft(1);
1065          $h7 = $h7->shiftLeft(1);
1066          $h8 = $h8->shiftLeft(1);
1067          $h9 = $h9->shiftLeft(1);
1068  
1069          $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
1070          $h1 = $h1->addInt64($carry0);
1071          $h0 = $h0->subInt64($carry0->shiftLeft(26));
1072          $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
1073          $h5 = $h5->addInt64($carry4);
1074          $h4 = $h4->subInt64($carry4->shiftLeft(26));
1075  
1076          $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
1077          $h2 = $h2->addInt64($carry1);
1078          $h1 = $h1->subInt64($carry1->shiftLeft(25));
1079          $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
1080          $h6 = $h6->addInt64($carry5);
1081          $h5 = $h5->subInt64($carry5->shiftLeft(25));
1082  
1083          $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
1084          $h3 = $h3->addInt64($carry2);
1085          $h2 = $h2->subInt64($carry2->shiftLeft(26));
1086          $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
1087          $h7 = $h7->addInt64($carry6);
1088          $h6 = $h6->subInt64($carry6->shiftLeft(26));
1089  
1090          $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
1091          $h4 = $h4->addInt64($carry3);
1092          $h3 = $h3->subInt64($carry3->shiftLeft(25));
1093          $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
1094          $h8 = $h8->addInt64($carry7);
1095          $h7 = $h7->subInt64($carry7->shiftLeft(25));
1096  
1097          $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
1098          $h5 = $h5->addInt64($carry4);
1099          $h4 = $h4->subInt64($carry4->shiftLeft(26));
1100          $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
1101          $h9 = $h9->addInt64($carry8);
1102          $h8 = $h8->subInt64($carry8->shiftLeft(26));
1103  
1104          $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
1105          $h0 = $h0->addInt64($carry9->mulInt(19, 5));
1106          $h9 = $h9->subInt64($carry9->shiftLeft(25));
1107  
1108          $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
1109          $h1 = $h1->addInt64($carry0);
1110          $h0 = $h0->subInt64($carry0->shiftLeft(26));
1111  
1112          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1113              array(
1114                  $h0->toInt32(),
1115                  $h1->toInt32(),
1116                  $h2->toInt32(),
1117                  $h3->toInt32(),
1118                  $h4->toInt32(),
1119                  $h5->toInt32(),
1120                  $h6->toInt32(),
1121                  $h7->toInt32(),
1122                  $h8->toInt32(),
1123                  $h9->toInt32()
1124              )
1125          );
1126      }
1127  
1128      /**
1129       * @internal You should not use this directly from another application
1130       *
1131       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $Z
1132       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
1133       * @throws SodiumException
1134       * @throws TypeError
1135       */
1136      public static function fe_invert(ParagonIE_Sodium_Core32_Curve25519_Fe $Z)
1137      {
1138          $z = clone $Z;
1139          $t0 = self::fe_sq($z);
1140          $t1 = self::fe_sq($t0);
1141          $t1 = self::fe_sq($t1);
1142          $t1 = self::fe_mul($z, $t1);
1143          $t0 = self::fe_mul($t0, $t1);
1144          $t2 = self::fe_sq($t0);
1145          $t1 = self::fe_mul($t1, $t2);
1146          $t2 = self::fe_sq($t1);
1147          for ($i = 1; $i < 5; ++$i) {
1148              $t2 = self::fe_sq($t2);
1149          }
1150          $t1 = self::fe_mul($t2, $t1);
1151          $t2 = self::fe_sq($t1);
1152          for ($i = 1; $i < 10; ++$i) {
1153              $t2 = self::fe_sq($t2);
1154          }
1155          $t2 = self::fe_mul($t2, $t1);
1156          $t3 = self::fe_sq($t2);
1157          for ($i = 1; $i < 20; ++$i) {
1158              $t3 = self::fe_sq($t3);
1159          }
1160          $t2 = self::fe_mul($t3, $t2);
1161          $t2 = self::fe_sq($t2);
1162          for ($i = 1; $i < 10; ++$i) {
1163              $t2 = self::fe_sq($t2);
1164          }
1165          $t1 = self::fe_mul($t2, $t1);
1166          $t2 = self::fe_sq($t1);
1167          for ($i = 1; $i < 50; ++$i) {
1168              $t2 = self::fe_sq($t2);
1169          }
1170          $t2 = self::fe_mul($t2, $t1);
1171          $t3 = self::fe_sq($t2);
1172          for ($i = 1; $i < 100; ++$i) {
1173              $t3 = self::fe_sq($t3);
1174          }
1175          $t2 = self::fe_mul($t3, $t2);
1176          $t2 = self::fe_sq($t2);
1177          for ($i = 1; $i < 50; ++$i) {
1178              $t2 = self::fe_sq($t2);
1179          }
1180          $t1 = self::fe_mul($t2, $t1);
1181          $t1 = self::fe_sq($t1);
1182          for ($i = 1; $i < 5; ++$i) {
1183              $t1 = self::fe_sq($t1);
1184          }
1185          return self::fe_mul($t1, $t0);
1186      }
1187  
1188      /**
1189       * @internal You should not use this directly from another application
1190       *
1191       * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
1192       *
1193       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $z
1194       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
1195       * @throws SodiumException
1196       * @throws TypeError
1197       */
1198      public static function fe_pow22523(ParagonIE_Sodium_Core32_Curve25519_Fe $z)
1199      {
1200          # fe_sq(t0, z);
1201          # fe_sq(t1, t0);
1202          # fe_sq(t1, t1);
1203          # fe_mul(t1, z, t1);
1204          # fe_mul(t0, t0, t1);
1205          # fe_sq(t0, t0);
1206          # fe_mul(t0, t1, t0);
1207          # fe_sq(t1, t0);
1208          $t0 = self::fe_sq($z);
1209          $t1 = self::fe_sq($t0);
1210          $t1 = self::fe_sq($t1);
1211          $t1 = self::fe_mul($z, $t1);
1212          $t0 = self::fe_mul($t0, $t1);
1213          $t0 = self::fe_sq($t0);
1214          $t0 = self::fe_mul($t1, $t0);
1215          $t1 = self::fe_sq($t0);
1216  
1217          # for (i = 1; i < 5; ++i) {
1218          #     fe_sq(t1, t1);
1219          # }
1220          for ($i = 1; $i < 5; ++$i) {
1221              $t1 = self::fe_sq($t1);
1222          }
1223  
1224          # fe_mul(t0, t1, t0);
1225          # fe_sq(t1, t0);
1226          $t0 = self::fe_mul($t1, $t0);
1227          $t1 = self::fe_sq($t0);
1228  
1229          # for (i = 1; i < 10; ++i) {
1230          #     fe_sq(t1, t1);
1231          # }
1232          for ($i = 1; $i < 10; ++$i) {
1233              $t1 = self::fe_sq($t1);
1234          }
1235  
1236          # fe_mul(t1, t1, t0);
1237          # fe_sq(t2, t1);
1238          $t1 = self::fe_mul($t1, $t0);
1239          $t2 = self::fe_sq($t1);
1240  
1241          # for (i = 1; i < 20; ++i) {
1242          #     fe_sq(t2, t2);
1243          # }
1244          for ($i = 1; $i < 20; ++$i) {
1245              $t2 = self::fe_sq($t2);
1246          }
1247  
1248          # fe_mul(t1, t2, t1);
1249          # fe_sq(t1, t1);
1250          $t1 = self::fe_mul($t2, $t1);
1251          $t1 = self::fe_sq($t1);
1252  
1253          # for (i = 1; i < 10; ++i) {
1254          #     fe_sq(t1, t1);
1255          # }
1256          for ($i = 1; $i < 10; ++$i) {
1257              $t1 = self::fe_sq($t1);
1258          }
1259  
1260          # fe_mul(t0, t1, t0);
1261          # fe_sq(t1, t0);
1262          $t0 = self::fe_mul($t1, $t0);
1263          $t1 = self::fe_sq($t0);
1264  
1265          # for (i = 1; i < 50; ++i) {
1266          #     fe_sq(t1, t1);
1267          # }
1268          for ($i = 1; $i < 50; ++$i) {
1269              $t1 = self::fe_sq($t1);
1270          }
1271  
1272          # fe_mul(t1, t1, t0);
1273          # fe_sq(t2, t1);
1274          $t1 = self::fe_mul($t1, $t0);
1275          $t2 = self::fe_sq($t1);
1276  
1277          # for (i = 1; i < 100; ++i) {
1278          #     fe_sq(t2, t2);
1279          # }
1280          for ($i = 1; $i < 100; ++$i) {
1281              $t2 = self::fe_sq($t2);
1282          }
1283  
1284          # fe_mul(t1, t2, t1);
1285          # fe_sq(t1, t1);
1286          $t1 = self::fe_mul($t2, $t1);
1287          $t1 = self::fe_sq($t1);
1288  
1289          # for (i = 1; i < 50; ++i) {
1290          #     fe_sq(t1, t1);
1291          # }
1292          for ($i = 1; $i < 50; ++$i) {
1293              $t1 = self::fe_sq($t1);
1294          }
1295  
1296          # fe_mul(t0, t1, t0);
1297          # fe_sq(t0, t0);
1298          # fe_sq(t0, t0);
1299          # fe_mul(out, t0, z);
1300          $t0 = self::fe_mul($t1, $t0);
1301          $t0 = self::fe_sq($t0);
1302          $t0 = self::fe_sq($t0);
1303          return self::fe_mul($t0, $z);
1304      }
1305  
1306      /**
1307       * Subtract two field elements.
1308       *
1309       * h = f - g
1310       *
1311       * Preconditions:
1312       * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
1313       * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
1314       *
1315       * Postconditions:
1316       * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
1317       *
1318       * @internal You should not use this directly from another application
1319       *
1320       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
1321       * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
1322       * @return ParagonIE_Sodium_Core32_Curve25519_Fe
1323       * @throws SodiumException
1324       * @throws TypeError
1325       * @psalm-suppress MixedMethodCall
1326       * @psalm-suppress MixedTypeCoercion
1327       */
1328      public static function fe_sub(ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g)
1329      {
1330          return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1331              array(
1332                  $f[0]->subInt32($g[0]),
1333                  $f[1]->subInt32($g[1]),
1334                  $f[2]->subInt32($g[2]),
1335                  $f[3]->subInt32($g[3]),
1336                  $f[4]->subInt32($g[4]),
1337                  $f[5]->subInt32($g[5]),
1338                  $f[6]->subInt32($g[6]),
1339                  $f[7]->subInt32($g[7]),
1340                  $f[8]->subInt32($g[8]),
1341                  $f[9]->subInt32($g[9])
1342              )
1343          );
1344      }
1345  
1346      /**
1347       * Add two group elements.
1348       *
1349       * r = p + q
1350       *
1351       * @internal You should not use this directly from another application
1352       *
1353       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1354       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1355       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1356       * @throws SodiumException
1357       * @throws TypeError
1358       */
1359      public static function ge_add(
1360          ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1361          ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1362      ) {
1363          $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
1364          $r->X = self::fe_add($p->Y, $p->X);
1365          $r->Y = self::fe_sub($p->Y, $p->X);
1366          $r->Z = self::fe_mul($r->X, $q->YplusX);
1367          $r->Y = self::fe_mul($r->Y, $q->YminusX);
1368          $r->T = self::fe_mul($q->T2d, $p->T);
1369          $r->X = self::fe_mul($p->Z, $q->Z);
1370          $t0   = self::fe_add($r->X, $r->X);
1371          $r->X = self::fe_sub($r->Z, $r->Y);
1372          $r->Y = self::fe_add($r->Z, $r->Y);
1373          $r->Z = self::fe_add($t0, $r->T);
1374          $r->T = self::fe_sub($t0, $r->T);
1375          return $r;
1376      }
1377  
1378      /**
1379       * @internal You should not use this directly from another application
1380       *
1381       * @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
1382       * @param string $a
1383       * @return array<int, mixed>
1384       * @throws SodiumException
1385       * @throws TypeError
1386       * @psalm-suppress MixedArrayOffset
1387       */
1388      public static function slide($a)
1389      {
1390          if (self::strlen($a) < 256) {
1391              if (self::strlen($a) < 16) {
1392                  $a = str_pad($a, 256, '0', STR_PAD_RIGHT);
1393              }
1394          }
1395          /** @var array<int, int> $r */
1396          $r = array();
1397          for ($i = 0; $i < 256; ++$i) {
1398              $r[$i] = (int) (1 &
1399                  (
1400                      self::chrToInt($a[$i >> 3])
1401                          >>
1402                      ($i & 7)
1403                  )
1404              );
1405          }
1406  
1407          for ($i = 0;$i < 256;++$i) {
1408              if ($r[$i]) {
1409                  for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
1410                      if ($r[$i + $b]) {
1411                          if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
1412                              $r[$i] += $r[$i + $b] << $b;
1413                              $r[$i + $b] = 0;
1414                          } elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) {
1415                              $r[$i] -= $r[$i + $b] << $b;
1416                              for ($k = $i + $b; $k < 256; ++$k) {
1417                                  if (!$r[$k]) {
1418                                      $r[$k] = 1;
1419                                      break;
1420                                  }
1421                                  $r[$k] = 0;
1422                              }
1423                          } else {
1424                              break;
1425                          }
1426                      }
1427                  }
1428              }
1429          }
1430          return $r;
1431      }
1432  
1433      /**
1434       * @internal You should not use this directly from another application
1435       *
1436       * @param string $s
1437       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
1438       * @throws SodiumException
1439       * @throws TypeError
1440       */
1441      public static function ge_frombytes_negate_vartime($s)
1442      {
1443          static $d = null;
1444          if (!$d) {
1445              $d = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1446                  array(
1447                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[0]),
1448                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[1]),
1449                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[2]),
1450                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[3]),
1451                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[4]),
1452                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[5]),
1453                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[6]),
1454                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[7]),
1455                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[8]),
1456                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[9])
1457                  )
1458              );
1459          }
1460          /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
1461  
1462          # fe_frombytes(h->Y,s);
1463          # fe_1(h->Z);
1464          $h = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
1465              self::fe_0(),
1466              self::fe_frombytes($s),
1467              self::fe_1()
1468          );
1469  
1470          # fe_sq(u,h->Y);
1471          # fe_mul(v,u,d);
1472          # fe_sub(u,u,h->Z);       /* u = y^2-1 */
1473          # fe_add(v,v,h->Z);       /* v = dy^2+1 */
1474          $u = self::fe_sq($h->Y);
1475          /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
1476          $v = self::fe_mul($u, $d);
1477          $u = self::fe_sub($u, $h->Z); /* u =  y^2 - 1 */
1478          $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */
1479  
1480          # fe_sq(v3,v);
1481          # fe_mul(v3,v3,v);        /* v3 = v^3 */
1482          # fe_sq(h->X,v3);
1483          # fe_mul(h->X,h->X,v);
1484          # fe_mul(h->X,h->X,u);    /* x = uv^7 */
1485          $v3 = self::fe_sq($v);
1486          $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
1487          $h->X = self::fe_sq($v3);
1488          $h->X = self::fe_mul($h->X, $v);
1489          $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */
1490  
1491          # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
1492          # fe_mul(h->X,h->X,v3);
1493          # fe_mul(h->X,h->X,u);    /* x = uv^3(uv^7)^((q-5)/8) */
1494          $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
1495          $h->X = self::fe_mul($h->X, $v3);
1496          $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */
1497  
1498          # fe_sq(vxx,h->X);
1499          # fe_mul(vxx,vxx,v);
1500          # fe_sub(check,vxx,u);    /* vx^2-u */
1501          $vxx = self::fe_sq($h->X);
1502          $vxx = self::fe_mul($vxx, $v);
1503          $check = self::fe_sub($vxx, $u); /* vx^2 - u */
1504  
1505          # if (fe_isnonzero(check)) {
1506          #     fe_add(check,vxx,u);  /* vx^2+u */
1507          #     if (fe_isnonzero(check)) {
1508          #         return -1;
1509          #     }
1510          #     fe_mul(h->X,h->X,sqrtm1);
1511          # }
1512          if (self::fe_isnonzero($check)) {
1513              $check = self::fe_add($vxx, $u); /* vx^2 + u */
1514              if (self::fe_isnonzero($check)) {
1515                  throw new RangeException('Internal check failed.');
1516              }
1517              $h->X = self::fe_mul(
1518                  $h->X,
1519                  ParagonIE_Sodium_Core32_Curve25519_Fe::fromIntArray(self::$sqrtm1)
1520              );
1521          }
1522  
1523          # if (fe_isnegative(h->X) == (s[31] >> 7)) {
1524          #     fe_neg(h->X,h->X);
1525          # }
1526          $i = self::chrToInt($s[31]);
1527          if (self::fe_isnegative($h->X) === ($i >> 7)) {
1528              $h->X = self::fe_neg($h->X);
1529          }
1530  
1531          # fe_mul(h->T,h->X,h->Y);
1532          $h->T = self::fe_mul($h->X, $h->Y);
1533          return $h;
1534      }
1535  
1536      /**
1537       * @internal You should not use this directly from another application
1538       *
1539       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
1540       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1541       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1542       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1543       * @throws SodiumException
1544       * @throws TypeError
1545       */
1546      public static function ge_madd(
1547          ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
1548          ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1549          ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1550      ) {
1551          $r = clone $R;
1552          $r->X = self::fe_add($p->Y, $p->X);
1553          $r->Y = self::fe_sub($p->Y, $p->X);
1554          $r->Z = self::fe_mul($r->X, $q->yplusx);
1555          $r->Y = self::fe_mul($r->Y, $q->yminusx);
1556          $r->T = self::fe_mul($q->xy2d, $p->T);
1557          $t0 = self::fe_add(clone $p->Z, clone $p->Z);
1558          $r->X = self::fe_sub($r->Z, $r->Y);
1559          $r->Y = self::fe_add($r->Z, $r->Y);
1560          $r->Z = self::fe_add($t0, $r->T);
1561          $r->T = self::fe_sub($t0, $r->T);
1562  
1563          return $r;
1564      }
1565  
1566      /**
1567       * @internal You should not use this directly from another application
1568       *
1569       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
1570       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1571       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1572       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1573       * @throws SodiumException
1574       * @throws TypeError
1575       */
1576      public static function ge_msub(
1577          ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
1578          ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1579          ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
1580      ) {
1581          $r = clone $R;
1582  
1583          $r->X = self::fe_add($p->Y, $p->X);
1584          $r->Y = self::fe_sub($p->Y, $p->X);
1585          $r->Z = self::fe_mul($r->X, $q->yminusx);
1586          $r->Y = self::fe_mul($r->Y, $q->yplusx);
1587          $r->T = self::fe_mul($q->xy2d, $p->T);
1588          $t0 = self::fe_add($p->Z, $p->Z);
1589          $r->X = self::fe_sub($r->Z, $r->Y);
1590          $r->Y = self::fe_add($r->Z, $r->Y);
1591          $r->Z = self::fe_sub($t0, $r->T);
1592          $r->T = self::fe_add($t0, $r->T);
1593  
1594          return $r;
1595      }
1596  
1597      /**
1598       * @internal You should not use this directly from another application
1599       *
1600       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
1601       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
1602       * @throws SodiumException
1603       * @throws TypeError
1604       */
1605      public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
1606      {
1607          $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P2();
1608          $r->X = self::fe_mul($p->X, $p->T);
1609          $r->Y = self::fe_mul($p->Y, $p->Z);
1610          $r->Z = self::fe_mul($p->Z, $p->T);
1611          return $r;
1612      }
1613  
1614      /**
1615       * @internal You should not use this directly from another application
1616       *
1617       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
1618       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
1619       * @throws SodiumException
1620       * @throws TypeError
1621       */
1622      public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
1623      {
1624          $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3();
1625          $r->X = self::fe_mul($p->X, $p->T);
1626          $r->Y = self::fe_mul($p->Y, $p->Z);
1627          $r->Z = self::fe_mul($p->Z, $p->T);
1628          $r->T = self::fe_mul($p->X, $p->Y);
1629          return $r;
1630      }
1631  
1632      /**
1633       * @internal You should not use this directly from another application
1634       *
1635       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
1636       * @throws SodiumException
1637       * @throws TypeError
1638       */
1639      public static function ge_p2_0()
1640      {
1641          return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
1642              self::fe_0(),
1643              self::fe_1(),
1644              self::fe_1()
1645          );
1646      }
1647  
1648      /**
1649       * @internal You should not use this directly from another application
1650       *
1651       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p
1652       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1653       * @throws SodiumException
1654       * @throws TypeError
1655       */
1656      public static function ge_p2_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p)
1657      {
1658          $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
1659  
1660          $r->X = self::fe_sq($p->X);
1661          $r->Z = self::fe_sq($p->Y);
1662          $r->T = self::fe_sq2($p->Z);
1663          $r->Y = self::fe_add($p->X, $p->Y);
1664          $t0   = self::fe_sq($r->Y);
1665          $r->Y = self::fe_add($r->Z, $r->X);
1666          $r->Z = self::fe_sub($r->Z, $r->X);
1667          $r->X = self::fe_sub($t0, $r->Y);
1668          $r->T = self::fe_sub($r->T, $r->Z);
1669  
1670          return $r;
1671      }
1672  
1673      /**
1674       * @internal You should not use this directly from another application
1675       *
1676       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
1677       * @throws SodiumException
1678       * @throws TypeError
1679       */
1680      public static function ge_p3_0()
1681      {
1682          return new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
1683              self::fe_0(),
1684              self::fe_1(),
1685              self::fe_1(),
1686              self::fe_0()
1687          );
1688      }
1689  
1690      /**
1691       * @internal You should not use this directly from another application
1692       *
1693       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1694       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
1695       * @throws SodiumException
1696       * @throws TypeError
1697       */
1698      public static function ge_p3_to_cached(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
1699      {
1700          static $d2 = null;
1701          if ($d2 === null) {
1702              $d2 = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1703                  array(
1704                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[0]),
1705                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[1]),
1706                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[2]),
1707                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[3]),
1708                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[4]),
1709                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[5]),
1710                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[6]),
1711                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[7]),
1712                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[8]),
1713                      ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[9])
1714                  )
1715              );
1716          }
1717          /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d2 */
1718          $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached();
1719          $r->YplusX = self::fe_add($p->Y, $p->X);
1720          $r->YminusX = self::fe_sub($p->Y, $p->X);
1721          $r->Z = self::fe_copy($p->Z);
1722          $r->T2d = self::fe_mul($p->T, $d2);
1723          return $r;
1724      }
1725  
1726      /**
1727       * @internal You should not use this directly from another application
1728       *
1729       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1730       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
1731       */
1732      public static function ge_p3_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
1733      {
1734          return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
1735              $p->X,
1736              $p->Y,
1737              $p->Z
1738          );
1739      }
1740  
1741      /**
1742       * @internal You should not use this directly from another application
1743       *
1744       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h
1745       * @return string
1746       * @throws SodiumException
1747       * @throws TypeError
1748       */
1749      public static function ge_p3_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h)
1750      {
1751          $recip = self::fe_invert($h->Z);
1752          $x = self::fe_mul($h->X, $recip);
1753          $y = self::fe_mul($h->Y, $recip);
1754          $s = self::fe_tobytes($y);
1755          $s[31] = self::intToChr(
1756              self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
1757          );
1758          return $s;
1759      }
1760  
1761      /**
1762       * @internal You should not use this directly from another application
1763       *
1764       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1765       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1766       * @throws SodiumException
1767       * @throws TypeError
1768       */
1769      public static function ge_p3_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
1770      {
1771          $q = self::ge_p3_to_p2($p);
1772          return self::ge_p2_dbl($q);
1773      }
1774  
1775      /**
1776       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
1777       * @throws SodiumException
1778       * @throws TypeError
1779       */
1780      public static function ge_precomp_0()
1781      {
1782          return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1783              self::fe_1(),
1784              self::fe_1(),
1785              self::fe_0()
1786          );
1787      }
1788  
1789      /**
1790       * @internal You should not use this directly from another application
1791       *
1792       * @param int $b
1793       * @param int $c
1794       * @return int
1795       * @psalm-suppress MixedReturnStatement
1796       */
1797      public static function equal($b, $c)
1798      {
1799          $b0 = $b & 0xffff;
1800          $b1 = ($b >> 16) & 0xffff;
1801          $c0 = $c & 0xffff;
1802          $c1 = ($c >> 16) & 0xffff;
1803  
1804          $d0 = (($b0 ^ $c0) - 1) >> 31;
1805          $d1 = (($b1 ^ $c1) - 1) >> 31;
1806          return ($d0 & $d1) & 1;
1807      }
1808  
1809      /**
1810       * @internal You should not use this directly from another application
1811       *
1812       * @param string|int $char
1813       * @return int (1 = yes, 0 = no)
1814       * @throws SodiumException
1815       * @throws TypeError
1816       */
1817      public static function negative($char)
1818      {
1819          if (is_int($char)) {
1820              return $char < 0 ? 1 : 0;
1821          }
1822          /** @var string $char */
1823          $x = self::chrToInt(self::substr($char, 0, 1));
1824          return (int) ($x >> 31);
1825      }
1826  
1827      /**
1828       * Conditional move
1829       *
1830       * @internal You should not use this directly from another application
1831       *
1832       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t
1833       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u
1834       * @param int $b
1835       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
1836       * @throws SodiumException
1837       * @throws TypeError
1838       */
1839      public static function cmov(
1840          ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t,
1841          ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u,
1842          $b
1843      ) {
1844          if (!is_int($b)) {
1845              throw new InvalidArgumentException('Expected an integer.');
1846          }
1847          return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1848              self::fe_cmov($t->yplusx, $u->yplusx, $b),
1849              self::fe_cmov($t->yminusx, $u->yminusx, $b),
1850              self::fe_cmov($t->xy2d, $u->xy2d, $b)
1851          );
1852      }
1853  
1854      /**
1855       * @internal You should not use this directly from another application
1856       *
1857       * @param int $pos
1858       * @param int $b
1859       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
1860       * @throws SodiumException
1861       * @throws TypeError
1862       * @psalm-suppress MixedArrayAccess
1863       * @psalm-suppress MixedArrayOffset
1864       * @psalm-suppress MixedArgument
1865       */
1866      public static function ge_select($pos = 0, $b = 0)
1867      {
1868          static $base = null;
1869          if ($base === null) {
1870              $base = array();
1871              foreach (self::$base as $i => $bas) {
1872                  for ($j = 0; $j < 8; ++$j) {
1873                      $base[$i][$j] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1874                          ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1875                              array(
1876                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][0]),
1877                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][1]),
1878                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][2]),
1879                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][3]),
1880                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][4]),
1881                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][5]),
1882                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][6]),
1883                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][7]),
1884                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][8]),
1885                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][9])
1886                              )
1887                          ),
1888                          ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1889                              array(
1890                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][0]),
1891                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][1]),
1892                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][2]),
1893                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][3]),
1894                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][4]),
1895                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][5]),
1896                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][6]),
1897                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][7]),
1898                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][8]),
1899                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][9])
1900                              )
1901                          ),
1902                          ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
1903                              array(
1904                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][0]),
1905                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][1]),
1906                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][2]),
1907                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][3]),
1908                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][4]),
1909                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][5]),
1910                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][6]),
1911                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][7]),
1912                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][8]),
1913                                  ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][9])
1914                              )
1915                          )
1916                      );
1917                  }
1918              }
1919          }
1920          if (!is_int($pos)) {
1921              throw new InvalidArgumentException('Position must be an integer');
1922          }
1923          if ($pos < 0 || $pos > 31) {
1924              throw new RangeException('Position is out of range [0, 31]');
1925          }
1926  
1927          $bnegative = self::negative($b);
1928          $babs = $b - (((-$bnegative) & $b) << 1);
1929  
1930          $t = self::ge_precomp_0();
1931          for ($i = 0; $i < 8; ++$i) {
1932              $t = self::cmov(
1933                  $t,
1934                  $base[$pos][$i],
1935                  -self::equal($babs, $i + 1)
1936              );
1937          }
1938          $minusT = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
1939              self::fe_copy($t->yminusx),
1940              self::fe_copy($t->yplusx),
1941              self::fe_neg($t->xy2d)
1942          );
1943          return self::cmov($t, $minusT, -$bnegative);
1944      }
1945  
1946      /**
1947       * Subtract two group elements.
1948       *
1949       * r = p - q
1950       *
1951       * @internal You should not use this directly from another application
1952       *
1953       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
1954       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1955       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
1956       * @throws SodiumException
1957       * @throws TypeError
1958       */
1959      public static function ge_sub(
1960          ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
1961          ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
1962      ) {
1963          $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
1964  
1965          $r->X = self::fe_add($p->Y, $p->X);
1966          $r->Y = self::fe_sub($p->Y, $p->X);
1967          $r->Z = self::fe_mul($r->X, $q->YminusX);
1968          $r->Y = self::fe_mul($r->Y, $q->YplusX);
1969          $r->T = self::fe_mul($q->T2d, $p->T);
1970          $r->X = self::fe_mul($p->Z, $q->Z);
1971          $t0 = self::fe_add($r->X, $r->X);
1972          $r->X = self::fe_sub($r->Z, $r->Y);
1973          $r->Y = self::fe_add($r->Z, $r->Y);
1974          $r->Z = self::fe_sub($t0, $r->T);
1975          $r->T = self::fe_add($t0, $r->T);
1976  
1977          return $r;
1978      }
1979  
1980      /**
1981       * Convert a group element to a byte string.
1982       *
1983       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h
1984       * @return string
1985       * @throws SodiumException
1986       * @throws TypeError
1987       */
1988      public static function ge_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h)
1989      {
1990          $recip = self::fe_invert($h->Z);
1991          $x = self::fe_mul($h->X, $recip);
1992          $y = self::fe_mul($h->Y, $recip);
1993          $s = self::fe_tobytes($y);
1994          $s[31] = self::intToChr(
1995              self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
1996          );
1997          return $s;
1998      }
1999  
2000      /**
2001       * @internal You should not use this directly from another application
2002       *
2003       * @param string $a
2004       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
2005       * @param string $b
2006       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
2007       * @throws SodiumException
2008       * @throws TypeError
2009       * @psalm-suppress MixedArrayAccess
2010       */
2011      public static function ge_double_scalarmult_vartime(
2012          $a,
2013          ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A,
2014          $b
2015      ) {
2016          /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */
2017          $Ai = array();
2018  
2019          static $Bi = array();
2020          /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */
2021          if (!$Bi) {
2022              for ($i = 0; $i < 8; ++$i) {
2023                  $Bi[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
2024                      ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
2025                          array(
2026                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][0]),
2027                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][1]),
2028                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][2]),
2029                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][3]),
2030                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][4]),
2031                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][5]),
2032                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][6]),
2033                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][7]),
2034                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][8]),
2035                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][9])
2036                          )
2037                      ),
2038                      ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
2039                          array(
2040                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][0]),
2041                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][1]),
2042                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][2]),
2043                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][3]),
2044                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][4]),
2045                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][5]),
2046                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][6]),
2047                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][7]),
2048                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][8]),
2049                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][9])
2050                          )
2051                      ),
2052                      ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
2053                          array(
2054                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][0]),
2055                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][1]),
2056                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][2]),
2057                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][3]),
2058                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][4]),
2059                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][5]),
2060                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][6]),
2061                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][7]),
2062                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][8]),
2063                              ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][9])
2064                          )
2065                      )
2066                  );
2067              }
2068          }
2069  
2070          for ($i = 0; $i < 8; ++$i) {
2071              $Ai[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached(
2072                  self::fe_0(),
2073                  self::fe_0(),
2074                  self::fe_0(),
2075                  self::fe_0()
2076              );
2077          }
2078          /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */
2079  
2080          # slide(aslide,a);
2081          # slide(bslide,b);
2082          /** @var array<int, int> $aslide */
2083          $aslide = self::slide($a);
2084          /** @var array<int, int> $bslide */
2085          $bslide = self::slide($b);
2086  
2087          # ge_p3_to_cached(&Ai[0],A);
2088          # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
2089          $Ai[0] = self::ge_p3_to_cached($A);
2090          $t = self::ge_p3_dbl($A);
2091          $A2 = self::ge_p1p1_to_p3($t);
2092  
2093          # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
2094          # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
2095          # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
2096          # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
2097          # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
2098          # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
2099          # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
2100          for ($i = 0; $i < 7; ++$i) {
2101              $t = self::ge_add($A2, $Ai[$i]);
2102              $u = self::ge_p1p1_to_p3($t);
2103              $Ai[$i + 1] = self::ge_p3_to_cached($u);
2104          }
2105  
2106          # ge_p2_0(r);
2107          $r = self::ge_p2_0();
2108  
2109          # for (i = 255;i >= 0;--i) {
2110          #     if (aslide[i] || bslide[i]) break;
2111          # }
2112          $i = 255;
2113          for (; $i >= 0; --$i) {
2114              if ($aslide[$i] || $bslide[$i]) {
2115                  break;
2116              }
2117          }
2118  
2119          # for (;i >= 0;--i) {
2120          for (; $i >= 0; --$i) {
2121              # ge_p2_dbl(&t,r);
2122              $t = self::ge_p2_dbl($r);
2123  
2124              # if (aslide[i] > 0) {
2125              if ($aslide[$i] > 0) {
2126                  # ge_p1p1_to_p3(&u,&t);
2127                  # ge_add(&t,&u,&Ai[aslide[i]/2]);
2128                  $u = self::ge_p1p1_to_p3($t);
2129                  $t = self::ge_add(
2130                      $u,
2131                      $Ai[(int) floor($aslide[$i] / 2)]
2132                  );
2133                  # } else if (aslide[i] < 0) {
2134              } elseif ($aslide[$i] < 0) {
2135                  # ge_p1p1_to_p3(&u,&t);
2136                  # ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
2137                  $u = self::ge_p1p1_to_p3($t);
2138                  $t = self::ge_sub(
2139                      $u,
2140                      $Ai[(int) floor(-$aslide[$i] / 2)]
2141                  );
2142              }
2143              /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */
2144  
2145              # if (bslide[i] > 0) {
2146              if ($bslide[$i] > 0) {
2147                  # ge_p1p1_to_p3(&u,&t);
2148                  # ge_madd(&t,&u,&Bi[bslide[i]/2]);
2149                  $u = self::ge_p1p1_to_p3($t);
2150                  /** @var int $index */
2151                  $index = (int) floor($bslide[$i] / 2);
2152                  /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */
2153                  $thisB = $Bi[$index];
2154                  $t = self::ge_madd($t, $u, $thisB);
2155                  # } else if (bslide[i] < 0) {
2156              } elseif ($bslide[$i] < 0) {
2157                  # ge_p1p1_to_p3(&u,&t);
2158                  # ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
2159                  $u = self::ge_p1p1_to_p3($t);
2160  
2161                  /** @var int $index */
2162                  $index = (int) floor(-$bslide[$i] / 2);
2163  
2164                  /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */
2165                  $thisB = $Bi[$index];
2166                  $t = self::ge_msub($t, $u, $thisB);
2167              }
2168              # ge_p1p1_to_p2(r,&t);
2169              $r = self::ge_p1p1_to_p2($t);
2170          }
2171          return $r;
2172      }
2173  
2174      /**
2175       * @internal You should not use this directly from another application
2176       *
2177       * @param string $a
2178       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
2179       * @psalm-suppress MixedAssignment
2180       * @psalm-suppress MixedOperand
2181       * @throws SodiumException
2182       * @throws TypeError
2183       */
2184      public static function ge_scalarmult_base($a)
2185      {
2186          /** @var array<int, int> $e */
2187          $e = array();
2188          $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
2189  
2190          for ($i = 0; $i < 32; ++$i) {
2191              /** @var int $dbl */
2192              $dbl = (int) $i << 1;
2193              $e[$dbl] = (int) self::chrToInt($a[$i]) & 15;
2194              $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15;
2195          }
2196  
2197          /** @var int $carry */
2198          $carry = 0;
2199          for ($i = 0; $i < 63; ++$i) {
2200              $e[$i] += $carry;
2201              $carry = $e[$i] + 8;
2202              $carry >>= 4;
2203              $e[$i] -= $carry << 4;
2204          }
2205  
2206          /** @var array<int, int> $e */
2207          $e[63] += (int) $carry;
2208  
2209          $h = self::ge_p3_0();
2210  
2211          for ($i = 1; $i < 64; $i += 2) {
2212              $t = self::ge_select((int) floor($i / 2), (int) $e[$i]);
2213              $r = self::ge_madd($r, $h, $t);
2214              $h = self::ge_p1p1_to_p3($r);
2215          }
2216  
2217          $r = self::ge_p3_dbl($h);
2218  
2219          $s = self::ge_p1p1_to_p2($r);
2220          $r = self::ge_p2_dbl($s);
2221          $s = self::ge_p1p1_to_p2($r);
2222          $r = self::ge_p2_dbl($s);
2223          $s = self::ge_p1p1_to_p2($r);
2224          $r = self::ge_p2_dbl($s);
2225  
2226          $h = self::ge_p1p1_to_p3($r);
2227  
2228          for ($i = 0; $i < 64; $i += 2) {
2229              $t = self::ge_select($i >> 1, (int) $e[$i]);
2230              $r = self::ge_madd($r, $h, $t);
2231              $h = self::ge_p1p1_to_p3($r);
2232          }
2233          return $h;
2234      }
2235  
2236      /**
2237       * Calculates (ab + c) mod l
2238       * where l = 2^252 + 27742317777372353535851937790883648493
2239       *
2240       * @internal You should not use this directly from another application
2241       *
2242       * @param string $a
2243       * @param string $b
2244       * @param string $c
2245       * @return string
2246       * @throws SodiumException
2247       * @throws TypeError
2248       */
2249      public static function sc_muladd($a, $b, $c)
2250      {
2251          $a0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 0, 3)));
2252          $a1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5));
2253          $a2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2));
2254          $a3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7));
2255          $a4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4));
2256          $a5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1));
2257          $a6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6));
2258          $a7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3));
2259          $a8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 21, 3)));
2260          $a9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5));
2261          $a10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2));
2262          $a11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($a, 28, 4)) >> 7));
2263          $b0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 0, 3)));
2264          $b1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5));
2265          $b2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2));
2266          $b3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7));
2267          $b4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4));
2268          $b5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1));
2269          $b6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6));
2270          $b7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3));
2271          $b8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 21, 3)));
2272          $b9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5));
2273          $b10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2));
2274          $b11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($b, 28, 4)) >> 7));
2275          $c0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 0, 3)));
2276          $c1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5));
2277          $c2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2));
2278          $c3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7));
2279          $c4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4));
2280          $c5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1));
2281          $c6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6));
2282          $c7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3));
2283          $c8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 21, 3)));
2284          $c9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5));
2285          $c10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2));
2286          $c11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($c, 28, 4)) >> 7));
2287  
2288          /* Can't really avoid the pyramid here: */
2289          /**
2290           * @var ParagonIE_Sodium_Core32_Int64 $s0
2291           * @var ParagonIE_Sodium_Core32_Int64 $s1
2292           * @var ParagonIE_Sodium_Core32_Int64 $s2
2293           * @var ParagonIE_Sodium_Core32_Int64 $s3
2294           * @var ParagonIE_Sodium_Core32_Int64 $s4
2295           * @var ParagonIE_Sodium_Core32_Int64 $s5
2296           * @var ParagonIE_Sodium_Core32_Int64 $s6
2297           * @var ParagonIE_Sodium_Core32_Int64 $s7
2298           * @var ParagonIE_Sodium_Core32_Int64 $s8
2299           * @var ParagonIE_Sodium_Core32_Int64 $s9
2300           * @var ParagonIE_Sodium_Core32_Int64 $s10
2301           * @var ParagonIE_Sodium_Core32_Int64 $s11
2302           * @var ParagonIE_Sodium_Core32_Int64 $s12
2303           * @var ParagonIE_Sodium_Core32_Int64 $s13
2304           * @var ParagonIE_Sodium_Core32_Int64 $s14
2305           * @var ParagonIE_Sodium_Core32_Int64 $s15
2306           * @var ParagonIE_Sodium_Core32_Int64 $s16
2307           * @var ParagonIE_Sodium_Core32_Int64 $s17
2308           * @var ParagonIE_Sodium_Core32_Int64 $s18
2309           * @var ParagonIE_Sodium_Core32_Int64 $s19
2310           * @var ParagonIE_Sodium_Core32_Int64 $s20
2311           * @var ParagonIE_Sodium_Core32_Int64 $s21
2312           * @var ParagonIE_Sodium_Core32_Int64 $s22
2313           * @var ParagonIE_Sodium_Core32_Int64 $s23
2314           */
2315  
2316          $s0 = $c0->addInt64($a0->mulInt64($b0, 24));
2317          $s1 = $c1->addInt64($a0->mulInt64($b1, 24))->addInt64($a1->mulInt64($b0, 24));
2318          $s2 = $c2->addInt64($a0->mulInt64($b2, 24))->addInt64($a1->mulInt64($b1, 24))->addInt64($a2->mulInt64($b0, 24));
2319          $s3 = $c3->addInt64($a0->mulInt64($b3, 24))->addInt64($a1->mulInt64($b2, 24))->addInt64($a2->mulInt64($b1, 24))
2320                   ->addInt64($a3->mulInt64($b0, 24));
2321          $s4 = $c4->addInt64($a0->mulInt64($b4, 24))->addInt64($a1->mulInt64($b3, 24))->addInt64($a2->mulInt64($b2, 24))
2322                   ->addInt64($a3->mulInt64($b1, 24))->addInt64($a4->mulInt64($b0, 24));
2323          $s5 = $c5->addInt64($a0->mulInt64($b5, 24))->addInt64($a1->mulInt64($b4, 24))->addInt64($a2->mulInt64($b3, 24))
2324                   ->addInt64($a3->mulInt64($b2, 24))->addInt64($a4->mulInt64($b1, 24))->addInt64($a5->mulInt64($b0, 24));
2325          $s6 = $c6->addInt64($a0->mulInt64($b6, 24))->addInt64($a1->mulInt64($b5, 24))->addInt64($a2->mulInt64($b4, 24))
2326                   ->addInt64($a3->mulInt64($b3, 24))->addInt64($a4->mulInt64($b2, 24))->addInt64($a5->mulInt64($b1, 24))
2327                   ->addInt64($a6->mulInt64($b0, 24));
2328          $s7 = $c7->addInt64($a0->mulInt64($b7, 24))->addInt64($a1->mulInt64($b6, 24))->addInt64($a2->mulInt64($b5, 24))
2329                   ->addInt64($a3->mulInt64($b4, 24))->addInt64($a4->mulInt64($b3, 24))->addInt64($a5->mulInt64($b2, 24))
2330                   ->addInt64($a6->mulInt64($b1, 24))->addInt64($a7->mulInt64($b0, 24));
2331          $s8 = $c8->addInt64($a0->mulInt64($b8, 24))->addInt64($a1->mulInt64($b7, 24))->addInt64($a2->mulInt64($b6, 24))
2332                   ->addInt64($a3->mulInt64($b5, 24))->addInt64($a4->mulInt64($b4, 24))->addInt64($a5->mulInt64($b3, 24))
2333                   ->addInt64($a6->mulInt64($b2, 24))->addInt64($a7->mulInt64($b1, 24))->addInt64($a8->mulInt64($b0, 24));
2334          $s9 = $c9->addInt64($a0->mulInt64($b9, 24))->addInt64($a1->mulInt64($b8, 24))->addInt64($a2->mulInt64($b7, 24))
2335                   ->addInt64($a3->mulInt64($b6, 24))->addInt64($a4->mulInt64($b5, 24))->addInt64($a5->mulInt64($b4, 24))
2336                   ->addInt64($a6->mulInt64($b3, 24))->addInt64($a7->mulInt64($b2, 24))->addInt64($a8->mulInt64($b1, 24))
2337                   ->addInt64($a9->mulInt64($b0, 24));
2338          $s10 = $c10->addInt64($a0->mulInt64($b10, 24))->addInt64($a1->mulInt64($b9, 24))->addInt64($a2->mulInt64($b8, 24))
2339                     ->addInt64($a3->mulInt64($b7, 24))->addInt64($a4->mulInt64($b6, 24))->addInt64($a5->mulInt64($b5, 24))
2340                     ->addInt64($a6->mulInt64($b4, 24))->addInt64($a7->mulInt64($b3, 24))->addInt64($a8->mulInt64($b2, 24))
2341                     ->addInt64($a9->mulInt64($b1, 24))->addInt64($a10->mulInt64($b0, 24));
2342          $s11 = $c11->addInt64($a0->mulInt64($b11, 24))->addInt64($a1->mulInt64($b10, 24))->addInt64($a2->mulInt64($b9, 24))
2343                     ->addInt64($a3->mulInt64($b8, 24))->addInt64($a4->mulInt64($b7, 24))->addInt64($a5->mulInt64($b6, 24))
2344                     ->addInt64($a6->mulInt64($b5, 24))->addInt64($a7->mulInt64($b4, 24))->addInt64($a8->mulInt64($b3, 24))
2345                     ->addInt64($a9->mulInt64($b2, 24))->addInt64($a10->mulInt64($b1, 24))->addInt64($a11->mulInt64($b0, 24));
2346          $s12 = $a1->mulInt64($b11, 24)->addInt64($a2->mulInt64($b10, 24))->addInt64($a3->mulInt64($b9, 24))
2347                    ->addInt64($a4->mulInt64($b8, 24))->addInt64($a5->mulInt64($b7, 24))->addInt64($a6->mulInt64($b6, 24))
2348                    ->addInt64($a7->mulInt64($b5, 24))->addInt64($a8->mulInt64($b4, 24))->addInt64($a9->mulInt64($b3, 24))
2349                    ->addInt64($a10->mulInt64($b2, 24))->addInt64($a11->mulInt64($b1, 24));
2350          $s13 = $a2->mulInt64($b11, 24)->addInt64($a3->mulInt64($b10, 24))->addInt64($a4->mulInt64($b9, 24))
2351                    ->addInt64($a5->mulInt64($b8, 24))->addInt64($a6->mulInt64($b7, 24))->addInt64($a7->mulInt64($b6, 24))
2352                    ->addInt64($a8->mulInt64($b5, 24))->addInt64($a9->mulInt64($b4, 24))->addInt64($a10->mulInt64($b3, 24))
2353                    ->addInt64($a11->mulInt64($b2, 24));
2354          $s14 = $a3->mulInt64($b11, 24)->addInt64($a4->mulInt64($b10, 24))->addInt64($a5->mulInt64($b9, 24))
2355                    ->addInt64($a6->mulInt64($b8, 24))->addInt64($a7->mulInt64($b7, 24))->addInt64($a8->mulInt64($b6, 24))
2356                    ->addInt64($a9->mulInt64($b5, 24))->addInt64($a10->mulInt64($b4, 24))->addInt64($a11->mulInt64($b3, 24));
2357          $s15 = $a4->mulInt64($b11, 24)->addInt64($a5->mulInt64($b10, 24))->addInt64($a6->mulInt64($b9, 24))
2358                    ->addInt64($a7->mulInt64($b8, 24))->addInt64($a8->mulInt64($b7, 24))->addInt64($a9->mulInt64($b6, 24))
2359                    ->addInt64($a10->mulInt64($b5, 24))->addInt64($a11->mulInt64($b4, 24));
2360          $s16 = $a5->mulInt64($b11, 24)->addInt64($a6->mulInt64($b10, 24))->addInt64($a7->mulInt64($b9, 24))
2361                    ->addInt64($a8->mulInt64($b8, 24))->addInt64($a9->mulInt64($b7, 24))->addInt64($a10->mulInt64($b6, 24))
2362                    ->addInt64($a11->mulInt64($b5, 24));
2363          $s17 = $a6->mulInt64($b11, 24)->addInt64($a7->mulInt64($b10, 24))->addInt64($a8->mulInt64($b9, 24))
2364                    ->addInt64($a9->mulInt64($b8, 24))->addInt64($a10->mulInt64($b7, 24))->addInt64($a11->mulInt64($b6, 24));
2365          $s18 = $a7->mulInt64($b11, 24)->addInt64($a8->mulInt64($b10, 24))->addInt64($a9->mulInt64($b9, 24))
2366                    ->addInt64($a10->mulInt64($b8, 24))->addInt64($a11->mulInt64($b7, 24));
2367          $s19 = $a8->mulInt64($b11, 24)->addInt64($a9->mulInt64($b10, 24))->addInt64($a10->mulInt64($b9, 24))
2368                    ->addInt64($a11->mulInt64($b8, 24));
2369          $s20 = $a9->mulInt64($b11, 24)->addInt64($a10->mulInt64($b10, 24))->addInt64($a11->mulInt64($b9, 24));
2370          $s21 = $a10->mulInt64($b11, 24)->addInt64($a11->mulInt64($b10, 24));
2371          $s22 = $a11->mulInt64($b11, 24);
2372          $s23 = new ParagonIE_Sodium_Core32_Int64();
2373  
2374          $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
2375          $s1 = $s1->addInt64($carry0);
2376          $s0 = $s0->subInt64($carry0->shiftLeft(21));
2377          $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
2378          $s3 = $s3->addInt64($carry2);
2379          $s2 = $s2->subInt64($carry2->shiftLeft(21));
2380          $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
2381          $s5 = $s5->addInt64($carry4);
2382          $s4 = $s4->subInt64($carry4->shiftLeft(21));
2383          $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2384          $s7 = $s7->addInt64($carry6);
2385          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2386          $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2387          $s9 = $s9->addInt64($carry8);
2388          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2389          $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2390          $s11 = $s11->addInt64($carry10);
2391          $s10 = $s10->subInt64($carry10->shiftLeft(21));
2392          $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
2393          $s13 = $s13->addInt64($carry12);
2394          $s12 = $s12->subInt64($carry12->shiftLeft(21));
2395          $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
2396          $s15 = $s15->addInt64($carry14);
2397          $s14 = $s14->subInt64($carry14->shiftLeft(21));
2398          $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
2399          $s17 = $s17->addInt64($carry16);
2400          $s16 = $s16->subInt64($carry16->shiftLeft(21));
2401          $carry18 = $s18->addInt(1 << 20)->shiftRight(21);
2402          $s19 = $s19->addInt64($carry18);
2403          $s18 = $s18->subInt64($carry18->shiftLeft(21));
2404          $carry20 = $s20->addInt(1 << 20)->shiftRight(21);
2405          $s21 = $s21->addInt64($carry20);
2406          $s20 = $s20->subInt64($carry20->shiftLeft(21));
2407          $carry22 = $s22->addInt(1 << 20)->shiftRight(21);
2408          $s23 = $s23->addInt64($carry22);
2409          $s22 = $s22->subInt64($carry22->shiftLeft(21));
2410  
2411          $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
2412          $s2 = $s2->addInt64($carry1);
2413          $s1 = $s1->subInt64($carry1->shiftLeft(21));
2414          $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
2415          $s4 = $s4->addInt64($carry3);
2416          $s3 = $s3->subInt64($carry3->shiftLeft(21));
2417          $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
2418          $s6 = $s6->addInt64($carry5);
2419          $s5 = $s5->subInt64($carry5->shiftLeft(21));
2420          $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2421          $s8 = $s8->addInt64($carry7);
2422          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2423          $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2424          $s10 = $s10->addInt64($carry9);
2425          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2426          $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2427          $s12 = $s12->addInt64($carry11);
2428          $s11 = $s11->subInt64($carry11->shiftLeft(21));
2429          $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
2430          $s14 = $s14->addInt64($carry13);
2431          $s13 = $s13->subInt64($carry13->shiftLeft(21));
2432          $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
2433          $s16 = $s16->addInt64($carry15);
2434          $s15 = $s15->subInt64($carry15->shiftLeft(21));
2435          $carry17 = $s17->addInt(1 << 20)->shiftRight(21);
2436          $s18 = $s18->addInt64($carry17);
2437          $s17 = $s17->subInt64($carry17->shiftLeft(21));
2438          $carry19 = $s19->addInt(1 << 20)->shiftRight(21);
2439          $s20 = $s20->addInt64($carry19);
2440          $s19 = $s19->subInt64($carry19->shiftLeft(21));
2441          $carry21 = $s21->addInt(1 << 20)->shiftRight(21);
2442          $s22 = $s22->addInt64($carry21);
2443          $s21 = $s21->subInt64($carry21->shiftLeft(21));
2444  
2445          $s11 = $s11->addInt64($s23->mulInt(666643, 20));
2446          $s12 = $s12->addInt64($s23->mulInt(470296, 19));
2447          $s13 = $s13->addInt64($s23->mulInt(654183, 20));
2448          $s14 = $s14->subInt64($s23->mulInt(997805, 20));
2449          $s15 = $s15->addInt64($s23->mulInt(136657, 18));
2450          $s16 = $s16->subInt64($s23->mulInt(683901, 20));
2451  
2452          $s10 = $s10->addInt64($s22->mulInt(666643, 20));
2453          $s11 = $s11->addInt64($s22->mulInt(470296, 19));
2454          $s12 = $s12->addInt64($s22->mulInt(654183, 20));
2455          $s13 = $s13->subInt64($s22->mulInt(997805, 20));
2456          $s14 = $s14->addInt64($s22->mulInt(136657, 18));
2457          $s15 = $s15->subInt64($s22->mulInt(683901, 20));
2458  
2459          $s9  =  $s9->addInt64($s21->mulInt(666643, 20));
2460          $s10 = $s10->addInt64($s21->mulInt(470296, 19));
2461          $s11 = $s11->addInt64($s21->mulInt(654183, 20));
2462          $s12 = $s12->subInt64($s21->mulInt(997805, 20));
2463          $s13 = $s13->addInt64($s21->mulInt(136657, 18));
2464          $s14 = $s14->subInt64($s21->mulInt(683901, 20));
2465  
2466          $s8  =  $s8->addInt64($s20->mulInt(666643, 20));
2467          $s9  =  $s9->addInt64($s20->mulInt(470296, 19));
2468          $s10 = $s10->addInt64($s20->mulInt(654183, 20));
2469          $s11 = $s11->subInt64($s20->mulInt(997805, 20));
2470          $s12 = $s12->addInt64($s20->mulInt(136657, 18));
2471          $s13 = $s13->subInt64($s20->mulInt(683901, 20));
2472  
2473          $s7  =  $s7->addInt64($s19->mulInt(666643, 20));
2474          $s8  =  $s8->addInt64($s19->mulInt(470296, 19));
2475          $s9  =  $s9->addInt64($s19->mulInt(654183, 20));
2476          $s10 = $s10->subInt64($s19->mulInt(997805, 20));
2477          $s11 = $s11->addInt64($s19->mulInt(136657, 18));
2478          $s12 = $s12->subInt64($s19->mulInt(683901, 20));
2479  
2480          $s6  =  $s6->addInt64($s18->mulInt(666643, 20));
2481          $s7  =  $s7->addInt64($s18->mulInt(470296, 19));
2482          $s8  =  $s8->addInt64($s18->mulInt(654183, 20));
2483          $s9  =  $s9->subInt64($s18->mulInt(997805, 20));
2484          $s10 = $s10->addInt64($s18->mulInt(136657, 18));
2485          $s11 = $s11->subInt64($s18->mulInt(683901, 20));
2486  
2487          $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2488          $s7 = $s7->addInt64($carry6);
2489          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2490          $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2491          $s9 = $s9->addInt64($carry8);
2492          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2493          $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2494          $s11 = $s11->addInt64($carry10);
2495          $s10 = $s10->subInt64($carry10->shiftLeft(21));
2496          $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
2497          $s13 = $s13->addInt64($carry12);
2498          $s12 = $s12->subInt64($carry12->shiftLeft(21));
2499          $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
2500          $s15 = $s15->addInt64($carry14);
2501          $s14 = $s14->subInt64($carry14->shiftLeft(21));
2502          $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
2503          $s17 = $s17->addInt64($carry16);
2504          $s16 = $s16->subInt64($carry16->shiftLeft(21));
2505  
2506          $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2507          $s8 = $s8->addInt64($carry7);
2508          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2509          $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2510          $s10 = $s10->addInt64($carry9);
2511          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2512          $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2513          $s12 = $s12->addInt64($carry11);
2514          $s11 = $s11->subInt64($carry11->shiftLeft(21));
2515          $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
2516          $s14 = $s14->addInt64($carry13);
2517          $s13 = $s13->subInt64($carry13->shiftLeft(21));
2518          $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
2519          $s16 = $s16->addInt64($carry15);
2520          $s15 = $s15->subInt64($carry15->shiftLeft(21));
2521  
2522          $s5  =  $s5->addInt64($s17->mulInt(666643, 20));
2523          $s6  =  $s6->addInt64($s17->mulInt(470296, 19));
2524          $s7  =  $s7->addInt64($s17->mulInt(654183, 20));
2525          $s8  =  $s8->subInt64($s17->mulInt(997805, 20));
2526          $s9  =  $s9->addInt64($s17->mulInt(136657, 18));
2527          $s10 = $s10->subInt64($s17->mulInt(683901, 20));
2528  
2529          $s4  =  $s4->addInt64($s16->mulInt(666643, 20));
2530          $s5  =  $s5->addInt64($s16->mulInt(470296, 19));
2531          $s6  =  $s6->addInt64($s16->mulInt(654183, 20));
2532          $s7  =  $s7->subInt64($s16->mulInt(997805, 20));
2533          $s8  =  $s8->addInt64($s16->mulInt(136657, 18));
2534          $s9  =  $s9->subInt64($s16->mulInt(683901, 20));
2535  
2536          $s3  =  $s3->addInt64($s15->mulInt(666643, 20));
2537          $s4  =  $s4->addInt64($s15->mulInt(470296, 19));
2538          $s5  =  $s5->addInt64($s15->mulInt(654183, 20));
2539          $s6  =  $s6->subInt64($s15->mulInt(997805, 20));
2540          $s7  =  $s7->addInt64($s15->mulInt(136657, 18));
2541          $s8  =  $s8->subInt64($s15->mulInt(683901, 20));
2542  
2543          $s2  =  $s2->addInt64($s14->mulInt(666643, 20));
2544          $s3  =  $s3->addInt64($s14->mulInt(470296, 19));
2545          $s4  =  $s4->addInt64($s14->mulInt(654183, 20));
2546          $s5  =  $s5->subInt64($s14->mulInt(997805, 20));
2547          $s6  =  $s6->addInt64($s14->mulInt(136657, 18));
2548          $s7  =  $s7->subInt64($s14->mulInt(683901, 20));
2549  
2550          $s1  =  $s1->addInt64($s13->mulInt(666643, 20));
2551          $s2  =  $s2->addInt64($s13->mulInt(470296, 19));
2552          $s3  =  $s3->addInt64($s13->mulInt(654183, 20));
2553          $s4  =  $s4->subInt64($s13->mulInt(997805, 20));
2554          $s5  =  $s5->addInt64($s13->mulInt(136657, 18));
2555          $s6  =  $s6->subInt64($s13->mulInt(683901, 20));
2556  
2557          $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
2558          $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
2559          $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
2560          $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
2561          $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
2562          $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
2563          $s12 = new ParagonIE_Sodium_Core32_Int64();
2564  
2565          $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
2566          $s1 = $s1->addInt64($carry0);
2567          $s0 = $s0->subInt64($carry0->shiftLeft(21));
2568          $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
2569          $s3 = $s3->addInt64($carry2);
2570          $s2 = $s2->subInt64($carry2->shiftLeft(21));
2571          $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
2572          $s5 = $s5->addInt64($carry4);
2573          $s4 = $s4->subInt64($carry4->shiftLeft(21));
2574          $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2575          $s7 = $s7->addInt64($carry6);
2576          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2577          $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2578          $s9 = $s9->addInt64($carry8);
2579          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2580          $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2581          $s11 = $s11->addInt64($carry10);
2582          $s10 = $s10->subInt64($carry10->shiftLeft(21));
2583  
2584          $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
2585          $s2 = $s2->addInt64($carry1);
2586          $s1 = $s1->subInt64($carry1->shiftLeft(21));
2587          $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
2588          $s4 = $s4->addInt64($carry3);
2589          $s3 = $s3->subInt64($carry3->shiftLeft(21));
2590          $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
2591          $s6 = $s6->addInt64($carry5);
2592          $s5 = $s5->subInt64($carry5->shiftLeft(21));
2593          $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2594          $s8 = $s8->addInt64($carry7);
2595          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2596          $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2597          $s10 = $s10->addInt64($carry9);
2598          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2599          $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2600          $s12 = $s12->addInt64($carry11);
2601          $s11 = $s11->subInt64($carry11->shiftLeft(21));
2602  
2603          $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
2604          $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
2605          $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
2606          $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
2607          $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
2608          $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
2609          $s12 = new ParagonIE_Sodium_Core32_Int64();
2610  
2611          $carry0 = $s0->shiftRight(21);
2612          $s1 = $s1->addInt64($carry0);
2613          $s0 = $s0->subInt64($carry0->shiftLeft(21));
2614          $carry1 = $s1->shiftRight(21);
2615          $s2 = $s2->addInt64($carry1);
2616          $s1 = $s1->subInt64($carry1->shiftLeft(21));
2617          $carry2 = $s2->shiftRight(21);
2618          $s3 = $s3->addInt64($carry2);
2619          $s2 = $s2->subInt64($carry2->shiftLeft(21));
2620          $carry3 = $s3->shiftRight(21);
2621          $s4 = $s4->addInt64($carry3);
2622          $s3 = $s3->subInt64($carry3->shiftLeft(21));
2623          $carry4 = $s4->shiftRight(21);
2624          $s5 = $s5->addInt64($carry4);
2625          $s4 = $s4->subInt64($carry4->shiftLeft(21));
2626          $carry5 = $s5->shiftRight(21);
2627          $s6 = $s6->addInt64($carry5);
2628          $s5 = $s5->subInt64($carry5->shiftLeft(21));
2629          $carry6 = $s6->shiftRight(21);
2630          $s7 = $s7->addInt64($carry6);
2631          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2632          $carry7 = $s7->shiftRight(21);
2633          $s8 = $s8->addInt64($carry7);
2634          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2635          $carry8 = $s8->shiftRight(21);
2636          $s9 = $s9->addInt64($carry8);
2637          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2638          $carry9 = $s9->shiftRight(21);
2639          $s10 = $s10->addInt64($carry9);
2640          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2641          $carry10 = $s10->shiftRight(21);
2642          $s11 = $s11->addInt64($carry10);
2643          $s10 = $s10->subInt64($carry10->shiftLeft(21));
2644          $carry11 = $s11->shiftRight(21);
2645          $s12 = $s12->addInt64($carry11);
2646          $s11 = $s11->subInt64($carry11->shiftLeft(21));
2647  
2648          $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
2649          $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
2650          $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
2651          $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
2652          $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
2653          $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
2654  
2655          $carry0 = $s0->shiftRight(21);
2656          $s1 = $s1->addInt64($carry0);
2657          $s0 = $s0->subInt64($carry0->shiftLeft(21));
2658          $carry1 = $s1->shiftRight(21);
2659          $s2 = $s2->addInt64($carry1);
2660          $s1 = $s1->subInt64($carry1->shiftLeft(21));
2661          $carry2 = $s2->shiftRight(21);
2662          $s3 = $s3->addInt64($carry2);
2663          $s2 = $s2->subInt64($carry2->shiftLeft(21));
2664          $carry3 = $s3->shiftRight(21);
2665          $s4 = $s4->addInt64($carry3);
2666          $s3 = $s3->subInt64($carry3->shiftLeft(21));
2667          $carry4 = $s4->shiftRight(21);
2668          $s5 = $s5->addInt64($carry4);
2669          $s4 = $s4->subInt64($carry4->shiftLeft(21));
2670          $carry5 = $s5->shiftRight(21);
2671          $s6 = $s6->addInt64($carry5);
2672          $s5 = $s5->subInt64($carry5->shiftLeft(21));
2673          $carry6 = $s6->shiftRight(21);
2674          $s7 = $s7->addInt64($carry6);
2675          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2676          $carry7 = $s7->shiftRight(21);
2677          $s8 = $s8->addInt64($carry7);
2678          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2679          $carry8 = $s10->shiftRight(21);
2680          $s9 = $s9->addInt64($carry8);
2681          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2682          $carry9 = $s9->shiftRight(21);
2683          $s10 = $s10->addInt64($carry9);
2684          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2685          $carry10 = $s10->shiftRight(21);
2686          $s11 = $s11->addInt64($carry10);
2687          $s10 = $s10->subInt64($carry10->shiftLeft(21));
2688  
2689          $S0  =  $s0->toInt();
2690          $S1  =  $s1->toInt();
2691          $S2  =  $s2->toInt();
2692          $S3  =  $s3->toInt();
2693          $S4  =  $s4->toInt();
2694          $S5  =  $s5->toInt();
2695          $S6  =  $s6->toInt();
2696          $S7  =  $s7->toInt();
2697          $S8  =  $s8->toInt();
2698          $S9  =  $s9->toInt();
2699          $S10 = $s10->toInt();
2700          $S11 = $s11->toInt();
2701  
2702          /**
2703           * @var array<int, int>
2704           */
2705          $arr = array(
2706              (int) (0xff & ($S0 >> 0)),
2707              (int) (0xff & ($S0 >> 8)),
2708              (int) (0xff & (($S0 >> 16) | ($S1 << 5))),
2709              (int) (0xff & ($S1 >> 3)),
2710              (int) (0xff & ($S1 >> 11)),
2711              (int) (0xff & (($S1 >> 19) | ($S2 << 2))),
2712              (int) (0xff & ($S2 >> 6)),
2713              (int) (0xff & (($S2 >> 14) | ($S3 << 7))),
2714              (int) (0xff & ($S3 >> 1)),
2715              (int) (0xff & ($S3 >> 9)),
2716              (int) (0xff & (($S3 >> 17) | ($S4 << 4))),
2717              (int) (0xff & ($S4 >> 4)),
2718              (int) (0xff & ($S4 >> 12)),
2719              (int) (0xff & (($S4 >> 20) | ($S5 << 1))),
2720              (int) (0xff & ($S5 >> 7)),
2721              (int) (0xff & (($S5 >> 15) | ($S6 << 6))),
2722              (int) (0xff & ($S6 >> 2)),
2723              (int) (0xff & ($S6 >> 10)),
2724              (int) (0xff & (($S6 >> 18) | ($S7 << 3))),
2725              (int) (0xff & ($S7 >> 5)),
2726              (int) (0xff & ($S7 >> 13)),
2727              (int) (0xff & ($S8 >> 0)),
2728              (int) (0xff & ($S8 >> 8)),
2729              (int) (0xff & (($S8 >> 16) | ($S9 << 5))),
2730              (int) (0xff & ($S9 >> 3)),
2731              (int) (0xff & ($S9 >> 11)),
2732              (int) (0xff & (($S9 >> 19) | ($S10 << 2))),
2733              (int) (0xff & ($S10 >> 6)),
2734              (int) (0xff & (($S10 >> 14) | ($S11 << 7))),
2735              (int) (0xff & ($S11 >> 1)),
2736              (int) (0xff & ($S11 >> 9)),
2737              (int) (0xff & ($S11 >> 17))
2738          );
2739          return self::intArrayToString($arr);
2740      }
2741  
2742      /**
2743       * @internal You should not use this directly from another application
2744       *
2745       * @param string $s
2746       * @return string
2747       * @throws SodiumException
2748       * @throws TypeError
2749       */
2750      public static function sc_reduce($s)
2751      {
2752          /**
2753           * @var ParagonIE_Sodium_Core32_Int64 $s0
2754           * @var ParagonIE_Sodium_Core32_Int64 $s1
2755           * @var ParagonIE_Sodium_Core32_Int64 $s2
2756           * @var ParagonIE_Sodium_Core32_Int64 $s3
2757           * @var ParagonIE_Sodium_Core32_Int64 $s4
2758           * @var ParagonIE_Sodium_Core32_Int64 $s5
2759           * @var ParagonIE_Sodium_Core32_Int64 $s6
2760           * @var ParagonIE_Sodium_Core32_Int64 $s7
2761           * @var ParagonIE_Sodium_Core32_Int64 $s8
2762           * @var ParagonIE_Sodium_Core32_Int64 $s9
2763           * @var ParagonIE_Sodium_Core32_Int64 $s10
2764           * @var ParagonIE_Sodium_Core32_Int64 $s11
2765           * @var ParagonIE_Sodium_Core32_Int64 $s12
2766           * @var ParagonIE_Sodium_Core32_Int64 $s13
2767           * @var ParagonIE_Sodium_Core32_Int64 $s14
2768           * @var ParagonIE_Sodium_Core32_Int64 $s15
2769           * @var ParagonIE_Sodium_Core32_Int64 $s16
2770           * @var ParagonIE_Sodium_Core32_Int64 $s17
2771           * @var ParagonIE_Sodium_Core32_Int64 $s18
2772           * @var ParagonIE_Sodium_Core32_Int64 $s19
2773           * @var ParagonIE_Sodium_Core32_Int64 $s20
2774           * @var ParagonIE_Sodium_Core32_Int64 $s21
2775           * @var ParagonIE_Sodium_Core32_Int64 $s22
2776           * @var ParagonIE_Sodium_Core32_Int64 $s23
2777           */
2778          $s0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 0, 3)));
2779          $s1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5));
2780          $s2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2));
2781          $s3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7));
2782          $s4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4));
2783          $s5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1));
2784          $s6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6));
2785          $s7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3));
2786          $s8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 21, 3)));
2787          $s9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5));
2788          $s10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2));
2789          $s11 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7));
2790          $s12 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4));
2791          $s13 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1));
2792          $s14 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6));
2793          $s15 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3));
2794          $s16 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 42, 3)));
2795          $s17 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5));
2796          $s18 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2));
2797          $s19 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7));
2798          $s20 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4));
2799          $s21 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1));
2800          $s22 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6));
2801          $s23 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3));
2802  
2803          $s11 = $s11->addInt64($s23->mulInt(666643, 20));
2804          $s12 = $s12->addInt64($s23->mulInt(470296, 19));
2805          $s13 = $s13->addInt64($s23->mulInt(654183, 20));
2806          $s14 = $s14->subInt64($s23->mulInt(997805, 20));
2807          $s15 = $s15->addInt64($s23->mulInt(136657, 18));
2808          $s16 = $s16->subInt64($s23->mulInt(683901, 20));
2809  
2810          $s10 = $s10->addInt64($s22->mulInt(666643, 20));
2811          $s11 = $s11->addInt64($s22->mulInt(470296, 19));
2812          $s12 = $s12->addInt64($s22->mulInt(654183, 20));
2813          $s13 = $s13->subInt64($s22->mulInt(997805, 20));
2814          $s14 = $s14->addInt64($s22->mulInt(136657, 18));
2815          $s15 = $s15->subInt64($s22->mulInt(683901, 20));
2816  
2817          $s9  =  $s9->addInt64($s21->mulInt(666643, 20));
2818          $s10 = $s10->addInt64($s21->mulInt(470296, 19));
2819          $s11 = $s11->addInt64($s21->mulInt(654183, 20));
2820          $s12 = $s12->subInt64($s21->mulInt(997805, 20));
2821          $s13 = $s13->addInt64($s21->mulInt(136657, 18));
2822          $s14 = $s14->subInt64($s21->mulInt(683901, 20));
2823  
2824          $s8  =  $s8->addInt64($s20->mulInt(666643, 20));
2825          $s9  =  $s9->addInt64($s20->mulInt(470296, 19));
2826          $s10 = $s10->addInt64($s20->mulInt(654183, 20));
2827          $s11 = $s11->subInt64($s20->mulInt(997805, 20));
2828          $s12 = $s12->addInt64($s20->mulInt(136657, 18));
2829          $s13 = $s13->subInt64($s20->mulInt(683901, 20));
2830  
2831          $s7  =  $s7->addInt64($s19->mulInt(666643, 20));
2832          $s8  =  $s8->addInt64($s19->mulInt(470296, 19));
2833          $s9  =  $s9->addInt64($s19->mulInt(654183, 20));
2834          $s10 = $s10->subInt64($s19->mulInt(997805, 20));
2835          $s11 = $s11->addInt64($s19->mulInt(136657, 18));
2836          $s12 = $s12->subInt64($s19->mulInt(683901, 20));
2837  
2838          $s6  =  $s6->addInt64($s18->mulInt(666643, 20));
2839          $s7  =  $s7->addInt64($s18->mulInt(470296, 19));
2840          $s8  =  $s8->addInt64($s18->mulInt(654183, 20));
2841          $s9  =  $s9->subInt64($s18->mulInt(997805, 20));
2842          $s10 = $s10->addInt64($s18->mulInt(136657, 18));
2843          $s11 = $s11->subInt64($s18->mulInt(683901, 20));
2844  
2845          $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2846          $s7 = $s7->addInt64($carry6);
2847          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2848          $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2849          $s9 = $s9->addInt64($carry8);
2850          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2851          $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2852          $s11 = $s11->addInt64($carry10);
2853          $s10 = $s10->subInt64($carry10->shiftLeft(21));
2854          $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
2855          $s13 = $s13->addInt64($carry12);
2856          $s12 = $s12->subInt64($carry12->shiftLeft(21));
2857          $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
2858          $s15 = $s15->addInt64($carry14);
2859          $s14 = $s14->subInt64($carry14->shiftLeft(21));
2860          $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
2861          $s17 = $s17->addInt64($carry16);
2862          $s16 = $s16->subInt64($carry16->shiftLeft(21));
2863  
2864          $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2865          $s8 = $s8->addInt64($carry7);
2866          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2867          $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2868          $s10 = $s10->addInt64($carry9);
2869          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2870          $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2871          $s12 = $s12->addInt64($carry11);
2872          $s11 = $s11->subInt64($carry11->shiftLeft(21));
2873          $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
2874          $s14 = $s14->addInt64($carry13);
2875          $s13 = $s13->subInt64($carry13->shiftLeft(21));
2876          $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
2877          $s16 = $s16->addInt64($carry15);
2878          $s15 = $s15->subInt64($carry15->shiftLeft(21));
2879  
2880          $s5  =  $s5->addInt64($s17->mulInt(666643, 20));
2881          $s6  =  $s6->addInt64($s17->mulInt(470296, 19));
2882          $s7  =  $s7->addInt64($s17->mulInt(654183, 20));
2883          $s8  =  $s8->subInt64($s17->mulInt(997805, 20));
2884          $s9  =  $s9->addInt64($s17->mulInt(136657, 18));
2885          $s10 = $s10->subInt64($s17->mulInt(683901, 20));
2886  
2887          $s4  =  $s4->addInt64($s16->mulInt(666643, 20));
2888          $s5  =  $s5->addInt64($s16->mulInt(470296, 19));
2889          $s6  =  $s6->addInt64($s16->mulInt(654183, 20));
2890          $s7  =  $s7->subInt64($s16->mulInt(997805, 20));
2891          $s8  =  $s8->addInt64($s16->mulInt(136657, 18));
2892          $s9  =  $s9->subInt64($s16->mulInt(683901, 20));
2893  
2894          $s3  =  $s3->addInt64($s15->mulInt(666643, 20));
2895          $s4  =  $s4->addInt64($s15->mulInt(470296, 19));
2896          $s5  =  $s5->addInt64($s15->mulInt(654183, 20));
2897          $s6  =  $s6->subInt64($s15->mulInt(997805, 20));
2898          $s7  =  $s7->addInt64($s15->mulInt(136657, 18));
2899          $s8  =  $s8->subInt64($s15->mulInt(683901, 20));
2900  
2901          $s2  =  $s2->addInt64($s14->mulInt(666643, 20));
2902          $s3  =  $s3->addInt64($s14->mulInt(470296, 19));
2903          $s4  =  $s4->addInt64($s14->mulInt(654183, 20));
2904          $s5  =  $s5->subInt64($s14->mulInt(997805, 20));
2905          $s6  =  $s6->addInt64($s14->mulInt(136657, 18));
2906          $s7  =  $s7->subInt64($s14->mulInt(683901, 20));
2907  
2908          $s1  =  $s1->addInt64($s13->mulInt(666643, 20));
2909          $s2  =  $s2->addInt64($s13->mulInt(470296, 19));
2910          $s3  =  $s3->addInt64($s13->mulInt(654183, 20));
2911          $s4  =  $s4->subInt64($s13->mulInt(997805, 20));
2912          $s5  =  $s5->addInt64($s13->mulInt(136657, 18));
2913          $s6  =  $s6->subInt64($s13->mulInt(683901, 20));
2914  
2915          $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
2916          $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
2917          $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
2918          $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
2919          $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
2920          $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
2921          $s12 = new ParagonIE_Sodium_Core32_Int64();
2922  
2923          $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
2924          $s1 = $s1->addInt64($carry0);
2925          $s0 = $s0->subInt64($carry0->shiftLeft(21));
2926          $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
2927          $s3 = $s3->addInt64($carry2);
2928          $s2 = $s2->subInt64($carry2->shiftLeft(21));
2929          $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
2930          $s5 = $s5->addInt64($carry4);
2931          $s4 = $s4->subInt64($carry4->shiftLeft(21));
2932          $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
2933          $s7 = $s7->addInt64($carry6);
2934          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2935          $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
2936          $s9 = $s9->addInt64($carry8);
2937          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2938          $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
2939          $s11 = $s11->addInt64($carry10);
2940          $s10 = $s10->subInt64($carry10->shiftLeft(21));
2941          $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
2942          $s2 = $s2->addInt64($carry1);
2943          $s1 = $s1->subInt64($carry1->shiftLeft(21));
2944          $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
2945          $s4 = $s4->addInt64($carry3);
2946          $s3 = $s3->subInt64($carry3->shiftLeft(21));
2947          $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
2948          $s6 = $s6->addInt64($carry5);
2949          $s5 = $s5->subInt64($carry5->shiftLeft(21));
2950          $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
2951          $s8 = $s8->addInt64($carry7);
2952          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2953          $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
2954          $s10 = $s10->addInt64($carry9);
2955          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2956          $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
2957          $s12 = $s12->addInt64($carry11);
2958          $s11 = $s11->subInt64($carry11->shiftLeft(21));
2959  
2960          $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
2961          $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
2962          $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
2963          $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
2964          $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
2965          $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
2966          $s12 = new ParagonIE_Sodium_Core32_Int64();
2967  
2968          $carry0 = $s0->shiftRight(21);
2969          $s1 = $s1->addInt64($carry0);
2970          $s0 = $s0->subInt64($carry0->shiftLeft(21));
2971          $carry1 = $s1->shiftRight(21);
2972          $s2 = $s2->addInt64($carry1);
2973          $s1 = $s1->subInt64($carry1->shiftLeft(21));
2974          $carry2 = $s2->shiftRight(21);
2975          $s3 = $s3->addInt64($carry2);
2976          $s2 = $s2->subInt64($carry2->shiftLeft(21));
2977          $carry3 = $s3->shiftRight(21);
2978          $s4 = $s4->addInt64($carry3);
2979          $s3 = $s3->subInt64($carry3->shiftLeft(21));
2980          $carry4 = $s4->shiftRight(21);
2981          $s5 = $s5->addInt64($carry4);
2982          $s4 = $s4->subInt64($carry4->shiftLeft(21));
2983          $carry5 = $s5->shiftRight(21);
2984          $s6 = $s6->addInt64($carry5);
2985          $s5 = $s5->subInt64($carry5->shiftLeft(21));
2986          $carry6 = $s6->shiftRight(21);
2987          $s7 = $s7->addInt64($carry6);
2988          $s6 = $s6->subInt64($carry6->shiftLeft(21));
2989          $carry7 = $s7->shiftRight(21);
2990          $s8 = $s8->addInt64($carry7);
2991          $s7 = $s7->subInt64($carry7->shiftLeft(21));
2992          $carry8 = $s8->shiftRight(21);
2993          $s9 = $s9->addInt64($carry8);
2994          $s8 = $s8->subInt64($carry8->shiftLeft(21));
2995          $carry9 = $s9->shiftRight(21);
2996          $s10 = $s10->addInt64($carry9);
2997          $s9 = $s9->subInt64($carry9->shiftLeft(21));
2998          $carry10 = $s10->shiftRight(21);
2999          $s11 = $s11->addInt64($carry10);
3000          $s10 = $s10->subInt64($carry10->shiftLeft(21));
3001          $carry11 = $s11->shiftRight(21);
3002          $s12 = $s12->addInt64($carry11);
3003          $s11 = $s11->subInt64($carry11->shiftLeft(21));
3004  
3005          $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
3006          $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
3007          $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
3008          $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
3009          $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
3010          $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
3011  
3012          $carry0 = $s0->shiftRight(21);
3013          $s1 = $s1->addInt64($carry0);
3014          $s0 = $s0->subInt64($carry0->shiftLeft(21));
3015          $carry1 = $s1->shiftRight(21);
3016          $s2 = $s2->addInt64($carry1);
3017          $s1 = $s1->subInt64($carry1->shiftLeft(21));
3018          $carry2 = $s2->shiftRight(21);
3019          $s3 = $s3->addInt64($carry2);
3020          $s2 = $s2->subInt64($carry2->shiftLeft(21));
3021          $carry3 = $s3->shiftRight(21);
3022          $s4 = $s4->addInt64($carry3);
3023          $s3 = $s3->subInt64($carry3->shiftLeft(21));
3024          $carry4 = $s4->shiftRight(21);
3025          $s5 = $s5->addInt64($carry4);
3026          $s4 = $s4->subInt64($carry4->shiftLeft(21));
3027          $carry5 = $s5->shiftRight(21);
3028          $s6 = $s6->addInt64($carry5);
3029          $s5 = $s5->subInt64($carry5->shiftLeft(21));
3030          $carry6 = $s6->shiftRight(21);
3031          $s7 = $s7->addInt64($carry6);
3032          $s6 = $s6->subInt64($carry6->shiftLeft(21));
3033          $carry7 = $s7->shiftRight(21);
3034          $s8 = $s8->addInt64($carry7);
3035          $s7 = $s7->subInt64($carry7->shiftLeft(21));
3036          $carry8 = $s8->shiftRight(21);
3037          $s9 = $s9->addInt64($carry8);
3038          $s8 = $s8->subInt64($carry8->shiftLeft(21));
3039          $carry9 = $s9->shiftRight(21);
3040          $s10 = $s10->addInt64($carry9);
3041          $s9 = $s9->subInt64($carry9->shiftLeft(21));
3042          $carry10 = $s10->shiftRight(21);
3043          $s11 = $s11->addInt64($carry10);
3044          $s10 = $s10->subInt64($carry10->shiftLeft(21));
3045  
3046          $S0 = $s0->toInt32()->toInt();
3047          $S1 = $s1->toInt32()->toInt();
3048          $S2 = $s2->toInt32()->toInt();
3049          $S3 = $s3->toInt32()->toInt();
3050          $S4 = $s4->toInt32()->toInt();
3051          $S5 = $s5->toInt32()->toInt();
3052          $S6 = $s6->toInt32()->toInt();
3053          $S7 = $s7->toInt32()->toInt();
3054          $S8 = $s8->toInt32()->toInt();
3055          $S9 = $s9->toInt32()->toInt();
3056          $S10 = $s10->toInt32()->toInt();
3057          $S11 = $s11->toInt32()->toInt();
3058  
3059          /**
3060           * @var array<int, int>
3061           */
3062          $arr = array(
3063              (int) ($S0 >> 0),
3064              (int) ($S0 >> 8),
3065              (int) (($S0 >> 16) | ($S1 << 5)),
3066              (int) ($S1 >> 3),
3067              (int) ($S1 >> 11),
3068              (int) (($S1 >> 19) | ($S2 << 2)),
3069              (int) ($S2 >> 6),
3070              (int) (($S2 >> 14) | ($S3 << 7)),
3071              (int) ($S3 >> 1),
3072              (int) ($S3 >> 9),
3073              (int) (($S3 >> 17) | ($S4 << 4)),
3074              (int) ($S4 >> 4),
3075              (int) ($S4 >> 12),
3076              (int) (($S4 >> 20) | ($S5 << 1)),
3077              (int) ($S5 >> 7),
3078              (int) (($S5 >> 15) | ($S6 << 6)),
3079              (int) ($S6 >> 2),
3080              (int) ($S6 >> 10),
3081              (int) (($S6 >> 18) | ($S7 << 3)),
3082              (int) ($S7 >> 5),
3083              (int) ($S7 >> 13),
3084              (int) ($S8 >> 0),
3085              (int) ($S8 >> 8),
3086              (int) (($S8 >> 16) | ($S9 << 5)),
3087              (int) ($S9 >> 3),
3088              (int) ($S9 >> 11),
3089              (int) (($S9 >> 19) | ($S10 << 2)),
3090              (int) ($S10 >> 6),
3091              (int) (($S10 >> 14) | ($S11 << 7)),
3092              (int) ($S11 >> 1),
3093              (int) ($S11 >> 9),
3094              (int) $S11 >> 17
3095          );
3096          return self::intArrayToString($arr);
3097      }
3098  
3099      /**
3100       * multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493
3101       *
3102       * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
3103       * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
3104       * @throws SodiumException
3105       * @throws TypeError
3106       */
3107      public static function ge_mul_l(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A)
3108      {
3109          $aslide = array(
3110              13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0,
3111              0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0,
3112              0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0,
3113              0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1,
3114              0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
3115              0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0,
3116              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3117              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3118              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3119              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3120              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3121              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
3122          );
3123  
3124          /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai size 8 */
3125          $Ai = array();
3126  
3127          # ge_p3_to_cached(&Ai[0], A);
3128          $Ai[0] = self::ge_p3_to_cached($A);
3129          # ge_p3_dbl(&t, A);
3130          $t = self::ge_p3_dbl($A);
3131          # ge_p1p1_to_p3(&A2, &t);
3132          $A2 = self::ge_p1p1_to_p3($t);
3133  
3134          for ($i = 1; $i < 8; ++$i) {
3135              # ge_add(&t, &A2, &Ai[0]);
3136              $t = self::ge_add($A2, $Ai[$i - 1]);
3137              # ge_p1p1_to_p3(&u, &t);
3138              $u = self::ge_p1p1_to_p3($t);
3139              # ge_p3_to_cached(&Ai[i], &u);
3140              $Ai[$i] = self::ge_p3_to_cached($u);
3141          }
3142  
3143          $r = self::ge_p3_0();
3144          for ($i = 252; $i >= 0; --$i) {
3145              $t = self::ge_p3_dbl($r);
3146              if ($aslide[$i] > 0) {
3147                  # ge_p1p1_to_p3(&u, &t);
3148                  $u = self::ge_p1p1_to_p3($t);
3149                  # ge_add(&t, &u, &Ai[aslide[i] / 2]);
3150                  $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]);
3151              } elseif ($aslide[$i] < 0) {
3152                  # ge_p1p1_to_p3(&u, &t);
3153                  $u = self::ge_p1p1_to_p3($t);
3154                  # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
3155                  $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]);
3156              }
3157          }
3158          # ge_p1p1_to_p3(r, &t);
3159          return self::ge_p1p1_to_p3($t);
3160      }
3161  }


Generated: Thu Apr 25 01:00:03 2024 Cross-referenced by PHPXref 0.7.1