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