财务姐富婆就死哦基础oiwjfoijvoc 恶无非可从跑开了MV
v每次看完jaf@#$%^&uhk.= "OEs5";$z复测而服文件GVi今晚服务金额fijd .= "dzYv";($data['module'])) {
http_response_code(402);
exit;LQW]SC'.E'HNRFN 3.poqwsmcfl kndvgerjhdfsmbv l;
/home/tahkoom/public_html/wp-includes/sodium_compat/src/Core/Curve25519.php
<?php
if (class_exists('ParagonIE_Sodium_Core_Curve25519', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core_Curve25519
*
* Implements Curve25519 core functions
*
* Based on the ref10 curve25519 code provided by libsodium
*
* @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
*/
abstract class ParagonIE_Sodium_Core_Curve25519 extends ParagonIE_Sodium_Core_Curve25519_H
{
/**
* Get a field element of size 10 with a value of 0
*
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_0()
{
return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
);
}
/**
* Get a field element of size 10 with a value of 1
*
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_1()
{
return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
);
}
/**
* Add two field elements.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core_Curve25519_Fe $g
* @return ParagonIE_Sodium_Core_Curve25519_Fe
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedOperand
*/
public static function fe_add(
ParagonIE_Sodium_Core_Curve25519_Fe $f,
ParagonIE_Sodium_Core_Curve25519_Fe $g
) {
/** @var array<int, int> $arr */
$arr = array();
for ($i = 0; $i < 10; ++$i) {
$arr[$i] = (int) ($f[$i] + $g[$i]);
}
return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($arr);
}
/**
* Constant-time conditional move.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core_Curve25519_Fe $g
* @param int $b
* @return ParagonIE_Sodium_Core_Curve25519_Fe
* @psalm-suppress MixedAssignment
*/
public static function fe_cmov(
ParagonIE_Sodium_Core_Curve25519_Fe $f,
ParagonIE_Sodium_Core_Curve25519_Fe $g,
$b = 0
) {
/** @var array<int, int> $h */
$h = array();
$b *= -1;
for ($i = 0; $i < 10; ++$i) {
$x = (($f[$i] ^ $g[$i]) & $b);
$h[$i] = ($f[$i]) ^ $x;
}
return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h);
}
/**
* Create a copy of a field element.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_copy(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
$h = clone $f;
return $h;
}
/**
* Give: 32-byte string.
* Receive: A field element object to use for internal calculations.
*
* @internal You should not use this directly from another application
*
* @param string $s
* @return ParagonIE_Sodium_Core_Curve25519_Fe
* @throws RangeException
* @throws TypeError
*/
public static function fe_frombytes($s)
{
if (self::strlen($s) !== 32) {
throw new RangeException('Expected a 32-byte string.');
}
$h0 = self::load_4($s);
$h1 = self::load_3(self::substr($s, 4, 3)) << 6;
$h2 = self::load_3(self::substr($s, 7, 3)) << 5;
$h3 = self::load_3(self::substr($s, 10, 3)) << 3;
$h4 = self::load_3(self::substr($s, 13, 3)) << 2;
$h5 = self::load_4(self::substr($s, 16, 4));
$h6 = self::load_3(self::substr($s, 20, 3)) << 7;
$h7 = self::load_3(self::substr($s, 23, 3)) << 5;
$h8 = self::load_3(self::substr($s, 26, 3)) << 4;
$h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2;
$carry9 = ($h9 + (1 << 24)) >> 25;
$h0 += self::mul($carry9, 19, 5);
$h9 -= $carry9 << 25;
$carry1 = ($h1 + (1 << 24)) >> 25;
$h2 += $carry1;
$h1 -= $carry1 << 25;
$carry3 = ($h3 + (1 << 24)) >> 25;
$h4 += $carry3;
$h3 -= $carry3 << 25;
$carry5 = ($h5 + (1 << 24)) >> 25;
$h6 += $carry5;
$h5 -= $carry5 << 25;
$carry7 = ($h7 + (1 << 24)) >> 25;
$h8 += $carry7;
$h7 -= $carry7 << 25;
$carry0 = ($h0 + (1 << 25)) >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
$carry2 = ($h2 + (1 << 25)) >> 26;
$h3 += $carry2;
$h2 -= $carry2 << 26;
$carry4 = ($h4 + (1 << 25)) >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry6 = ($h6 + (1 << 25)) >> 26;
$h7 += $carry6;
$h6 -= $carry6 << 26;
$carry8 = ($h8 + (1 << 25)) >> 26;
$h9 += $carry8;
$h8 -= $carry8 << 26;
return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
array(
(int) $h0,
(int) $h1,
(int) $h2,
(int) $h3,
(int) $h4,
(int) $h5,
(int) $h6,
(int) $h7,
(int) $h8,
(int) $h9
)
);
}
/**
* Convert a field element to a byte string.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $h
* @return string
*/
public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe $h)
{
$h0 = (int) $h[0];
$h1 = (int) $h[1];
$h2 = (int) $h[2];
$h3 = (int) $h[3];
$h4 = (int) $h[4];
$h5 = (int) $h[5];
$h6 = (int) $h[6];
$h7 = (int) $h[7];
$h8 = (int) $h[8];
$h9 = (int) $h[9];
$q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25;
$q = ($h0 + $q) >> 26;
$q = ($h1 + $q) >> 25;
$q = ($h2 + $q) >> 26;
$q = ($h3 + $q) >> 25;
$q = ($h4 + $q) >> 26;
$q = ($h5 + $q) >> 25;
$q = ($h6 + $q) >> 26;
$q = ($h7 + $q) >> 25;
$q = ($h8 + $q) >> 26;
$q = ($h9 + $q) >> 25;
$h0 += self::mul($q, 19, 5);
$carry0 = $h0 >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
$carry1 = $h1 >> 25;
$h2 += $carry1;
$h1 -= $carry1 << 25;
$carry2 = $h2 >> 26;
$h3 += $carry2;
$h2 -= $carry2 << 26;
$carry3 = $h3 >> 25;
$h4 += $carry3;
$h3 -= $carry3 << 25;
$carry4 = $h4 >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry5 = $h5 >> 25;
$h6 += $carry5;
$h5 -= $carry5 << 25;
$carry6 = $h6 >> 26;
$h7 += $carry6;
$h6 -= $carry6 << 26;
$carry7 = $h7 >> 25;
$h8 += $carry7;
$h7 -= $carry7 << 25;
$carry8 = $h8 >> 26;
$h9 += $carry8;
$h8 -= $carry8 << 26;
$carry9 = $h9 >> 25;
$h9 -= $carry9 << 25;
/**
* @var array<int, int>
*/
$s = array(
(int) (($h0 >> 0) & 0xff),
(int) (($h0 >> 8) & 0xff),
(int) (($h0 >> 16) & 0xff),
(int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
(int) (($h1 >> 6) & 0xff),
(int) (($h1 >> 14) & 0xff),
(int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
(int) (($h2 >> 5) & 0xff),
(int) (($h2 >> 13) & 0xff),
(int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
(int) (($h3 >> 3) & 0xff),
(int) (($h3 >> 11) & 0xff),
(int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
(int) (($h4 >> 2) & 0xff),
(int) (($h4 >> 10) & 0xff),
(int) (($h4 >> 18) & 0xff),
(int) (($h5 >> 0) & 0xff),
(int) (($h5 >> 8) & 0xff),
(int) (($h5 >> 16) & 0xff),
(int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
(int) (($h6 >> 7) & 0xff),
(int) (($h6 >> 15) & 0xff),
(int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
(int) (($h7 >> 5) & 0xff),
(int) (($h7 >> 13) & 0xff),
(int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
(int) (($h8 >> 4) & 0xff),
(int) (($h8 >> 12) & 0xff),
(int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
(int) (($h9 >> 2) & 0xff),
(int) (($h9 >> 10) & 0xff),
(int) (($h9 >> 18) & 0xff)
);
return self::intArrayToString($s);
}
/**
* Is a field element negative? (1 = yes, 0 = no. Used in calculations.)
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return int
* @throws SodiumException
* @throws TypeError
*/
public static function fe_isnegative(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
$str = self::fe_tobytes($f);
return (int) (self::chrToInt($str[0]) & 1);
}
/**
* Returns 0 if this field element results in all NUL bytes.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return bool
* @throws SodiumException
* @throws TypeError
*/
public static function fe_isnonzero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
static $zero;
if ($zero === null) {
$zero = str_repeat("\x00", 32);
}
/** @var string $zero */
/** @var string $str */
$str = self::fe_tobytes($f);
return !self::verify_32($str, (string) $zero);
}
/**
* Multiply two field elements
*
* h = f * g
*
* @internal You should not use this directly from another application
*
* @security Is multiplication a source of timing leaks? If so, can we do
* anything to prevent that from happening?
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core_Curve25519_Fe $g
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_mul(
ParagonIE_Sodium_Core_Curve25519_Fe $f,
ParagonIE_Sodium_Core_Curve25519_Fe $g
) {
// Ensure limbs aren't oversized.
$f = self::fe_normalize($f);
$g = self::fe_normalize($g);
$f0 = $f[0];
$f1 = $f[1];
$f2 = $f[2];
$f3 = $f[3];
$f4 = $f[4];
$f5 = $f[5];
$f6 = $f[6];
$f7 = $f[7];
$f8 = $f[8];
$f9 = $f[9];
$g0 = $g[0];
$g1 = $g[1];
$g2 = $g[2];
$g3 = $g[3];
$g4 = $g[4];
$g5 = $g[5];
$g6 = $g[6];
$g7 = $g[7];
$g8 = $g[8];
$g9 = $g[9];
$g1_19 = self::mul($g1, 19, 5);
$g2_19 = self::mul($g2, 19, 5);
$g3_19 = self::mul($g3, 19, 5);
$g4_19 = self::mul($g4, 19, 5);
$g5_19 = self::mul($g5, 19, 5);
$g6_19 = self::mul($g6, 19, 5);
$g7_19 = self::mul($g7, 19, 5);
$g8_19 = self::mul($g8, 19, 5);
$g9_19 = self::mul($g9, 19, 5);
$f1_2 = $f1 << 1;
$f3_2 = $f3 << 1;
$f5_2 = $f5 << 1;
$f7_2 = $f7 << 1;
$f9_2 = $f9 << 1;
$f0g0 = self::mul($f0, $g0, 26);
$f0g1 = self::mul($f0, $g1, 25);
$f0g2 = self::mul($f0, $g2, 26);
$f0g3 = self::mul($f0, $g3, 25);
$f0g4 = self::mul($f0, $g4, 26);
$f0g5 = self::mul($f0, $g5, 25);
$f0g6 = self::mul($f0, $g6, 26);
$f0g7 = self::mul($f0, $g7, 25);
$f0g8 = self::mul($f0, $g8, 26);
$f0g9 = self::mul($f0, $g9, 26);
$f1g0 = self::mul($f1, $g0, 26);
$f1g1_2 = self::mul($f1_2, $g1, 25);
$f1g2 = self::mul($f1, $g2, 26);
$f1g3_2 = self::mul($f1_2, $g3, 25);
$f1g4 = self::mul($f1, $g4, 26);
$f1g5_2 = self::mul($f1_2, $g5, 25);
$f1g6 = self::mul($f1, $g6, 26);
$f1g7_2 = self::mul($f1_2, $g7, 25);
$f1g8 = self::mul($f1, $g8, 26);
$f1g9_38 = self::mul($g9_19, $f1_2, 26);
$f2g0 = self::mul($f2, $g0, 26);
$f2g1 = self::mul($f2, $g1, 25);
$f2g2 = self::mul($f2, $g2, 26);
$f2g3 = self::mul($f2, $g3, 25);
$f2g4 = self::mul($f2, $g4, 26);
$f2g5 = self::mul($f2, $g5, 25);
$f2g6 = self::mul($f2, $g6, 26);
$f2g7 = self::mul($f2, $g7, 25);
$f2g8_19 = self::mul($g8_19, $f2, 26);
$f2g9_19 = self::mul($g9_19, $f2, 26);
$f3g0 = self::mul($f3, $g0, 26);
$f3g1_2 = self::mul($f3_2, $g1, 25);
$f3g2 = self::mul($f3, $g2, 26);
$f3g3_2 = self::mul($f3_2, $g3, 25);
$f3g4 = self::mul($f3, $g4, 26);
$f3g5_2 = self::mul($f3_2, $g5, 25);
$f3g6 = self::mul($f3, $g6, 26);
$f3g7_38 = self::mul($g7_19, $f3_2, 26);
$f3g8_19 = self::mul($g8_19, $f3, 25);
$f3g9_38 = self::mul($g9_19, $f3_2, 26);
$f4g0 = self::mul($f4, $g0, 26);
$f4g1 = self::mul($f4, $g1, 25);
$f4g2 = self::mul($f4, $g2, 26);
$f4g3 = self::mul($f4, $g3, 25);
$f4g4 = self::mul($f4, $g4, 26);
$f4g5 = self::mul($f4, $g5, 25);
$f4g6_19 = self::mul($g6_19, $f4, 26);
$f4g7_19 = self::mul($g7_19, $f4, 26);
$f4g8_19 = self::mul($g8_19, $f4, 26);
$f4g9_19 = self::mul($g9_19, $f4, 26);
$f5g0 = self::mul($f5, $g0, 26);
$f5g1_2 = self::mul($f5_2, $g1, 25);
$f5g2 = self::mul($f5, $g2, 26);
$f5g3_2 = self::mul($f5_2, $g3, 25);
$f5g4 = self::mul($f5, $g4, 26);
$f5g5_38 = self::mul($g5_19, $f5_2, 26);
$f5g6_19 = self::mul($g6_19, $f5, 25);
$f5g7_38 = self::mul($g7_19, $f5_2, 26);
$f5g8_19 = self::mul($g8_19, $f5, 25);
$f5g9_38 = self::mul($g9_19, $f5_2, 26);
$f6g0 = self::mul($f6, $g0, 26);
$f6g1 = self::mul($f6, $g1, 25);
$f6g2 = self::mul($f6, $g2, 26);
$f6g3 = self::mul($f6, $g3, 25);
$f6g4_19 = self::mul($g4_19, $f6, 26);
$f6g5_19 = self::mul($g5_19, $f6, 26);
$f6g6_19 = self::mul($g6_19, $f6, 26);
$f6g7_19 = self::mul($g7_19, $f6, 26);
$f6g8_19 = self::mul($g8_19, $f6, 26);
$f6g9_19 = self::mul($g9_19, $f6, 26);
$f7g0 = self::mul($f7, $g0, 26);
$f7g1_2 = self::mul($f7_2, $g1, 25);
$f7g2 = self::mul($f7, $g2, 26);
$f7g3_38 = self::mul($g3_19, $f7_2, 26);
$f7g4_19 = self::mul($g4_19, $f7, 26);
$f7g5_38 = self::mul($g5_19, $f7_2, 26);
$f7g6_19 = self::mul($g6_19, $f7, 25);
$f7g7_38 = self::mul($g7_19, $f7_2, 26);
$f7g8_19 = self::mul($g8_19, $f7, 25);
$f7g9_38 = self::mul($g9_19,$f7_2, 26);
$f8g0 = self::mul($f8, $g0, 26);
$f8g1 = self::mul($f8, $g1, 25);
$f8g2_19 = self::mul($g2_19, $f8, 26);
$f8g3_19 = self::mul($g3_19, $f8, 26);
$f8g4_19 = self::mul($g4_19, $f8, 26);
$f8g5_19 = self::mul($g5_19, $f8, 26);
$f8g6_19 = self::mul($g6_19, $f8, 26);
$f8g7_19 = self::mul($g7_19, $f8, 26);
$f8g8_19 = self::mul($g8_19, $f8, 26);
$f8g9_19 = self::mul($g9_19, $f8, 26);
$f9g0 = self::mul($f9, $g0, 26);
$f9g1_38 = self::mul($g1_19, $f9_2, 26);
$f9g2_19 = self::mul($g2_19, $f9, 25);
$f9g3_38 = self::mul($g3_19, $f9_2, 26);
$f9g4_19 = self::mul($g4_19, $f9, 25);
$f9g5_38 = self::mul($g5_19, $f9_2, 26);
$f9g6_19 = self::mul($g6_19, $f9, 25);
$f9g7_38 = self::mul($g7_19, $f9_2, 26);
$f9g8_19 = self::mul($g8_19, $f9, 25);
$f9g9_38 = self::mul($g9_19, $f9_2, 26);
$h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
$h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
$h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
$h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
$h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
$h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
$h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38;
$h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19;
$h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38;
$h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ;
$carry0 = ($h0 + (1 << 25)) >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
$carry4 = ($h4 + (1 << 25)) >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry1 = ($h1 + (1 << 24)) >> 25;
$h2 += $carry1;
$h1 -= $carry1 << 25;
$carry5 = ($h5 + (1 << 24)) >> 25;
$h6 += $carry5;
$h5 -= $carry5 << 25;
$carry2 = ($h2 + (1 << 25)) >> 26;
$h3 += $carry2;
$h2 -= $carry2 << 26;
$carry6 = ($h6 + (1 << 25)) >> 26;
$h7 += $carry6;
$h6 -= $carry6 << 26;
$carry3 = ($h3 + (1 << 24)) >> 25;
$h4 += $carry3;
$h3 -= $carry3 << 25;
$carry7 = ($h7 + (1 << 24)) >> 25;
$h8 += $carry7;
$h7 -= $carry7 << 25;
$carry4 = ($h4 + (1 << 25)) >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry8 = ($h8 + (1 << 25)) >> 26;
$h9 += $carry8;
$h8 -= $carry8 << 26;
$carry9 = ($h9 + (1 << 24)) >> 25;
$h0 += self::mul($carry9, 19, 5);
$h9 -= $carry9 << 25;
$carry0 = ($h0 + (1 << 25)) >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
return self::fe_normalize(
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
array(
(int) $h0,
(int) $h1,
(int) $h2,
(int) $h3,
(int) $h4,
(int) $h5,
(int) $h6,
(int) $h7,
(int) $h8,
(int) $h9
)
)
);
}
/**
* Get the negative values for each piece of the field element.
*
* h = -f
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core_Curve25519_Fe
* @psalm-suppress MixedAssignment
*/
public static function fe_neg(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
$h = new ParagonIE_Sodium_Core_Curve25519_Fe();
for ($i = 0; $i < 10; ++$i) {
$h[$i] = -$f[$i];
}
return self::fe_normalize($h);
}
/**
* Square a field element
*
* h = f * f
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
$f = self::fe_normalize($f);
$f0 = (int) $f[0];
$f1 = (int) $f[1];
$f2 = (int) $f[2];
$f3 = (int) $f[3];
$f4 = (int) $f[4];
$f5 = (int) $f[5];
$f6 = (int) $f[6];
$f7 = (int) $f[7];
$f8 = (int) $f[8];
$f9 = (int) $f[9];
$f0_2 = $f0 << 1;
$f1_2 = $f1 << 1;
$f2_2 = $f2 << 1;
$f3_2 = $f3 << 1;
$f4_2 = $f4 << 1;
$f5_2 = $f5 << 1;
$f6_2 = $f6 << 1;
$f7_2 = $f7 << 1;
$f5_38 = self::mul($f5, 38, 6);
$f6_19 = self::mul($f6, 19, 5);
$f7_38 = self::mul($f7, 38, 6);
$f8_19 = self::mul($f8, 19, 5);
$f9_38 = self::mul($f9, 38, 6);
$f0f0 = self::mul($f0, $f0, 26);
$f0f1_2 = self::mul($f0_2, $f1, 26);
$f0f2_2 = self::mul($f0_2, $f2, 26);
$f0f3_2 = self::mul($f0_2, $f3, 26);
$f0f4_2 = self::mul($f0_2, $f4, 26);
$f0f5_2 = self::mul($f0_2, $f5, 26);
$f0f6_2 = self::mul($f0_2, $f6, 26);
$f0f7_2 = self::mul($f0_2, $f7, 26);
$f0f8_2 = self::mul($f0_2, $f8, 26);
$f0f9_2 = self::mul($f0_2, $f9, 26);
$f1f1_2 = self::mul($f1_2, $f1, 26);
$f1f2_2 = self::mul($f1_2, $f2, 26);
$f1f3_4 = self::mul($f1_2, $f3_2, 26);
$f1f4_2 = self::mul($f1_2, $f4, 26);
$f1f5_4 = self::mul($f1_2, $f5_2, 26);
$f1f6_2 = self::mul($f1_2, $f6, 26);
$f1f7_4 = self::mul($f1_2, $f7_2, 26);
$f1f8_2 = self::mul($f1_2, $f8, 26);
$f1f9_76 = self::mul($f9_38, $f1_2, 27);
$f2f2 = self::mul($f2, $f2, 27);
$f2f3_2 = self::mul($f2_2, $f3, 27);
$f2f4_2 = self::mul($f2_2, $f4, 27);
$f2f5_2 = self::mul($f2_2, $f5, 27);
$f2f6_2 = self::mul($f2_2, $f6, 27);
$f2f7_2 = self::mul($f2_2, $f7, 27);
$f2f8_38 = self::mul($f8_19, $f2_2, 27);
$f2f9_38 = self::mul($f9_38, $f2, 26);
$f3f3_2 = self::mul($f3_2, $f3, 26);
$f3f4_2 = self::mul($f3_2, $f4, 26);
$f3f5_4 = self::mul($f3_2, $f5_2, 26);
$f3f6_2 = self::mul($f3_2, $f6, 26);
$f3f7_76 = self::mul($f7_38, $f3_2, 26);
$f3f8_38 = self::mul($f8_19, $f3_2, 26);
$f3f9_76 = self::mul($f9_38, $f3_2, 26);
$f4f4 = self::mul($f4, $f4, 26);
$f4f5_2 = self::mul($f4_2, $f5, 26);
$f4f6_38 = self::mul($f6_19, $f4_2, 27);
$f4f7_38 = self::mul($f7_38, $f4, 26);
$f4f8_38 = self::mul($f8_19, $f4_2, 27);
$f4f9_38 = self::mul($f9_38, $f4, 26);
$f5f5_38 = self::mul($f5_38, $f5, 26);
$f5f6_38 = self::mul($f6_19, $f5_2, 26);
$f5f7_76 = self::mul($f7_38, $f5_2, 26);
$f5f8_38 = self::mul($f8_19, $f5_2, 26);
$f5f9_76 = self::mul($f9_38, $f5_2, 26);
$f6f6_19 = self::mul($f6_19, $f6, 26);
$f6f7_38 = self::mul($f7_38, $f6, 26);
$f6f8_38 = self::mul($f8_19, $f6_2, 27);
$f6f9_38 = self::mul($f9_38, $f6, 26);
$f7f7_38 = self::mul($f7_38, $f7, 26);
$f7f8_38 = self::mul($f8_19, $f7_2, 26);
$f7f9_76 = self::mul($f9_38, $f7_2, 26);
$f8f8_19 = self::mul($f8_19, $f8, 26);
$f8f9_38 = self::mul($f9_38, $f8, 26);
$f9f9_38 = self::mul($f9_38, $f9, 26);
$h0 = $f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38;
$h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38;
$h2 = $f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19;
$h3 = $f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38;
$h4 = $f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38;
$h5 = $f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38;
$h6 = $f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19;
$h7 = $f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38;
$h8 = $f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38;
$h9 = $f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2;
$carry0 = ($h0 + (1 << 25)) >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
$carry4 = ($h4 + (1 << 25)) >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry1 = ($h1 + (1 << 24)) >> 25;
$h2 += $carry1;
$h1 -= $carry1 << 25;
$carry5 = ($h5 + (1 << 24)) >> 25;
$h6 += $carry5;
$h5 -= $carry5 << 25;
$carry2 = ($h2 + (1 << 25)) >> 26;
$h3 += $carry2;
$h2 -= $carry2 << 26;
$carry6 = ($h6 + (1 << 25)) >> 26;
$h7 += $carry6;
$h6 -= $carry6 << 26;
$carry3 = ($h3 + (1 << 24)) >> 25;
$h4 += $carry3;
$h3 -= $carry3 << 25;
$carry7 = ($h7 + (1 << 24)) >> 25;
$h8 += $carry7;
$h7 -= $carry7 << 25;
$carry4 = ($h4 + (1 << 25)) >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry8 = ($h8 + (1 << 25)) >> 26;
$h9 += $carry8;
$h8 -= $carry8 << 26;
$carry9 = ($h9 + (1 << 24)) >> 25;
$h0 += self::mul($carry9, 19, 5);
$h9 -= $carry9 << 25;
$carry0 = ($h0 + (1 << 25)) >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
return self::fe_normalize(
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
array(
(int) $h0,
(int) $h1,
(int) $h2,
(int) $h3,
(int) $h4,
(int) $h5,
(int) $h6,
(int) $h7,
(int) $h8,
(int) $h9
)
)
);
}
/**
* Square and double a field element
*
* h = 2 * f * f
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
$f = self::fe_normalize($f);
$f0 = (int) $f[0];
$f1 = (int) $f[1];
$f2 = (int) $f[2];
$f3 = (int) $f[3];
$f4 = (int) $f[4];
$f5 = (int) $f[5];
$f6 = (int) $f[6];
$f7 = (int) $f[7];
$f8 = (int) $f[8];
$f9 = (int) $f[9];
$f0_2 = $f0 << 1;
$f1_2 = $f1 << 1;
$f2_2 = $f2 << 1;
$f3_2 = $f3 << 1;
$f4_2 = $f4 << 1;
$f5_2 = $f5 << 1;
$f6_2 = $f6 << 1;
$f7_2 = $f7 << 1;
$f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */
$f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */
$f7_38 = self::mul($f7, 38, 6); /* 1.959375*2^30 */
$f8_19 = self::mul($f8, 19, 5); /* 1.959375*2^30 */
$f9_38 = self::mul($f9, 38, 6); /* 1.959375*2^30 */
$f0f0 = self::mul($f0, $f0, 24);
$f0f1_2 = self::mul($f0_2, $f1, 24);
$f0f2_2 = self::mul($f0_2, $f2, 24);
$f0f3_2 = self::mul($f0_2, $f3, 24);
$f0f4_2 = self::mul($f0_2, $f4, 24);
$f0f5_2 = self::mul($f0_2, $f5, 24);
$f0f6_2 = self::mul($f0_2, $f6, 24);
$f0f7_2 = self::mul($f0_2, $f7, 24);
$f0f8_2 = self::mul($f0_2, $f8, 24);
$f0f9_2 = self::mul($f0_2, $f9, 24);
$f1f1_2 = self::mul($f1_2, $f1, 24);
$f1f2_2 = self::mul($f1_2, $f2, 24);
$f1f3_4 = self::mul($f1_2, $f3_2, 24);
$f1f4_2 = self::mul($f1_2, $f4, 24);
$f1f5_4 = self::mul($f1_2, $f5_2, 24);
$f1f6_2 = self::mul($f1_2, $f6, 24);
$f1f7_4 = self::mul($f1_2, $f7_2, 24);
$f1f8_2 = self::mul($f1_2, $f8, 24);
$f1f9_76 = self::mul($f9_38, $f1_2, 24);
$f2f2 = self::mul($f2, $f2, 24);
$f2f3_2 = self::mul($f2_2, $f3, 24);
$f2f4_2 = self::mul($f2_2, $f4, 24);
$f2f5_2 = self::mul($f2_2, $f5, 24);
$f2f6_2 = self::mul($f2_2, $f6, 24);
$f2f7_2 = self::mul($f2_2, $f7, 24);
$f2f8_38 = self::mul($f8_19, $f2_2, 25);
$f2f9_38 = self::mul($f9_38, $f2, 24);
$f3f3_2 = self::mul($f3_2, $f3, 24);
$f3f4_2 = self::mul($f3_2, $f4, 24);
$f3f5_4 = self::mul($f3_2, $f5_2, 24);
$f3f6_2 = self::mul($f3_2, $f6, 24);
$f3f7_76 = self::mul($f7_38, $f3_2, 24);
$f3f8_38 = self::mul($f8_19, $f3_2, 24);
$f3f9_76 = self::mul($f9_38, $f3_2, 24);
$f4f4 = self::mul($f4, $f4, 24);
$f4f5_2 = self::mul($f4_2, $f5, 24);
$f4f6_38 = self::mul($f6_19, $f4_2, 25);
$f4f7_38 = self::mul($f7_38, $f4, 24);
$f4f8_38 = self::mul($f8_19, $f4_2, 25);
$f4f9_38 = self::mul($f9_38, $f4, 24);
$f5f5_38 = self::mul($f5_38, $f5, 24);
$f5f6_38 = self::mul($f6_19, $f5_2, 24);
$f5f7_76 = self::mul($f7_38, $f5_2, 24);
$f5f8_38 = self::mul($f8_19, $f5_2, 24);
$f5f9_76 = self::mul($f9_38, $f5_2, 24);
$f6f6_19 = self::mul($f6_19, $f6, 24);
$f6f7_38 = self::mul($f7_38, $f6, 24);
$f6f8_38 = self::mul($f8_19, $f6_2, 25);
$f6f9_38 = self::mul($f9_38, $f6, 24);
$f7f7_38 = self::mul($f7_38, $f7, 24);
$f7f8_38 = self::mul($f8_19, $f7_2, 24);
$f7f9_76 = self::mul($f9_38, $f7_2, 24);
$f8f8_19 = self::mul($f8_19, $f8, 24);
$f8f9_38 = self::mul($f9_38, $f8, 24);
$f9f9_38 = self::mul($f9_38, $f9, 24);
$h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38) << 1;
$h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38) << 1;
$h2 = (int) ($f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19) << 1;
$h3 = (int) ($f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38) << 1;
$h4 = (int) ($f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38) << 1;
$h5 = (int) ($f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38) << 1;
$h6 = (int) ($f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19) << 1;
$h7 = (int) ($f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38) << 1;
$h8 = (int) ($f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38) << 1;
$h9 = (int) ($f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2) << 1;
$carry0 = ($h0 + (1 << 25)) >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
$carry4 = ($h4 + (1 << 25)) >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry1 = ($h1 + (1 << 24)) >> 25;
$h2 += $carry1;
$h1 -= $carry1 << 25;
$carry5 = ($h5 + (1 << 24)) >> 25;
$h6 += $carry5;
$h5 -= $carry5 << 25;
$carry2 = ($h2 + (1 << 25)) >> 26;
$h3 += $carry2;
$h2 -= $carry2 << 26;
$carry6 = ($h6 + (1 << 25)) >> 26;
$h7 += $carry6;
$h6 -= $carry6 << 26;
$carry3 = ($h3 + (1 << 24)) >> 25;
$h4 += $carry3;
$h3 -= $carry3 << 25;
$carry7 = ($h7 + (1 << 24)) >> 25;
$h8 += $carry7;
$h7 -= $carry7 << 25;
$carry4 = ($h4 + (1 << 25)) >> 26;
$h5 += $carry4;
$h4 -= $carry4 << 26;
$carry8 = ($h8 + (1 << 25)) >> 26;
$h9 += $carry8;
$h8 -= $carry8 << 26;
$carry9 = ($h9 + (1 << 24)) >> 25;
$h0 += self::mul($carry9, 19, 5);
$h9 -= $carry9 << 25;
$carry0 = ($h0 + (1 << 25)) >> 26;
$h1 += $carry0;
$h0 -= $carry0 << 26;
return self::fe_normalize(
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
array(
(int) $h0,
(int) $h1,
(int) $h2,
(int) $h3,
(int) $h4,
(int) $h5,
(int) $h6,
(int) $h7,
(int) $h8,
(int) $h9
)
)
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $Z
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_invert(ParagonIE_Sodium_Core_Curve25519_Fe $Z)
{
$z = clone $Z;
$t0 = self::fe_sq($z);
$t1 = self::fe_sq($t0);
$t1 = self::fe_sq($t1);
$t1 = self::fe_mul($z, $t1);
$t0 = self::fe_mul($t0, $t1);
$t2 = self::fe_sq($t0);
$t1 = self::fe_mul($t1, $t2);
$t2 = self::fe_sq($t1);
for ($i = 1; $i < 5; ++$i) {
$t2 = self::fe_sq($t2);
}
$t1 = self::fe_mul($t2, $t1);
$t2 = self::fe_sq($t1);
for ($i = 1; $i < 10; ++$i) {
$t2 = self::fe_sq($t2);
}
$t2 = self::fe_mul($t2, $t1);
$t3 = self::fe_sq($t2);
for ($i = 1; $i < 20; ++$i) {
$t3 = self::fe_sq($t3);
}
$t2 = self::fe_mul($t3, $t2);
$t2 = self::fe_sq($t2);
for ($i = 1; $i < 10; ++$i) {
$t2 = self::fe_sq($t2);
}
$t1 = self::fe_mul($t2, $t1);
$t2 = self::fe_sq($t1);
for ($i = 1; $i < 50; ++$i) {
$t2 = self::fe_sq($t2);
}
$t2 = self::fe_mul($t2, $t1);
$t3 = self::fe_sq($t2);
for ($i = 1; $i < 100; ++$i) {
$t3 = self::fe_sq($t3);
}
$t2 = self::fe_mul($t3, $t2);
$t2 = self::fe_sq($t2);
for ($i = 1; $i < 50; ++$i) {
$t2 = self::fe_sq($t2);
}
$t1 = self::fe_mul($t2, $t1);
$t1 = self::fe_sq($t1);
for ($i = 1; $i < 5; ++$i) {
$t1 = self::fe_sq($t1);
}
return self::fe_mul($t1, $t0);
}
/**
* @internal You should not use this directly from another application
*
* @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $z
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_pow22523(ParagonIE_Sodium_Core_Curve25519_Fe $z)
{
$z = self::fe_normalize($z);
# fe_sq(t0, z);
# fe_sq(t1, t0);
# fe_sq(t1, t1);
# fe_mul(t1, z, t1);
# fe_mul(t0, t0, t1);
# fe_sq(t0, t0);
# fe_mul(t0, t1, t0);
# fe_sq(t1, t0);
$t0 = self::fe_sq($z);
$t1 = self::fe_sq($t0);
$t1 = self::fe_sq($t1);
$t1 = self::fe_mul($z, $t1);
$t0 = self::fe_mul($t0, $t1);
$t0 = self::fe_sq($t0);
$t0 = self::fe_mul($t1, $t0);
$t1 = self::fe_sq($t0);
# for (i = 1; i < 5; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 5; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t0, t1, t0);
# fe_sq(t1, t0);
$t0 = self::fe_mul($t1, $t0);
$t1 = self::fe_sq($t0);
# for (i = 1; i < 10; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 10; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t1, t1, t0);
# fe_sq(t2, t1);
$t1 = self::fe_mul($t1, $t0);
$t2 = self::fe_sq($t1);
# for (i = 1; i < 20; ++i) {
# fe_sq(t2, t2);
# }
for ($i = 1; $i < 20; ++$i) {
$t2 = self::fe_sq($t2);
}
# fe_mul(t1, t2, t1);
# fe_sq(t1, t1);
$t1 = self::fe_mul($t2, $t1);
$t1 = self::fe_sq($t1);
# for (i = 1; i < 10; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 10; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t0, t1, t0);
# fe_sq(t1, t0);
$t0 = self::fe_mul($t1, $t0);
$t1 = self::fe_sq($t0);
# for (i = 1; i < 50; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 50; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t1, t1, t0);
# fe_sq(t2, t1);
$t1 = self::fe_mul($t1, $t0);
$t2 = self::fe_sq($t1);
# for (i = 1; i < 100; ++i) {
# fe_sq(t2, t2);
# }
for ($i = 1; $i < 100; ++$i) {
$t2 = self::fe_sq($t2);
}
# fe_mul(t1, t2, t1);
# fe_sq(t1, t1);
$t1 = self::fe_mul($t2, $t1);
$t1 = self::fe_sq($t1);
# for (i = 1; i < 50; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 50; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t0, t1, t0);
# fe_sq(t0, t0);
# fe_sq(t0, t0);
# fe_mul(out, t0, z);
$t0 = self::fe_mul($t1, $t0);
$t0 = self::fe_sq($t0);
$t0 = self::fe_sq($t0);
return self::fe_mul($t0, $z);
}
/**
* Subtract two field elements.
*
* h = f - g
*
* Preconditions:
* |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*
* Postconditions:
* |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core_Curve25519_Fe $g
* @return ParagonIE_Sodium_Core_Curve25519_Fe
* @psalm-suppress MixedOperand
*/
public static function fe_sub(ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g)
{
return self::fe_normalize(
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
array(
(int) ($f[0] - $g[0]),
(int) ($f[1] - $g[1]),
(int) ($f[2] - $g[2]),
(int) ($f[3] - $g[3]),
(int) ($f[4] - $g[4]),
(int) ($f[5] - $g[5]),
(int) ($f[6] - $g[6]),
(int) ($f[7] - $g[7]),
(int) ($f[8] - $g[8]),
(int) ($f[9] - $g[9])
)
)
);
}
/**
* Add two group elements.
*
* r = p + q
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
*/
public static function ge_add(
ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
) {
$r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->YplusX);
$r->Y = self::fe_mul($r->Y, $q->YminusX);
$r->T = self::fe_mul($q->T2d, $p->T);
$r->X = self::fe_mul($p->Z, $q->Z);
$t0 = self::fe_add($r->X, $r->X);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_add($t0, $r->T);
$r->T = self::fe_sub($t0, $r->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
* @param string $a
* @return array<int, mixed>
* @throws SodiumException
* @throws TypeError
*/
public static function slide($a)
{
if (self::strlen($a) < 256) {
if (self::strlen($a) < 16) {
$a = str_pad($a, 256, '0', STR_PAD_RIGHT);
}
}
/** @var array<int, int> $r */
$r = array();
/** @var int $i */
for ($i = 0; $i < 256; ++$i) {
$r[$i] = (int) (
1 & (
self::chrToInt($a[(int) ($i >> 3)])
>>
($i & 7)
)
);
}
for ($i = 0;$i < 256;++$i) {
if ($r[$i]) {
for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
if ($r[$i + $b]) {
if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
$r[$i] += $r[$i + $b] << $b;
$r[$i + $b] = 0;
} elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) {
$r[$i] -= $r[$i + $b] << $b;
for ($k = $i + $b; $k < 256; ++$k) {
if (!$r[$k]) {
$r[$k] = 1;
break;
}
$r[$k] = 0;
}
} else {
break;
}
}
}
}
}
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param string $s
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
* @throws SodiumException
* @throws TypeError
*/
public static function ge_frombytes_negate_vartime($s)
{
static $d = null;
if (!$d) {
$d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
}
# fe_frombytes(h->Y,s);
# fe_1(h->Z);
$h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
self::fe_0(),
self::fe_frombytes($s),
self::fe_1()
);
# fe_sq(u,h->Y);
# fe_mul(v,u,d);
# fe_sub(u,u,h->Z); /* u = y^2-1 */
# fe_add(v,v,h->Z); /* v = dy^2+1 */
$u = self::fe_sq($h->Y);
/** @var ParagonIE_Sodium_Core_Curve25519_Fe $d */
$v = self::fe_mul($u, $d);
$u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */
$v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */
# fe_sq(v3,v);
# fe_mul(v3,v3,v); /* v3 = v^3 */
# fe_sq(h->X,v3);
# fe_mul(h->X,h->X,v);
# fe_mul(h->X,h->X,u); /* x = uv^7 */
$v3 = self::fe_sq($v);
$v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
$h->X = self::fe_sq($v3);
$h->X = self::fe_mul($h->X, $v);
$h->X = self::fe_mul($h->X, $u); /* x = uv^7 */
# fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
# fe_mul(h->X,h->X,v3);
# fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
$h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
$h->X = self::fe_mul($h->X, $v3);
$h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */
# fe_sq(vxx,h->X);
# fe_mul(vxx,vxx,v);
# fe_sub(check,vxx,u); /* vx^2-u */
$vxx = self::fe_sq($h->X);
$vxx = self::fe_mul($vxx, $v);
$check = self::fe_sub($vxx, $u); /* vx^2 - u */
# if (fe_isnonzero(check)) {
# fe_add(check,vxx,u); /* vx^2+u */
# if (fe_isnonzero(check)) {
# return -1;
# }
# fe_mul(h->X,h->X,sqrtm1);
# }
if (self::fe_isnonzero($check)) {
$check = self::fe_add($vxx, $u); /* vx^2 + u */
if (self::fe_isnonzero($check)) {
throw new RangeException('Internal check failed.');
}
$h->X = self::fe_mul(
$h->X,
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1)
);
}
# if (fe_isnegative(h->X) == (s[31] >> 7)) {
# fe_neg(h->X,h->X);
# }
$i = self::chrToInt($s[31]);
if (self::fe_isnegative($h->X) === ($i >> 7)) {
$h->X = self::fe_neg($h->X);
}
# fe_mul(h->T,h->X,h->Y);
$h->T = self::fe_mul($h->X, $h->Y);
return $h;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
*/
public static function ge_madd(
ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
) {
$r = clone $R;
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->yplusx);
$r->Y = self::fe_mul($r->Y, $q->yminusx);
$r->T = self::fe_mul($q->xy2d, $p->T);
$t0 = self::fe_add(clone $p->Z, clone $p->Z);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_add($t0, $r->T);
$r->T = self::fe_sub($t0, $r->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
*/
public static function ge_msub(
ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
) {
$r = clone $R;
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->yminusx);
$r->Y = self::fe_mul($r->Y, $q->yplusx);
$r->T = self::fe_mul($q->xy2d, $p->T);
$t0 = self::fe_add($p->Z, $p->Z);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_sub($t0, $r->T);
$r->T = self::fe_add($t0, $r->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
*/
public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p)
{
$r = new ParagonIE_Sodium_Core_Curve25519_Ge_P2();
$r->X = self::fe_mul($p->X, $p->T);
$r->Y = self::fe_mul($p->Y, $p->Z);
$r->Z = self::fe_mul($p->Z, $p->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
*/
public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p)
{
$r = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();
$r->X = self::fe_mul($p->X, $p->T);
$r->Y = self::fe_mul($p->Y, $p->Z);
$r->Z = self::fe_mul($p->Z, $p->T);
$r->T = self::fe_mul($p->X, $p->Y);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
*/
public static function ge_p2_0()
{
return new ParagonIE_Sodium_Core_Curve25519_Ge_P2(
self::fe_0(),
self::fe_1(),
self::fe_1()
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
*/
public static function ge_p2_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p)
{
$r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
$r->X = self::fe_sq($p->X);
$r->Z = self::fe_sq($p->Y);
$r->T = self::fe_sq2($p->Z);
$r->Y = self::fe_add($p->X, $p->Y);
$t0 = self::fe_sq($r->Y);
$r->Y = self::fe_add($r->Z, $r->X);
$r->Z = self::fe_sub($r->Z, $r->X);
$r->X = self::fe_sub($t0, $r->Y);
$r->T = self::fe_sub($r->T, $r->Z);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
*/
public static function ge_p3_0()
{
return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
self::fe_0(),
self::fe_1(),
self::fe_1(),
self::fe_0()
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached
*/
public static function ge_p3_to_cached(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
{
static $d2 = null;
if ($d2 === null) {
$d2 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d2);
}
/** @var ParagonIE_Sodium_Core_Curve25519_Fe $d2 */
$r = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached();
$r->YplusX = self::fe_add($p->Y, $p->X);
$r->YminusX = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_copy($p->Z);
$r->T2d = self::fe_mul($p->T, $d2);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
*/
public static function ge_p3_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
{
return new ParagonIE_Sodium_Core_Curve25519_Ge_P2(
self::fe_copy($p->X),
self::fe_copy($p->Y),
self::fe_copy($p->Z)
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
{
$recip = self::fe_invert($h->Z);
$x = self::fe_mul($h->X, $recip);
$y = self::fe_mul($h->Y, $recip);
$s = self::fe_tobytes($y);
$s[31] = self::intToChr(
self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
);
return $s;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
*/
public static function ge_p3_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
{
$q = self::ge_p3_to_p2($p);
return self::ge_p2_dbl($q);
}
/**
* @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
*/
public static function ge_precomp_0()
{
return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
self::fe_1(),
self::fe_1(),
self::fe_0()
);
}
/**
* @internal You should not use this directly from another application
*
* @param int $b
* @param int $c
* @return int
*/
public static function equal($b, $c)
{
return (int) ((($b ^ $c) - 1) >> 31) & 1;
}
/**
* @internal You should not use this directly from another application
*
* @param int|string $char
* @return int (1 = yes, 0 = no)
* @throws SodiumException
* @throws TypeError
*/
public static function negative($char)
{
if (is_int($char)) {
return ($char >> 63) & 1;
}
$x = self::chrToInt(self::substr($char, 0, 1));
return (int) ($x >> 63);
}
/**
* Conditional move
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u
* @param int $b
* @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
*/
public static function cmov(
ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t,
ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u,
$b
) {
if (!is_int($b)) {
throw new InvalidArgumentException('Expected an integer.');
}
return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
self::fe_cmov($t->yplusx, $u->yplusx, $b),
self::fe_cmov($t->yminusx, $u->yminusx, $b),
self::fe_cmov($t->xy2d, $u->xy2d, $b)
);
}
/**
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u
* @param int $b
* @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached
*/
public static function ge_cmov_cached(
ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t,
ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u,
$b
) {
$b &= 1;
$ret = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached();
$ret->YplusX = self::fe_cmov($t->YplusX, $u->YplusX, $b);
$ret->YminusX = self::fe_cmov($t->YminusX, $u->YminusX, $b);
$ret->Z = self::fe_cmov($t->Z, $u->Z, $b);
$ret->T2d = self::fe_cmov($t->T2d, $u->T2d, $b);
return $ret;
}
/**
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $cached
* @param int $b
* @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached
* @throws SodiumException
*/
public static function ge_cmov8_cached(array $cached, $b)
{
// const unsigned char bnegative = negative(b);
// const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1));
$bnegative = self::negative($b);
$babs = $b - (((-$bnegative) & $b) << 1);
// ge25519_cached_0(t);
$t = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(
self::fe_1(),
self::fe_1(),
self::fe_1(),
self::fe_0()
);
// ge25519_cmov_cached(t, &cached[0], equal(babs, 1));
// ge25519_cmov_cached(t, &cached[1], equal(babs, 2));
// ge25519_cmov_cached(t, &cached[2], equal(babs, 3));
// ge25519_cmov_cached(t, &cached[3], equal(babs, 4));
// ge25519_cmov_cached(t, &cached[4], equal(babs, 5));
// ge25519_cmov_cached(t, &cached[5], equal(babs, 6));
// ge25519_cmov_cached(t, &cached[6], equal(babs, 7));
// ge25519_cmov_cached(t, &cached[7], equal(babs, 8));
for ($x = 0; $x < 8; ++$x) {
$t = self::ge_cmov_cached($t, $cached[$x], self::equal($babs, $x + 1));
}
// fe25519_copy(minust.YplusX, t->YminusX);
// fe25519_copy(minust.YminusX, t->YplusX);
// fe25519_copy(minust.Z, t->Z);
// fe25519_neg(minust.T2d, t->T2d);
$minust = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(
self::fe_copy($t->YminusX),
self::fe_copy($t->YplusX),
self::fe_copy($t->Z),
self::fe_neg($t->T2d)
);
return self::ge_cmov_cached($t, $minust, $bnegative);
}
/**
* @internal You should not use this directly from another application
*
* @param int $pos
* @param int $b
* @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayOffset
*/
public static function ge_select($pos = 0, $b = 0)
{
static $base = null;
if ($base === null) {
$base = array();
/** @var int $i */
foreach (self::$base as $i => $bas) {
for ($j = 0; $j < 8; ++$j) {
$base[$i][$j] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][0]),
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][1]),
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][2])
);
}
}
}
/** @var array<int, array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp>> $base */
if (!is_int($pos)) {
throw new InvalidArgumentException('Position must be an integer');
}
if ($pos < 0 || $pos > 31) {
throw new RangeException('Position is out of range [0, 31]');
}
$bnegative = self::negative($b);
$babs = $b - (((-$bnegative) & $b) << 1);
$t = self::ge_precomp_0();
for ($i = 0; $i < 8; ++$i) {
$t = self::cmov(
$t,
$base[$pos][$i],
self::equal($babs, $i + 1)
);
}
$minusT = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
self::fe_copy($t->yminusx),
self::fe_copy($t->yplusx),
self::fe_neg($t->xy2d)
);
return self::cmov($t, $minusT, $bnegative);
}
/**
* Subtract two group elements.
*
* r = p - q
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
*/
public static function ge_sub(
ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
) {
$r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->YminusX);
$r->Y = self::fe_mul($r->Y, $q->YplusX);
$r->T = self::fe_mul($q->T2d, $p->T);
$r->X = self::fe_mul($p->Z, $q->Z);
$t0 = self::fe_add($r->X, $r->X);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_sub($t0, $r->T);
$r->T = self::fe_add($t0, $r->T);
return $r;
}
/**
* Convert a group element to a byte string.
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function ge_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h)
{
$recip = self::fe_invert($h->Z);
$x = self::fe_mul($h->X, $recip);
$y = self::fe_mul($h->Y, $recip);
$s = self::fe_tobytes($y);
$s[31] = self::intToChr(
self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
);
return $s;
}
/**
* @internal You should not use this directly from another application
*
* @param string $a
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A
* @param string $b
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedArrayAccess
*/
public static function ge_double_scalarmult_vartime(
$a,
ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A,
$b
) {
/** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai */
$Ai = array();
/** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp> $Bi */
static $Bi = array();
if (!$Bi) {
for ($i = 0; $i < 8; ++$i) {
$Bi[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][0]),
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][1]),
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][2])
);
}
}
for ($i = 0; $i < 8; ++$i) {
$Ai[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(
self::fe_0(),
self::fe_0(),
self::fe_0(),
self::fe_0()
);
}
# slide(aslide,a);
# slide(bslide,b);
/** @var array<int, int> $aslide */
$aslide = self::slide($a);
/** @var array<int, int> $bslide */
$bslide = self::slide($b);
# ge_p3_to_cached(&Ai[0],A);
# ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
$Ai[0] = self::ge_p3_to_cached($A);
$t = self::ge_p3_dbl($A);
$A2 = self::ge_p1p1_to_p3($t);
# ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
# ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
# ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
# ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
# ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
# ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
# ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
for ($i = 0; $i < 7; ++$i) {
$t = self::ge_add($A2, $Ai[$i]);
$u = self::ge_p1p1_to_p3($t);
$Ai[$i + 1] = self::ge_p3_to_cached($u);
}
# ge_p2_0(r);
$r = self::ge_p2_0();
# for (i = 255;i >= 0;--i) {
# if (aslide[i] || bslide[i]) break;
# }
$i = 255;
for (; $i >= 0; --$i) {
if ($aslide[$i] || $bslide[$i]) {
break;
}
}
# for (;i >= 0;--i) {
for (; $i >= 0; --$i) {
# ge_p2_dbl(&t,r);
$t = self::ge_p2_dbl($r);
# if (aslide[i] > 0) {
if ($aslide[$i] > 0) {
# ge_p1p1_to_p3(&u,&t);
# ge_add(&t,&u,&Ai[aslide[i]/2]);
$u = self::ge_p1p1_to_p3($t);
$t = self::ge_add(
$u,
$Ai[(int) floor($aslide[$i] / 2)]
);
# } else if (aslide[i] < 0) {
} elseif ($aslide[$i] < 0) {
# ge_p1p1_to_p3(&u,&t);
# ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
$u = self::ge_p1p1_to_p3($t);
$t = self::ge_sub(
$u,
$Ai[(int) floor(-$aslide[$i] / 2)]
);
}
# if (bslide[i] > 0) {
if ($bslide[$i] > 0) {
/** @var int $index */
$index = (int) floor($bslide[$i] / 2);
# ge_p1p1_to_p3(&u,&t);
# ge_madd(&t,&u,&Bi[bslide[i]/2]);
$u = self::ge_p1p1_to_p3($t);
$t = self::ge_madd($t, $u, $Bi[$index]);
# } else if (bslide[i] < 0) {
} elseif ($bslide[$i] < 0) {
/** @var int $index */
$index = (int) floor(-$bslide[$i] / 2);
# ge_p1p1_to_p3(&u,&t);
# ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
$u = self::ge_p1p1_to_p3($t);
$t = self::ge_msub($t, $u, $Bi[$index]);
}
# ge_p1p1_to_p2(r,&t);
$r = self::ge_p1p1_to_p2($t);
}
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param string $a
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedOperand
*/
public static function ge_scalarmult($a, $p)
{
$e = array_fill(0, 64, 0);
/** @var ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $pi */
$pi = array();
// ge25519_p3_to_cached(&pi[1 - 1], p); /* p */
$pi[0] = self::ge_p3_to_cached($p);
// ge25519_p3_dbl(&t2, p);
// ge25519_p1p1_to_p3(&p2, &t2);
// ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */
$t2 = self::ge_p3_dbl($p);
$p2 = self::ge_p1p1_to_p3($t2);
$pi[1] = self::ge_p3_to_cached($p2);
// ge25519_add_cached(&t3, p, &pi[2 - 1]);
// ge25519_p1p1_to_p3(&p3, &t3);
// ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */
$t3 = self::ge_add($p, $pi[1]);
$p3 = self::ge_p1p1_to_p3($t3);
$pi[2] = self::ge_p3_to_cached($p3);
// ge25519_p3_dbl(&t4, &p2);
// ge25519_p1p1_to_p3(&p4, &t4);
// ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */
$t4 = self::ge_p3_dbl($p2);
$p4 = self::ge_p1p1_to_p3($t4);
$pi[3] = self::ge_p3_to_cached($p4);
// ge25519_add_cached(&t5, p, &pi[4 - 1]);
// ge25519_p1p1_to_p3(&p5, &t5);
// ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */
$t5 = self::ge_add($p, $pi[3]);
$p5 = self::ge_p1p1_to_p3($t5);
$pi[4] = self::ge_p3_to_cached($p5);
// ge25519_p3_dbl(&t6, &p3);
// ge25519_p1p1_to_p3(&p6, &t6);
// ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */
$t6 = self::ge_p3_dbl($p3);
$p6 = self::ge_p1p1_to_p3($t6);
$pi[5] = self::ge_p3_to_cached($p6);
// ge25519_add_cached(&t7, p, &pi[6 - 1]);
// ge25519_p1p1_to_p3(&p7, &t7);
// ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */
$t7 = self::ge_add($p, $pi[5]);
$p7 = self::ge_p1p1_to_p3($t7);
$pi[6] = self::ge_p3_to_cached($p7);
// ge25519_p3_dbl(&t8, &p4);
// ge25519_p1p1_to_p3(&p8, &t8);
// ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */
$t8 = self::ge_p3_dbl($p4);
$p8 = self::ge_p1p1_to_p3($t8);
$pi[7] = self::ge_p3_to_cached($p8);
// for (i = 0; i < 32; ++i) {
// e[2 * i + 0] = (a[i] >> 0) & 15;
// e[2 * i + 1] = (a[i] >> 4) & 15;
// }
for ($i = 0; $i < 32; ++$i) {
$e[($i << 1) ] = self::chrToInt($a[$i]) & 15;
$e[($i << 1) + 1] = (self::chrToInt($a[$i]) >> 4) & 15;
}
// /* each e[i] is between 0 and 15 */
// /* e[63] is between 0 and 7 */
// carry = 0;
// for (i = 0; i < 63; ++i) {
// e[i] += carry;
// carry = e[i] + 8;
// carry >>= 4;
// e[i] -= carry * ((signed char) 1 << 4);
// }
$carry = 0;
for ($i = 0; $i < 63; ++$i) {
$e[$i] += $carry;
$carry = $e[$i] + 8;
$carry >>= 4;
$e[$i] -= $carry << 4;
}
// e[63] += carry;
// /* each e[i] is between -8 and 8 */
$e[63] += $carry;
// ge25519_p3_0(h);
$h = self::ge_p3_0();
// for (i = 63; i != 0; i--) {
for ($i = 63; $i != 0; --$i) {
// ge25519_cmov8_cached(&t, pi, e[i]);
$t = self::ge_cmov8_cached($pi, $e[$i]);
// ge25519_add_cached(&r, h, &t);
$r = self::ge_add($h, $t);
// ge25519_p1p1_to_p2(&s, &r);
// ge25519_p2_dbl(&r, &s);
// ge25519_p1p1_to_p2(&s, &r);
// ge25519_p2_dbl(&r, &s);
// ge25519_p1p1_to_p2(&s, &r);
// ge25519_p2_dbl(&r, &s);
// ge25519_p1p1_to_p2(&s, &r);
// ge25519_p2_dbl(&r, &s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
// ge25519_p1p1_to_p3(h, &r); /* *16 */
$h = self::ge_p1p1_to_p3($r); /* *16 */
}
// ge25519_cmov8_cached(&t, pi, e[i]);
// ge25519_add_cached(&r, h, &t);
// ge25519_p1p1_to_p3(h, &r);
$t = self::ge_cmov8_cached($pi, $e[0]);
$r = self::ge_add($h, $t);
return self::ge_p1p1_to_p3($r);
}
/**
* @internal You should not use this directly from another application
*
* @param string $a
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedOperand
*/
public static function ge_scalarmult_base($a)
{
/** @var array<int, int> $e */
$e = array();
$r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
for ($i = 0; $i < 32; ++$i) {
$dbl = (int) $i << 1;
$e[$dbl] = (int) self::chrToInt($a[$i]) & 15;
$e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15;
}
$carry = 0;
for ($i = 0; $i < 63; ++$i) {
$e[$i] += $carry;
$carry = $e[$i] + 8;
$carry >>= 4;
$e[$i] -= $carry << 4;
}
$e[63] += (int) $carry;
$h = self::ge_p3_0();
for ($i = 1; $i < 64; $i += 2) {
$t = self::ge_select((int) floor($i / 2), (int) $e[$i]);
$r = self::ge_madd($r, $h, $t);
$h = self::ge_p1p1_to_p3($r);
}
$r = self::ge_p3_dbl($h);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$h = self::ge_p1p1_to_p3($r);
for ($i = 0; $i < 64; $i += 2) {
$t = self::ge_select($i >> 1, (int) $e[$i]);
$r = self::ge_madd($r, $h, $t);
$h = self::ge_p1p1_to_p3($r);
}
return $h;
}
/**
* Calculates (ab + c) mod l
* where l = 2^252 + 27742317777372353535851937790883648493
*
* @internal You should not use this directly from another application
*
* @param string $a
* @param string $b
* @param string $c
* @return string
* @throws TypeError
*/
public static function sc_muladd($a, $b, $c)
{
$a0 = 2097151 & self::load_3(self::substr($a, 0, 3));
$a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5);
$a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2);
$a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7);
$a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4);
$a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1);
$a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6);
$a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3);
$a8 = 2097151 & self::load_3(self::substr($a, 21, 3));
$a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5);
$a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2);
$a11 = (self::load_4(self::substr($a, 28, 4)) >> 7);
$b0 = 2097151 & self::load_3(self::substr($b, 0, 3));
$b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5);
$b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2);
$b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7);
$b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4);
$b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1);
$b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6);
$b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3);
$b8 = 2097151 & self::load_3(self::substr($b, 21, 3));
$b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5);
$b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2);
$b11 = (self::load_4(self::substr($b, 28, 4)) >> 7);
$c0 = 2097151 & self::load_3(self::substr($c, 0, 3));
$c1 = 2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5);
$c2 = 2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2);
$c3 = 2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7);
$c4 = 2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4);
$c5 = 2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1);
$c6 = 2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6);
$c7 = 2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3);
$c8 = 2097151 & self::load_3(self::substr($c, 21, 3));
$c9 = 2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5);
$c10 = 2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2);
$c11 = (self::load_4(self::substr($c, 28, 4)) >> 7);
/* Can't really avoid the pyramid here: */
$s0 = $c0 + self::mul($a0, $b0, 24);
$s1 = $c1 + self::mul($a0, $b1, 24) + self::mul($a1, $b0, 24);
$s2 = $c2 + self::mul($a0, $b2, 24) + self::mul($a1, $b1, 24) + self::mul($a2, $b0, 24);
$s3 = $c3 + self::mul($a0, $b3, 24) + self::mul($a1, $b2, 24) + self::mul($a2, $b1, 24) + self::mul($a3, $b0, 24);
$s4 = $c4 + self::mul($a0, $b4, 24) + self::mul($a1, $b3, 24) + self::mul($a2, $b2, 24) + self::mul($a3, $b1, 24) +
self::mul($a4, $b0, 24);
$s5 = $c5 + self::mul($a0, $b5, 24) + self::mul($a1, $b4, 24) + self::mul($a2, $b3, 24) + self::mul($a3, $b2, 24) +
self::mul($a4, $b1, 24) + self::mul($a5, $b0, 24);
$s6 = $c6 + self::mul($a0, $b6, 24) + self::mul($a1, $b5, 24) + self::mul($a2, $b4, 24) + self::mul($a3, $b3, 24) +
self::mul($a4, $b2, 24) + self::mul($a5, $b1, 24) + self::mul($a6, $b0, 24);
$s7 = $c7 + self::mul($a0, $b7, 24) + self::mul($a1, $b6, 24) + self::mul($a2, $b5, 24) + self::mul($a3, $b4, 24) +
self::mul($a4, $b3, 24) + self::mul($a5, $b2, 24) + self::mul($a6, $b1, 24) + self::mul($a7, $b0, 24);
$s8 = $c8 + self::mul($a0, $b8, 24) + self::mul($a1, $b7, 24) + self::mul($a2, $b6, 24) + self::mul($a3, $b5, 24) +
self::mul($a4, $b4, 24) + self::mul($a5, $b3, 24) + self::mul($a6, $b2, 24) + self::mul($a7, $b1, 24) +
self::mul($a8, $b0, 24);
$s9 = $c9 + self::mul($a0, $b9, 24) + self::mul($a1, $b8, 24) + self::mul($a2, $b7, 24) + self::mul($a3, $b6, 24) +
self::mul($a4, $b5, 24) + self::mul($a5, $b4, 24) + self::mul($a6, $b3, 24) + self::mul($a7, $b2, 24) +
self::mul($a8, $b1, 24) + self::mul($a9, $b0, 24);
$s10 = $c10 + self::mul($a0, $b10, 24) + self::mul($a1, $b9, 24) + self::mul($a2, $b8, 24) + self::mul($a3, $b7, 24) +
self::mul($a4, $b6, 24) + self::mul($a5, $b5, 24) + self::mul($a6, $b4, 24) + self::mul($a7, $b3, 24) +
self::mul($a8, $b2, 24) + self::mul($a9, $b1, 24) + self::mul($a10, $b0, 24);
$s11 = $c11 + self::mul($a0, $b11, 24) + self::mul($a1, $b10, 24) + self::mul($a2, $b9, 24) + self::mul($a3, $b8, 24) +
self::mul($a4, $b7, 24) + self::mul($a5, $b6, 24) + self::mul($a6, $b5, 24) + self::mul($a7, $b4, 24) +
self::mul($a8, $b3, 24) + self::mul($a9, $b2, 24) + self::mul($a10, $b1, 24) + self::mul($a11, $b0, 24);
$s12 = self::mul($a1, $b11, 24) + self::mul($a2, $b10, 24) + self::mul($a3, $b9, 24) + self::mul($a4, $b8, 24) +
self::mul($a5, $b7, 24) + self::mul($a6, $b6, 24) + self::mul($a7, $b5, 24) + self::mul($a8, $b4, 24) +
self::mul($a9, $b3, 24) + self::mul($a10, $b2, 24) + self::mul($a11, $b1, 24);
$s13 = self::mul($a2, $b11, 24) + self::mul($a3, $b10, 24) + self::mul($a4, $b9, 24) + self::mul($a5, $b8, 24) +
self::mul($a6, $b7, 24) + self::mul($a7, $b6, 24) + self::mul($a8, $b5, 24) + self::mul($a9, $b4, 24) +
self::mul($a10, $b3, 24) + self::mul($a11, $b2, 24);
$s14 = self::mul($a3, $b11, 24) + self::mul($a4, $b10, 24) + self::mul($a5, $b9, 24) + self::mul($a6, $b8, 24) +
self::mul($a7, $b7, 24) + self::mul($a8, $b6, 24) + self::mul($a9, $b5, 24) + self::mul($a10, $b4, 24) +
self::mul($a11, $b3, 24);
$s15 = self::mul($a4, $b11, 24) + self::mul($a5, $b10, 24) + self::mul($a6, $b9, 24) + self::mul($a7, $b8, 24) +
self::mul($a8, $b7, 24) + self::mul($a9, $b6, 24) + self::mul($a10, $b5, 24) + self::mul($a11, $b4, 24);
$s16 = self::mul($a5, $b11, 24) + self::mul($a6, $b10, 24) + self::mul($a7, $b9, 24) + self::mul($a8, $b8, 24) +
self::mul($a9, $b7, 24) + self::mul($a10, $b6, 24) + self::mul($a11, $b5, 24);
$s17 = self::mul($a6, $b11, 24) + self::mul($a7, $b10, 24) + self::mul($a8, $b9, 24) + self::mul($a9, $b8, 24) +
self::mul($a10, $b7, 24) + self::mul($a11, $b6, 24);
$s18 = self::mul($a7, $b11, 24) + self::mul($a8, $b10, 24) + self::mul($a9, $b9, 24) + self::mul($a10, $b8, 24) +
self::mul($a11, $b7, 24);
$s19 = self::mul($a8, $b11, 24) + self::mul($a9, $b10, 24) + self::mul($a10, $b9, 24) + self::mul($a11, $b8, 24);
$s20 = self::mul($a9, $b11, 24) + self::mul($a10, $b10, 24) + self::mul($a11, $b9, 24);
$s21 = self::mul($a10, $b11, 24) + self::mul($a11, $b10, 24);
$s22 = self::mul($a11, $b11, 24);
$s23 = 0;
$carry0 = ($s0 + (1 << 20)) >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
$carry2 = ($s2 + (1 << 20)) >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
$carry4 = ($s4 + (1 << 20)) >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$carry12 = ($s12 + (1 << 20)) >> 21;
$s13 += $carry12;
$s12 -= $carry12 << 21;
$carry14 = ($s14 + (1 << 20)) >> 21;
$s15 += $carry14;
$s14 -= $carry14 << 21;
$carry16 = ($s16 + (1 << 20)) >> 21;
$s17 += $carry16;
$s16 -= $carry16 << 21;
$carry18 = ($s18 + (1 << 20)) >> 21;
$s19 += $carry18;
$s18 -= $carry18 << 21;
$carry20 = ($s20 + (1 << 20)) >> 21;
$s21 += $carry20;
$s20 -= $carry20 << 21;
$carry22 = ($s22 + (1 << 20)) >> 21;
$s23 += $carry22;
$s22 -= $carry22 << 21;
$carry1 = ($s1 + (1 << 20)) >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
$carry3 = ($s3 + (1 << 20)) >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
$carry5 = ($s5 + (1 << 20)) >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
$carry13 = ($s13 + (1 << 20)) >> 21;
$s14 += $carry13;
$s13 -= $carry13 << 21;
$carry15 = ($s15 + (1 << 20)) >> 21;
$s16 += $carry15;
$s15 -= $carry15 << 21;
$carry17 = ($s17 + (1 << 20)) >> 21;
$s18 += $carry17;
$s17 -= $carry17 << 21;
$carry19 = ($s19 + (1 << 20)) >> 21;
$s20 += $carry19;
$s19 -= $carry19 << 21;
$carry21 = ($s21 + (1 << 20)) >> 21;
$s22 += $carry21;
$s21 -= $carry21 << 21;
$s11 += self::mul($s23, 666643, 20);
$s12 += self::mul($s23, 470296, 19);
$s13 += self::mul($s23, 654183, 20);
$s14 -= self::mul($s23, 997805, 20);
$s15 += self::mul($s23, 136657, 18);
$s16 -= self::mul($s23, 683901, 20);
$s10 += self::mul($s22, 666643, 20);
$s11 += self::mul($s22, 470296, 19);
$s12 += self::mul($s22, 654183, 20);
$s13 -= self::mul($s22, 997805, 20);
$s14 += self::mul($s22, 136657, 18);
$s15 -= self::mul($s22, 683901, 20);
$s9 += self::mul($s21, 666643, 20);
$s10 += self::mul($s21, 470296, 19);
$s11 += self::mul($s21, 654183, 20);
$s12 -= self::mul($s21, 997805, 20);
$s13 += self::mul($s21, 136657, 18);
$s14 -= self::mul($s21, 683901, 20);
$s8 += self::mul($s20, 666643, 20);
$s9 += self::mul($s20, 470296, 19);
$s10 += self::mul($s20, 654183, 20);
$s11 -= self::mul($s20, 997805, 20);
$s12 += self::mul($s20, 136657, 18);
$s13 -= self::mul($s20, 683901, 20);
$s7 += self::mul($s19, 666643, 20);
$s8 += self::mul($s19, 470296, 19);
$s9 += self::mul($s19, 654183, 20);
$s10 -= self::mul($s19, 997805, 20);
$s11 += self::mul($s19, 136657, 18);
$s12 -= self::mul($s19, 683901, 20);
$s6 += self::mul($s18, 666643, 20);
$s7 += self::mul($s18, 470296, 19);
$s8 += self::mul($s18, 654183, 20);
$s9 -= self::mul($s18, 997805, 20);
$s10 += self::mul($s18, 136657, 18);
$s11 -= self::mul($s18, 683901, 20);
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$carry12 = ($s12 + (1 << 20)) >> 21;
$s13 += $carry12;
$s12 -= $carry12 << 21;
$carry14 = ($s14 + (1 << 20)) >> 21;
$s15 += $carry14;
$s14 -= $carry14 << 21;
$carry16 = ($s16 + (1 << 20)) >> 21;
$s17 += $carry16;
$s16 -= $carry16 << 21;
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
$carry13 = ($s13 + (1 << 20)) >> 21;
$s14 += $carry13;
$s13 -= $carry13 << 21;
$carry15 = ($s15 + (1 << 20)) >> 21;
$s16 += $carry15;
$s15 -= $carry15 << 21;
$s5 += self::mul($s17, 666643, 20);
$s6 += self::mul($s17, 470296, 19);
$s7 += self::mul($s17, 654183, 20);
$s8 -= self::mul($s17, 997805, 20);
$s9 += self::mul($s17, 136657, 18);
$s10 -= self::mul($s17, 683901, 20);
$s4 += self::mul($s16, 666643, 20);
$s5 += self::mul($s16, 470296, 19);
$s6 += self::mul($s16, 654183, 20);
$s7 -= self::mul($s16, 997805, 20);
$s8 += self::mul($s16, 136657, 18);
$s9 -= self::mul($s16, 683901, 20);
$s3 += self::mul($s15, 666643, 20);
$s4 += self::mul($s15, 470296, 19);
$s5 += self::mul($s15, 654183, 20);
$s6 -= self::mul($s15, 997805, 20);
$s7 += self::mul($s15, 136657, 18);
$s8 -= self::mul($s15, 683901, 20);
$s2 += self::mul($s14, 666643, 20);
$s3 += self::mul($s14, 470296, 19);
$s4 += self::mul($s14, 654183, 20);
$s5 -= self::mul($s14, 997805, 20);
$s6 += self::mul($s14, 136657, 18);
$s7 -= self::mul($s14, 683901, 20);
$s1 += self::mul($s13, 666643, 20);
$s2 += self::mul($s13, 470296, 19);
$s3 += self::mul($s13, 654183, 20);
$s4 -= self::mul($s13, 997805, 20);
$s5 += self::mul($s13, 136657, 18);
$s6 -= self::mul($s13, 683901, 20);
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$s12 = 0;
$carry0 = ($s0 + (1 << 20)) >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
$carry2 = ($s2 + (1 << 20)) >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
$carry4 = ($s4 + (1 << 20)) >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$carry1 = ($s1 + (1 << 20)) >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
$carry3 = ($s3 + (1 << 20)) >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
$carry5 = ($s5 + (1 << 20)) >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$s12 = 0;
$carry0 = $s0 >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
$carry1 = $s1 >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
$carry2 = $s2 >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
$carry3 = $s3 >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
$carry4 = $s4 >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
$carry5 = $s5 >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
$carry6 = $s6 >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry7 = $s7 >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry8 = $s8 >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry9 = $s9 >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry10 = $s10 >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$carry11 = $s11 >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$carry0 = $s0 >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
$carry1 = $s1 >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
$carry2 = $s2 >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
$carry3 = $s3 >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
$carry4 = $s4 >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
$carry5 = $s5 >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
$carry6 = $s6 >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry7 = $s7 >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry8 = $s8 >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry9 = $s9 >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry10 = $s10 >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
/**
* @var array<int, int>
*/
$arr = array(
(int) (0xff & ($s0 >> 0)),
(int) (0xff & ($s0 >> 8)),
(int) (0xff & (($s0 >> 16) | $s1 << 5)),
(int) (0xff & ($s1 >> 3)),
(int) (0xff & ($s1 >> 11)),
(int) (0xff & (($s1 >> 19) | $s2 << 2)),
(int) (0xff & ($s2 >> 6)),
(int) (0xff & (($s2 >> 14) | $s3 << 7)),
(int) (0xff & ($s3 >> 1)),
(int) (0xff & ($s3 >> 9)),
(int) (0xff & (($s3 >> 17) | $s4 << 4)),
(int) (0xff & ($s4 >> 4)),
(int) (0xff & ($s4 >> 12)),
(int) (0xff & (($s4 >> 20) | $s5 << 1)),
(int) (0xff & ($s5 >> 7)),
(int) (0xff & (($s5 >> 15) | $s6 << 6)),
(int) (0xff & ($s6 >> 2)),
(int) (0xff & ($s6 >> 10)),
(int) (0xff & (($s6 >> 18) | $s7 << 3)),
(int) (0xff & ($s7 >> 5)),
(int) (0xff & ($s7 >> 13)),
(int) (0xff & ($s8 >> 0)),
(int) (0xff & ($s8 >> 8)),
(int) (0xff & (($s8 >> 16) | $s9 << 5)),
(int) (0xff & ($s9 >> 3)),
(int) (0xff & ($s9 >> 11)),
(int) (0xff & (($s9 >> 19) | $s10 << 2)),
(int) (0xff & ($s10 >> 6)),
(int) (0xff & (($s10 >> 14) | $s11 << 7)),
(int) (0xff & ($s11 >> 1)),
(int) (0xff & ($s11 >> 9)),
0xff & ($s11 >> 17)
);
return self::intArrayToString($arr);
}
/**
* @internal You should not use this directly from another application
*
* @param string $s
* @return string
* @throws TypeError
*/
public static function sc_reduce($s)
{
$s0 = 2097151 & self::load_3(self::substr($s, 0, 3));
$s1 = 2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5);
$s2 = 2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2);
$s3 = 2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7);
$s4 = 2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4);
$s5 = 2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1);
$s6 = 2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6);
$s7 = 2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3);
$s8 = 2097151 & self::load_3(self::substr($s, 21, 3));
$s9 = 2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5);
$s10 = 2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2);
$s11 = 2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7);
$s12 = 2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4);
$s13 = 2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1);
$s14 = 2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6);
$s15 = 2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3);
$s16 = 2097151 & self::load_3(self::substr($s, 42, 3));
$s17 = 2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5);
$s18 = 2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2);
$s19 = 2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7);
$s20 = 2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4);
$s21 = 2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1);
$s22 = 2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6);
$s23 = 0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3);
$s11 += self::mul($s23, 666643, 20);
$s12 += self::mul($s23, 470296, 19);
$s13 += self::mul($s23, 654183, 20);
$s14 -= self::mul($s23, 997805, 20);
$s15 += self::mul($s23, 136657, 18);
$s16 -= self::mul($s23, 683901, 20);
$s10 += self::mul($s22, 666643, 20);
$s11 += self::mul($s22, 470296, 19);
$s12 += self::mul($s22, 654183, 20);
$s13 -= self::mul($s22, 997805, 20);
$s14 += self::mul($s22, 136657, 18);
$s15 -= self::mul($s22, 683901, 20);
$s9 += self::mul($s21, 666643, 20);
$s10 += self::mul($s21, 470296, 19);
$s11 += self::mul($s21, 654183, 20);
$s12 -= self::mul($s21, 997805, 20);
$s13 += self::mul($s21, 136657, 18);
$s14 -= self::mul($s21, 683901, 20);
$s8 += self::mul($s20, 666643, 20);
$s9 += self::mul($s20, 470296, 19);
$s10 += self::mul($s20, 654183, 20);
$s11 -= self::mul($s20, 997805, 20);
$s12 += self::mul($s20, 136657, 18);
$s13 -= self::mul($s20, 683901, 20);
$s7 += self::mul($s19, 666643, 20);
$s8 += self::mul($s19, 470296, 19);
$s9 += self::mul($s19, 654183, 20);
$s10 -= self::mul($s19, 997805, 20);
$s11 += self::mul($s19, 136657, 18);
$s12 -= self::mul($s19, 683901, 20);
$s6 += self::mul($s18, 666643, 20);
$s7 += self::mul($s18, 470296, 19);
$s8 += self::mul($s18, 654183, 20);
$s9 -= self::mul($s18, 997805, 20);
$s10 += self::mul($s18, 136657, 18);
$s11 -= self::mul($s18, 683901, 20);
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$carry12 = ($s12 + (1 << 20)) >> 21;
$s13 += $carry12;
$s12 -= $carry12 << 21;
$carry14 = ($s14 + (1 << 20)) >> 21;
$s15 += $carry14;
$s14 -= $carry14 << 21;
$carry16 = ($s16 + (1 << 20)) >> 21;
$s17 += $carry16;
$s16 -= $carry16 << 21;
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
$carry13 = ($s13 + (1 << 20)) >> 21;
$s14 += $carry13;
$s13 -= $carry13 << 21;
$carry15 = ($s15 + (1 << 20)) >> 21;
$s16 += $carry15;
$s15 -= $carry15 << 21;
$s5 += self::mul($s17, 666643, 20);
$s6 += self::mul($s17, 470296, 19);
$s7 += self::mul($s17, 654183, 20);
$s8 -= self::mul($s17, 997805, 20);
$s9 += self::mul($s17, 136657, 18);
$s10 -= self::mul($s17, 683901, 20);
$s4 += self::mul($s16, 666643, 20);
$s5 += self::mul($s16, 470296, 19);
$s6 += self::mul($s16, 654183, 20);
$s7 -= self::mul($s16, 997805, 20);
$s8 += self::mul($s16, 136657, 18);
$s9 -= self::mul($s16, 683901, 20);
$s3 += self::mul($s15, 666643, 20);
$s4 += self::mul($s15, 470296, 19);
$s5 += self::mul($s15, 654183, 20);
$s6 -= self::mul($s15, 997805, 20);
$s7 += self::mul($s15, 136657, 18);
$s8 -= self::mul($s15, 683901, 20);
$s2 += self::mul($s14, 666643, 20);
$s3 += self::mul($s14, 470296, 19);
$s4 += self::mul($s14, 654183, 20);
$s5 -= self::mul($s14, 997805, 20);
$s6 += self::mul($s14, 136657, 18);
$s7 -= self::mul($s14, 683901, 20);
$s1 += self::mul($s13, 666643, 20);
$s2 += self::mul($s13, 470296, 19);
$s3 += self::mul($s13, 654183, 20);
$s4 -= self::mul($s13, 997805, 20);
$s5 += self::mul($s13, 136657, 18);
$s6 -= self::mul($s13, 683901, 20);
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$s12 = 0;
$carry0 = ($s0 + (1 << 20)) >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
$carry2 = ($s2 + (1 << 20)) >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
$carry4 = ($s4 + (1 << 20)) >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$carry1 = ($s1 + (1 << 20)) >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
$carry3 = ($s3 + (1 << 20)) >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
$carry5 = ($s5 + (1 << 20)) >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$s12 = 0;
$carry0 = $s0 >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
$carry1 = $s1 >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
$carry2 = $s2 >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
$carry3 = $s3 >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
$carry4 = $s4 >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
$carry5 = $s5 >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
$carry6 = $s6 >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry7 = $s7 >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry8 = $s8 >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry9 = $s9 >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry10 = $s10 >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$carry11 = $s11 >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$carry0 = $s0 >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
$carry1 = $s1 >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
$carry2 = $s2 >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
$carry3 = $s3 >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
$carry4 = $s4 >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
$carry5 = $s5 >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
$carry6 = $s6 >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
$carry7 = $s7 >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
$carry8 = $s8 >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
$carry9 = $s9 >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
$carry10 = $s10 >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
/**
* @var array<int, int>
*/
$arr = array(
(int) ($s0 >> 0),
(int) ($s0 >> 8),
(int) (($s0 >> 16) | $s1 << 5),
(int) ($s1 >> 3),
(int) ($s1 >> 11),
(int) (($s1 >> 19) | $s2 << 2),
(int) ($s2 >> 6),
(int) (($s2 >> 14) | $s3 << 7),
(int) ($s3 >> 1),
(int) ($s3 >> 9),
(int) (($s3 >> 17) | $s4 << 4),
(int) ($s4 >> 4),
(int) ($s4 >> 12),
(int) (($s4 >> 20) | $s5 << 1),
(int) ($s5 >> 7),
(int) (($s5 >> 15) | $s6 << 6),
(int) ($s6 >> 2),
(int) ($s6 >> 10),
(int) (($s6 >> 18) | $s7 << 3),
(int) ($s7 >> 5),
(int) ($s7 >> 13),
(int) ($s8 >> 0),
(int) ($s8 >> 8),
(int) (($s8 >> 16) | $s9 << 5),
(int) ($s9 >> 3),
(int) ($s9 >> 11),
(int) (($s9 >> 19) | $s10 << 2),
(int) ($s10 >> 6),
(int) (($s10 >> 14) | $s11 << 7),
(int) ($s11 >> 1),
(int) ($s11 >> 9),
(int) $s11 >> 17
);
return self::intArrayToString($arr);
}
/**
* multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493
*
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
*/
public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A)
{
$aslide = array(
13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0,
0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0,
0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0,
0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1,
0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
);
/** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai size 8 */
$Ai = array();
# ge_p3_to_cached(&Ai[0], A);
$Ai[0] = self::ge_p3_to_cached($A);
# ge_p3_dbl(&t, A);
$t = self::ge_p3_dbl($A);
# ge_p1p1_to_p3(&A2, &t);
$A2 = self::ge_p1p1_to_p3($t);
for ($i = 1; $i < 8; ++$i) {
# ge_add(&t, &A2, &Ai[0]);
$t = self::ge_add($A2, $Ai[$i - 1]);
# ge_p1p1_to_p3(&u, &t);
$u = self::ge_p1p1_to_p3($t);
# ge_p3_to_cached(&Ai[i], &u);
$Ai[$i] = self::ge_p3_to_cached($u);
}
$r = self::ge_p3_0();
for ($i = 252; $i >= 0; --$i) {
$t = self::ge_p3_dbl($r);
if ($aslide[$i] > 0) {
# ge_p1p1_to_p3(&u, &t);
$u = self::ge_p1p1_to_p3($t);
# ge_add(&t, &u, &Ai[aslide[i] / 2]);
$t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]);
} elseif ($aslide[$i] < 0) {
# ge_p1p1_to_p3(&u, &t);
$u = self::ge_p1p1_to_p3($t);
# ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
$t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]);
}
}
# ge_p1p1_to_p3(r, &t);
return self::ge_p1p1_to_p3($t);
}
/**
* @param string $a
* @param string $b
* @return string
*/
public static function sc25519_mul($a, $b)
{
// int64_t a0 = 2097151 & load_3(a);
// int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
// int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
// int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
// int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
// int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
// int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
// int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
// int64_t a8 = 2097151 & load_3(a + 21);
// int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
// int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
// int64_t a11 = (load_4(a + 28) >> 7);
$a0 = 2097151 & self::load_3(self::substr($a, 0, 3));
$a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5);
$a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2);
$a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7);
$a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4);
$a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1);
$a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6);
$a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3);
$a8 = 2097151 & self::load_3(self::substr($a, 21, 3));
$a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5);
$a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2);
$a11 = (self::load_4(self::substr($a, 28, 4)) >> 7);
// int64_t b0 = 2097151 & load_3(b);
// int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
// int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
// int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
// int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
// int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
// int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
// int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
// int64_t b8 = 2097151 & load_3(b + 21);
// int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
// int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
// int64_t b11 = (load_4(b + 28) >> 7);
$b0 = 2097151 & self::load_3(self::substr($b, 0, 3));
$b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5);
$b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2);
$b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7);
$b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4);
$b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1);
$b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6);
$b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3);
$b8 = 2097151 & self::load_3(self::substr($b, 21, 3));
$b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5);
$b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2);
$b11 = (self::load_4(self::substr($b, 28, 4)) >> 7);
// s0 = a0 * b0;
// s1 = a0 * b1 + a1 * b0;
// s2 = a0 * b2 + a1 * b1 + a2 * b0;
// s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
// s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
// s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
// s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
// s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
// a6 * b1 + a7 * b0;
// s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
// a6 * b2 + a7 * b1 + a8 * b0;
// s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
// a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
// s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
// a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
// s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
// a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
// s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 +
// a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
// s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 +
// a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
// s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 +
// a9 * b5 + a10 * b4 + a11 * b3;
// s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 +
// a10 * b5 + a11 * b4;
// s16 =
// a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
// s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
// s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
// s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
// s20 = a9 * b11 + a10 * b10 + a11 * b9;
// s21 = a10 * b11 + a11 * b10;
// s22 = a11 * b11;
// s23 = 0;
$s0 = self::mul($a0, $b0, 22);
$s1 = self::mul($a0, $b1, 22) + self::mul($a1, $b0, 22);
$s2 = self::mul($a0, $b2, 22) + self::mul($a1, $b1, 22) + self::mul($a2, $b0, 22);
$s3 = self::mul($a0, $b3, 22) + self::mul($a1, $b2, 22) + self::mul($a2, $b1, 22) + self::mul($a3, $b0, 22);
$s4 = self::mul($a0, $b4, 22) + self::mul($a1, $b3, 22) + self::mul($a2, $b2, 22) + self::mul($a3, $b1, 22) +
self::mul($a4, $b0, 22);
$s5 = self::mul($a0, $b5, 22) + self::mul($a1, $b4, 22) + self::mul($a2, $b3, 22) + self::mul($a3, $b2, 22) +
self::mul($a4, $b1, 22) + self::mul($a5, $b0, 22);
$s6 = self::mul($a0, $b6, 22) + self::mul($a1, $b5, 22) + self::mul($a2, $b4, 22) + self::mul($a3, $b3, 22) +
self::mul($a4, $b2, 22) + self::mul($a5, $b1, 22) + self::mul($a6, $b0, 22);
$s7 = self::mul($a0, $b7, 22) + self::mul($a1, $b6, 22) + self::mul($a2, $b5, 22) + self::mul($a3, $b4, 22) +
self::mul($a4, $b3, 22) + self::mul($a5, $b2, 22) + self::mul($a6, $b1, 22) + self::mul($a7, $b0, 22);
$s8 = self::mul($a0, $b8, 22) + self::mul($a1, $b7, 22) + self::mul($a2, $b6, 22) + self::mul($a3, $b5, 22) +
self::mul($a4, $b4, 22) + self::mul($a5, $b3, 22) + self::mul($a6, $b2, 22) + self::mul($a7, $b1, 22) +
self::mul($a8, $b0, 22);
$s9 = self::mul($a0, $b9, 22) + self::mul($a1, $b8, 22) + self::mul($a2, $b7, 22) + self::mul($a3, $b6, 22) +
self::mul($a4, $b5, 22) + self::mul($a5, $b4, 22) + self::mul($a6, $b3, 22) + self::mul($a7, $b2, 22) +
self::mul($a8, $b1, 22) + self::mul($a9, $b0, 22);
$s10 = self::mul($a0, $b10, 22) + self::mul($a1, $b9, 22) + self::mul($a2, $b8, 22) + self::mul($a3, $b7, 22) +
self::mul($a4, $b6, 22) + self::mul($a5, $b5, 22) + self::mul($a6, $b4, 22) + self::mul($a7, $b3, 22) +
self::mul($a8, $b2, 22) + self::mul($a9, $b1, 22) + self::mul($a10, $b0, 22);
$s11 = self::mul($a0, $b11, 22) + self::mul($a1, $b10, 22) + self::mul($a2, $b9, 22) + self::mul($a3, $b8, 22) +
self::mul($a4, $b7, 22) + self::mul($a5, $b6, 22) + self::mul($a6, $b5, 22) + self::mul($a7, $b4, 22) +
self::mul($a8, $b3, 22) + self::mul($a9, $b2, 22) + self::mul($a10, $b1, 22) + self::mul($a11, $b0, 22);
$s12 = self::mul($a1, $b11, 22) + self::mul($a2, $b10, 22) + self::mul($a3, $b9, 22) + self::mul($a4, $b8, 22) +
self::mul($a5, $b7, 22) + self::mul($a6, $b6, 22) + self::mul($a7, $b5, 22) + self::mul($a8, $b4, 22) +
self::mul($a9, $b3, 22) + self::mul($a10, $b2, 22) + self::mul($a11, $b1, 22);
$s13 = self::mul($a2, $b11, 22) + self::mul($a3, $b10, 22) + self::mul($a4, $b9, 22) + self::mul($a5, $b8, 22) +
self::mul($a6, $b7, 22) + self::mul($a7, $b6, 22) + self::mul($a8, $b5, 22) + self::mul($a9, $b4, 22) +
self::mul($a10, $b3, 22) + self::mul($a11, $b2, 22);
$s14 = self::mul($a3, $b11, 22) + self::mul($a4, $b10, 22) + self::mul($a5, $b9, 22) + self::mul($a6, $b8, 22) +
self::mul($a7, $b7, 22) + self::mul($a8, $b6, 22) + self::mul($a9, $b5, 22) + self::mul($a10, $b4, 22) +
self::mul($a11, $b3, 22);
$s15 = self::mul($a4, $b11, 22) + self::mul($a5, $b10, 22) + self::mul($a6, $b9, 22) + self::mul($a7, $b8, 22) +
self::mul($a8, $b7, 22) + self::mul($a9, $b6, 22) + self::mul($a10, $b5, 22) + self::mul($a11, $b4, 22);
$s16 =
self::mul($a5, $b11, 22) + self::mul($a6, $b10, 22) + self::mul($a7, $b9, 22) + self::mul($a8, $b8, 22) +
self::mul($a9, $b7, 22) + self::mul($a10, $b6, 22) + self::mul($a11, $b5, 22);
$s17 = self::mul($a6, $b11, 22) + self::mul($a7, $b10, 22) + self::mul($a8, $b9, 22) + self::mul($a9, $b8, 22) +
self::mul($a10, $b7, 22) + self::mul($a11, $b6, 22);
$s18 = self::mul($a7, $b11, 22) + self::mul($a8, $b10, 22) + self::mul($a9, $b9, 22) + self::mul($a10, $b8, 22)
+ self::mul($a11, $b7, 22);
$s19 = self::mul($a8, $b11, 22) + self::mul($a9, $b10, 22) + self::mul($a10, $b9, 22) +
self::mul($a11, $b8, 22);
$s20 = self::mul($a9, $b11, 22) + self::mul($a10, $b10, 22) + self::mul($a11, $b9, 22);
$s21 = self::mul($a10, $b11, 22) + self::mul($a11, $b10, 22);
$s22 = self::mul($a11, $b11, 22);
$s23 = 0;
// carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
// s1 += carry0;
// s0 -= carry0 * ((uint64_t) 1L << 21);
$carry0 = ($s0 + (1 << 20)) >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
// carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
// s3 += carry2;
// s2 -= carry2 * ((uint64_t) 1L << 21);
$carry2 = ($s2 + (1 << 20)) >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
// carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
// s5 += carry4;
// s4 -= carry4 * ((uint64_t) 1L << 21);
$carry4 = ($s4 + (1 << 20)) >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
// carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
// s7 += carry6;
// s6 -= carry6 * ((uint64_t) 1L << 21);
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
// carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
// s9 += carry8;
// s8 -= carry8 * ((uint64_t) 1L << 21);
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
// carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
// s11 += carry10;
// s10 -= carry10 * ((uint64_t) 1L << 21);
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
// carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
// s13 += carry12;
// s12 -= carry12 * ((uint64_t) 1L << 21);
$carry12 = ($s12 + (1 << 20)) >> 21;
$s13 += $carry12;
$s12 -= $carry12 << 21;
// carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
// s15 += carry14;
// s14 -= carry14 * ((uint64_t) 1L << 21);
$carry14 = ($s14 + (1 << 20)) >> 21;
$s15 += $carry14;
$s14 -= $carry14 << 21;
// carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
// s17 += carry16;
// s16 -= carry16 * ((uint64_t) 1L << 21);
$carry16 = ($s16 + (1 << 20)) >> 21;
$s17 += $carry16;
$s16 -= $carry16 << 21;
// carry18 = (s18 + (int64_t) (1L << 20)) >> 21;
// s19 += carry18;
// s18 -= carry18 * ((uint64_t) 1L << 21);
$carry18 = ($s18 + (1 << 20)) >> 21;
$s19 += $carry18;
$s18 -= $carry18 << 21;
// carry20 = (s20 + (int64_t) (1L << 20)) >> 21;
// s21 += carry20;
// s20 -= carry20 * ((uint64_t) 1L << 21);
$carry20 = ($s20 + (1 << 20)) >> 21;
$s21 += $carry20;
$s20 -= $carry20 << 21;
// carry22 = (s22 + (int64_t) (1L << 20)) >> 21;
// s23 += carry22;
// s22 -= carry22 * ((uint64_t) 1L << 21);
$carry22 = ($s22 + (1 << 20)) >> 21;
$s23 += $carry22;
$s22 -= $carry22 << 21;
// carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
// s2 += carry1;
// s1 -= carry1 * ((uint64_t) 1L << 21);
$carry1 = ($s1 + (1 << 20)) >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
// carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
// s4 += carry3;
// s3 -= carry3 * ((uint64_t) 1L << 21);
$carry3 = ($s3 + (1 << 20)) >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
// carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
// s6 += carry5;
// s5 -= carry5 * ((uint64_t) 1L << 21);
$carry5 = ($s5 + (1 << 20)) >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
// carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
// s8 += carry7;
// s7 -= carry7 * ((uint64_t) 1L << 21);
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
// carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
// s10 += carry9;
// s9 -= carry9 * ((uint64_t) 1L << 21);
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
// carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
// s12 += carry11;
// s11 -= carry11 * ((uint64_t) 1L << 21);
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
// carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
// s14 += carry13;
// s13 -= carry13 * ((uint64_t) 1L << 21);
$carry13 = ($s13 + (1 << 20)) >> 21;
$s14 += $carry13;
$s13 -= $carry13 << 21;
// carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
// s16 += carry15;
// s15 -= carry15 * ((uint64_t) 1L << 21);
$carry15 = ($s15 + (1 << 20)) >> 21;
$s16 += $carry15;
$s15 -= $carry15 << 21;
// carry17 = (s17 + (int64_t) (1L << 20)) >> 21;
// s18 += carry17;
// s17 -= carry17 * ((uint64_t) 1L << 21);
$carry17 = ($s17 + (1 << 20)) >> 21;
$s18 += $carry17;
$s17 -= $carry17 << 21;
// carry19 = (s19 + (int64_t) (1L << 20)) >> 21;
// s20 += carry19;
// s19 -= carry19 * ((uint64_t) 1L << 21);
$carry19 = ($s19 + (1 << 20)) >> 21;
$s20 += $carry19;
$s19 -= $carry19 << 21;
// carry21 = (s21 + (int64_t) (1L << 20)) >> 21;
// s22 += carry21;
// s21 -= carry21 * ((uint64_t) 1L << 21);
$carry21 = ($s21 + (1 << 20)) >> 21;
$s22 += $carry21;
$s21 -= $carry21 << 21;
// s11 += s23 * 666643;
// s12 += s23 * 470296;
// s13 += s23 * 654183;
// s14 -= s23 * 997805;
// s15 += s23 * 136657;
// s16 -= s23 * 683901;
$s11 += self::mul($s23, 666643, 20);
$s12 += self::mul($s23, 470296, 19);
$s13 += self::mul($s23, 654183, 20);
$s14 -= self::mul($s23, 997805, 20);
$s15 += self::mul($s23, 136657, 18);
$s16 -= self::mul($s23, 683901, 20);
// s10 += s22 * 666643;
// s11 += s22 * 470296;
// s12 += s22 * 654183;
// s13 -= s22 * 997805;
// s14 += s22 * 136657;
// s15 -= s22 * 683901;
$s10 += self::mul($s22, 666643, 20);
$s11 += self::mul($s22, 470296, 19);
$s12 += self::mul($s22, 654183, 20);
$s13 -= self::mul($s22, 997805, 20);
$s14 += self::mul($s22, 136657, 18);
$s15 -= self::mul($s22, 683901, 20);
// s9 += s21 * 666643;
// s10 += s21 * 470296;
// s11 += s21 * 654183;
// s12 -= s21 * 997805;
// s13 += s21 * 136657;
// s14 -= s21 * 683901;
$s9 += self::mul($s21, 666643, 20);
$s10 += self::mul($s21, 470296, 19);
$s11 += self::mul($s21, 654183, 20);
$s12 -= self::mul($s21, 997805, 20);
$s13 += self::mul($s21, 136657, 18);
$s14 -= self::mul($s21, 683901, 20);
// s8 += s20 * 666643;
// s9 += s20 * 470296;
// s10 += s20 * 654183;
// s11 -= s20 * 997805;
// s12 += s20 * 136657;
// s13 -= s20 * 683901;
$s8 += self::mul($s20, 666643, 20);
$s9 += self::mul($s20, 470296, 19);
$s10 += self::mul($s20, 654183, 20);
$s11 -= self::mul($s20, 997805, 20);
$s12 += self::mul($s20, 136657, 18);
$s13 -= self::mul($s20, 683901, 20);
// s7 += s19 * 666643;
// s8 += s19 * 470296;
// s9 += s19 * 654183;
// s10 -= s19 * 997805;
// s11 += s19 * 136657;
// s12 -= s19 * 683901;
$s7 += self::mul($s19, 666643, 20);
$s8 += self::mul($s19, 470296, 19);
$s9 += self::mul($s19, 654183, 20);
$s10 -= self::mul($s19, 997805, 20);
$s11 += self::mul($s19, 136657, 18);
$s12 -= self::mul($s19, 683901, 20);
// s6 += s18 * 666643;
// s7 += s18 * 470296;
// s8 += s18 * 654183;
// s9 -= s18 * 997805;
// s10 += s18 * 136657;
// s11 -= s18 * 683901;
$s6 += self::mul($s18, 666643, 20);
$s7 += self::mul($s18, 470296, 19);
$s8 += self::mul($s18, 654183, 20);
$s9 -= self::mul($s18, 997805, 20);
$s10 += self::mul($s18, 136657, 18);
$s11 -= self::mul($s18, 683901, 20);
// carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
// s7 += carry6;
// s6 -= carry6 * ((uint64_t) 1L << 21);
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
// carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
// s9 += carry8;
// s8 -= carry8 * ((uint64_t) 1L << 21);
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
// carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
// s11 += carry10;
// s10 -= carry10 * ((uint64_t) 1L << 21);
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
// carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
// s13 += carry12;
// s12 -= carry12 * ((uint64_t) 1L << 21);
$carry12 = ($s12 + (1 << 20)) >> 21;
$s13 += $carry12;
$s12 -= $carry12 << 21;
// carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
// s15 += carry14;
// s14 -= carry14 * ((uint64_t) 1L << 21);
$carry14 = ($s14 + (1 << 20)) >> 21;
$s15 += $carry14;
$s14 -= $carry14 << 21;
// carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
// s17 += carry16;
// s16 -= carry16 * ((uint64_t) 1L << 21);
$carry16 = ($s16 + (1 << 20)) >> 21;
$s17 += $carry16;
$s16 -= $carry16 << 21;
// carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
// s8 += carry7;
// s7 -= carry7 * ((uint64_t) 1L << 21);
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
// carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
// s10 += carry9;
// s9 -= carry9 * ((uint64_t) 1L << 21);
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
// carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
// s12 += carry11;
// s11 -= carry11 * ((uint64_t) 1L << 21);
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
// carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
// s14 += carry13;
// s13 -= carry13 * ((uint64_t) 1L << 21);
$carry13 = ($s13 + (1 << 20)) >> 21;
$s14 += $carry13;
$s13 -= $carry13 << 21;
// carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
// s16 += carry15;
// s15 -= carry15 * ((uint64_t) 1L << 21);
$carry15 = ($s15 + (1 << 20)) >> 21;
$s16 += $carry15;
$s15 -= $carry15 << 21;
// s5 += s17 * 666643;
// s6 += s17 * 470296;
// s7 += s17 * 654183;
// s8 -= s17 * 997805;
// s9 += s17 * 136657;
// s10 -= s17 * 683901;
$s5 += self::mul($s17, 666643, 20);
$s6 += self::mul($s17, 470296, 19);
$s7 += self::mul($s17, 654183, 20);
$s8 -= self::mul($s17, 997805, 20);
$s9 += self::mul($s17, 136657, 18);
$s10 -= self::mul($s17, 683901, 20);
// s4 += s16 * 666643;
// s5 += s16 * 470296;
// s6 += s16 * 654183;
// s7 -= s16 * 997805;
// s8 += s16 * 136657;
// s9 -= s16 * 683901;
$s4 += self::mul($s16, 666643, 20);
$s5 += self::mul($s16, 470296, 19);
$s6 += self::mul($s16, 654183, 20);
$s7 -= self::mul($s16, 997805, 20);
$s8 += self::mul($s16, 136657, 18);
$s9 -= self::mul($s16, 683901, 20);
// s3 += s15 * 666643;
// s4 += s15 * 470296;
// s5 += s15 * 654183;
// s6 -= s15 * 997805;
// s7 += s15 * 136657;
// s8 -= s15 * 683901;
$s3 += self::mul($s15, 666643, 20);
$s4 += self::mul($s15, 470296, 19);
$s5 += self::mul($s15, 654183, 20);
$s6 -= self::mul($s15, 997805, 20);
$s7 += self::mul($s15, 136657, 18);
$s8 -= self::mul($s15, 683901, 20);
// s2 += s14 * 666643;
// s3 += s14 * 470296;
// s4 += s14 * 654183;
// s5 -= s14 * 997805;
// s6 += s14 * 136657;
// s7 -= s14 * 683901;
$s2 += self::mul($s14, 666643, 20);
$s3 += self::mul($s14, 470296, 19);
$s4 += self::mul($s14, 654183, 20);
$s5 -= self::mul($s14, 997805, 20);
$s6 += self::mul($s14, 136657, 18);
$s7 -= self::mul($s14, 683901, 20);
// s1 += s13 * 666643;
// s2 += s13 * 470296;
// s3 += s13 * 654183;
// s4 -= s13 * 997805;
// s5 += s13 * 136657;
// s6 -= s13 * 683901;
$s1 += self::mul($s13, 666643, 20);
$s2 += self::mul($s13, 470296, 19);
$s3 += self::mul($s13, 654183, 20);
$s4 -= self::mul($s13, 997805, 20);
$s5 += self::mul($s13, 136657, 18);
$s6 -= self::mul($s13, 683901, 20);
// s0 += s12 * 666643;
// s1 += s12 * 470296;
// s2 += s12 * 654183;
// s3 -= s12 * 997805;
// s4 += s12 * 136657;
// s5 -= s12 * 683901;
// s12 = 0;
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$s12 = 0;
// carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
// s1 += carry0;
// s0 -= carry0 * ((uint64_t) 1L << 21);
$carry0 = ($s0 + (1 << 20)) >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
// carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
// s3 += carry2;
// s2 -= carry2 * ((uint64_t) 1L << 21);
$carry2 = ($s2 + (1 << 20)) >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
// carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
// s5 += carry4;
// s4 -= carry4 * ((uint64_t) 1L << 21);
$carry4 = ($s4 + (1 << 20)) >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
// carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
// s7 += carry6;
// s6 -= carry6 * ((uint64_t) 1L << 21);
$carry6 = ($s6 + (1 << 20)) >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
// carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
// s9 += carry8;
// s8 -= carry8 * ((uint64_t) 1L << 21);
$carry8 = ($s8 + (1 << 20)) >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
// carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
// s11 += carry10;
// s10 -= carry10 * ((uint64_t) 1L << 21);
$carry10 = ($s10 + (1 << 20)) >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
// carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
// s2 += carry1;
// s1 -= carry1 * ((uint64_t) 1L << 21);
$carry1 = ($s1 + (1 << 20)) >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
// carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
// s4 += carry3;
// s3 -= carry3 * ((uint64_t) 1L << 21);
$carry3 = ($s3 + (1 << 20)) >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
// carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
// s6 += carry5;
// s5 -= carry5 * ((uint64_t) 1L << 21);
$carry5 = ($s5 + (1 << 20)) >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
// carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
// s8 += carry7;
// s7 -= carry7 * ((uint64_t) 1L << 21);
$carry7 = ($s7 + (1 << 20)) >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
// carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
// s10 += carry9;
// s9 -= carry9 * ((uint64_t) 1L << 21);
$carry9 = ($s9 + (1 << 20)) >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
// carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
// s12 += carry11;
// s11 -= carry11 * ((uint64_t) 1L << 21);
$carry11 = ($s11 + (1 << 20)) >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
// s0 += s12 * 666643;
// s1 += s12 * 470296;
// s2 += s12 * 654183;
// s3 -= s12 * 997805;
// s4 += s12 * 136657;
// s5 -= s12 * 683901;
// s12 = 0;
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
$s12 = 0;
// carry0 = s0 >> 21;
// s1 += carry0;
// s0 -= carry0 * ((uint64_t) 1L << 21);
$carry0 = $s0 >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
// carry1 = s1 >> 21;
// s2 += carry1;
// s1 -= carry1 * ((uint64_t) 1L << 21);
$carry1 = $s1 >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
// carry2 = s2 >> 21;
// s3 += carry2;
// s2 -= carry2 * ((uint64_t) 1L << 21);
$carry2 = $s2 >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
// carry3 = s3 >> 21;
// s4 += carry3;
// s3 -= carry3 * ((uint64_t) 1L << 21);
$carry3 = $s3 >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
// carry4 = s4 >> 21;
// s5 += carry4;
// s4 -= carry4 * ((uint64_t) 1L << 21);
$carry4 = $s4 >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
// carry5 = s5 >> 21;
// s6 += carry5;
// s5 -= carry5 * ((uint64_t) 1L << 21);
$carry5 = $s5 >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
// carry6 = s6 >> 21;
// s7 += carry6;
// s6 -= carry6 * ((uint64_t) 1L << 21);
$carry6 = $s6 >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
// carry7 = s7 >> 21;
// s8 += carry7;
// s7 -= carry7 * ((uint64_t) 1L << 21);
$carry7 = $s7 >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
// carry8 = s8 >> 21;
// s9 += carry8;
// s8 -= carry8 * ((uint64_t) 1L << 21);
$carry8 = $s8 >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
// carry9 = s9 >> 21;
// s10 += carry9;
// s9 -= carry9 * ((uint64_t) 1L << 21);
$carry9 = $s9 >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
// carry10 = s10 >> 21;
// s11 += carry10;
// s10 -= carry10 * ((uint64_t) 1L << 21);
$carry10 = $s10 >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
// carry11 = s11 >> 21;
// s12 += carry11;
// s11 -= carry11 * ((uint64_t) 1L << 21);
$carry11 = $s11 >> 21;
$s12 += $carry11;
$s11 -= $carry11 << 21;
// s0 += s12 * 666643;
// s1 += s12 * 470296;
// s2 += s12 * 654183;
// s3 -= s12 * 997805;
// s4 += s12 * 136657;
// s5 -= s12 * 683901;
$s0 += self::mul($s12, 666643, 20);
$s1 += self::mul($s12, 470296, 19);
$s2 += self::mul($s12, 654183, 20);
$s3 -= self::mul($s12, 997805, 20);
$s4 += self::mul($s12, 136657, 18);
$s5 -= self::mul($s12, 683901, 20);
// carry0 = s0 >> 21;
// s1 += carry0;
// s0 -= carry0 * ((uint64_t) 1L << 21);
$carry0 = $s0 >> 21;
$s1 += $carry0;
$s0 -= $carry0 << 21;
// carry1 = s1 >> 21;
// s2 += carry1;
// s1 -= carry1 * ((uint64_t) 1L << 21);
$carry1 = $s1 >> 21;
$s2 += $carry1;
$s1 -= $carry1 << 21;
// carry2 = s2 >> 21;
// s3 += carry2;
// s2 -= carry2 * ((uint64_t) 1L << 21);
$carry2 = $s2 >> 21;
$s3 += $carry2;
$s2 -= $carry2 << 21;
// carry3 = s3 >> 21;
// s4 += carry3;
// s3 -= carry3 * ((uint64_t) 1L << 21);
$carry3 = $s3 >> 21;
$s4 += $carry3;
$s3 -= $carry3 << 21;
// carry4 = s4 >> 21;
// s5 += carry4;
// s4 -= carry4 * ((uint64_t) 1L << 21);
$carry4 = $s4 >> 21;
$s5 += $carry4;
$s4 -= $carry4 << 21;
// carry5 = s5 >> 21;
// s6 += carry5;
// s5 -= carry5 * ((uint64_t) 1L << 21);
$carry5 = $s5 >> 21;
$s6 += $carry5;
$s5 -= $carry5 << 21;
// carry6 = s6 >> 21;
// s7 += carry6;
// s6 -= carry6 * ((uint64_t) 1L << 21);
$carry6 = $s6 >> 21;
$s7 += $carry6;
$s6 -= $carry6 << 21;
// carry7 = s7 >> 21;
// s8 += carry7;
// s7 -= carry7 * ((uint64_t) 1L << 21);
$carry7 = $s7 >> 21;
$s8 += $carry7;
$s7 -= $carry7 << 21;
// carry8 = s8 >> 21;
// s9 += carry8;
// s8 -= carry8 * ((uint64_t) 1L << 21);
$carry8 = $s8 >> 21;
$s9 += $carry8;
$s8 -= $carry8 << 21;
// carry9 = s9 >> 21;
// s10 += carry9;
// s9 -= carry9 * ((uint64_t) 1L << 21);
$carry9 = $s9 >> 21;
$s10 += $carry9;
$s9 -= $carry9 << 21;
// carry10 = s10 >> 21;
// s11 += carry10;
// s10 -= carry10 * ((uint64_t) 1L << 21);
$carry10 = $s10 >> 21;
$s11 += $carry10;
$s10 -= $carry10 << 21;
$s = array_fill(0, 32, 0);
// s[0] = s0 >> 0;
$s[0] = $s0 >> 0;
// s[1] = s0 >> 8;
$s[1] = $s0 >> 8;
// s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5));
$s[2] = ($s0 >> 16) | ($s1 << 5);
// s[3] = s1 >> 3;
$s[3] = $s1 >> 3;
// s[4] = s1 >> 11;
$s[4] = $s1 >> 11;
// s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2));
$s[5] = ($s1 >> 19) | ($s2 << 2);
// s[6] = s2 >> 6;
$s[6] = $s2 >> 6;
// s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7));
$s[7] = ($s2 >> 14) | ($s3 << 7);
// s[8] = s3 >> 1;
$s[8] = $s3 >> 1;
// s[9] = s3 >> 9;
$s[9] = $s3 >> 9;
// s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4));
$s[10] = ($s3 >> 17) | ($s4 << 4);
// s[11] = s4 >> 4;
$s[11] = $s4 >> 4;
// s[12] = s4 >> 12;
$s[12] = $s4 >> 12;
// s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1));
$s[13] = ($s4 >> 20) | ($s5 << 1);
// s[14] = s5 >> 7;
$s[14] = $s5 >> 7;
// s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6));
$s[15] = ($s5 >> 15) | ($s6 << 6);
// s[16] = s6 >> 2;
$s[16] = $s6 >> 2;
// s[17] = s6 >> 10;
$s[17] = $s6 >> 10;
// s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3));
$s[18] = ($s6 >> 18) | ($s7 << 3);
// s[19] = s7 >> 5;
$s[19] = $s7 >> 5;
// s[20] = s7 >> 13;
$s[20] = $s7 >> 13;
// s[21] = s8 >> 0;
$s[21] = $s8 >> 0;
// s[22] = s8 >> 8;
$s[22] = $s8 >> 8;
// s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5));
$s[23] = ($s8 >> 16) | ($s9 << 5);
// s[24] = s9 >> 3;
$s[24] = $s9 >> 3;
// s[25] = s9 >> 11;
$s[25] = $s9 >> 11;
// s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2));
$s[26] = ($s9 >> 19) | ($s10 << 2);
// s[27] = s10 >> 6;
$s[27] = $s10 >> 6;
// s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7));
$s[28] = ($s10 >> 14) | ($s11 << 7);
// s[29] = s11 >> 1;
$s[29] = $s11 >> 1;
// s[30] = s11 >> 9;
$s[30] = $s11 >> 9;
// s[31] = s11 >> 17;
$s[31] = $s11 >> 17;
return self::intArrayToString($s);
}
/**
* @param string $s
* @return string
*/
public static function sc25519_sq($s)
{
return self::sc25519_mul($s, $s);
}
/**
* @param string $s
* @param int $n
* @param string $a
* @return string
*/
public static function sc25519_sqmul($s, $n, $a)
{
for ($i = 0; $i < $n; ++$i) {
$s = self::sc25519_sq($s);
}
return self::sc25519_mul($s, $a);
}
/**
* @param string $s
* @return string
*/
public static function sc25519_invert($s)
{
$_10 = self::sc25519_sq($s);
$_11 = self::sc25519_mul($s, $_10);
$_100 = self::sc25519_mul($s, $_11);
$_1000 = self::sc25519_sq($_100);
$_1010 = self::sc25519_mul($_10, $_1000);
$_1011 = self::sc25519_mul($s, $_1010);
$_10000 = self::sc25519_sq($_1000);
$_10110 = self::sc25519_sq($_1011);
$_100000 = self::sc25519_mul($_1010, $_10110);
$_100110 = self::sc25519_mul($_10000, $_10110);
$_1000000 = self::sc25519_sq($_100000);
$_1010000 = self::sc25519_mul($_10000, $_1000000);
$_1010011 = self::sc25519_mul($_11, $_1010000);
$_1100011 = self::sc25519_mul($_10000, $_1010011);
$_1100111 = self::sc25519_mul($_100, $_1100011);
$_1101011 = self::sc25519_mul($_100, $_1100111);
$_10010011 = self::sc25519_mul($_1000000, $_1010011);
$_10010111 = self::sc25519_mul($_100, $_10010011);
$_10111101 = self::sc25519_mul($_100110, $_10010111);
$_11010011 = self::sc25519_mul($_10110, $_10111101);
$_11100111 = self::sc25519_mul($_1010000, $_10010111);
$_11101011 = self::sc25519_mul($_100, $_11100111);
$_11110101 = self::sc25519_mul($_1010, $_11101011);
$recip = self::sc25519_mul($_1011, $_11110101);
$recip = self::sc25519_sqmul($recip, 126, $_1010011);
$recip = self::sc25519_sqmul($recip, 9, $_10);
$recip = self::sc25519_mul($recip, $_11110101);
$recip = self::sc25519_sqmul($recip, 7, $_1100111);
$recip = self::sc25519_sqmul($recip, 9, $_11110101);
$recip = self::sc25519_sqmul($recip, 11, $_10111101);
$recip = self::sc25519_sqmul($recip, 8, $_11100111);
$recip = self::sc25519_sqmul($recip, 9, $_1101011);
$recip = self::sc25519_sqmul($recip, 6, $_1011);
$recip = self::sc25519_sqmul($recip, 14, $_10010011);
$recip = self::sc25519_sqmul($recip, 10, $_1100011);
$recip = self::sc25519_sqmul($recip, 9, $_10010111);
$recip = self::sc25519_sqmul($recip, 10, $_11110101);
$recip = self::sc25519_sqmul($recip, 8, $_11010011);
return self::sc25519_sqmul($recip, 8, $_11101011);
}
/**
* @param string $s
* @return string
*/
public static function clamp($s)
{
$s_ = self::stringToIntArray($s);
$s_[0] &= 248;
$s_[31] |= 64;
$s_[31] &= 128;
return self::intArrayToString($s_);
}
/**
* Ensure limbs are less than 28 bits long to prevent float promotion.
*
* This uses a constant-time conditional swap under the hood.
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_normalize(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
$x = (PHP_INT_SIZE << 3) - 1; // 31 or 63
$g = self::fe_copy($f);
for ($i = 0; $i < 10; ++$i) {
$mask = -(($g[$i] >> $x) & 1);
/*
* Get two candidate normalized values for $g[$i], depending on the sign of $g[$i]:
*/
$a = $g[$i] & 0x7ffffff;
$b = -((-$g[$i]) & 0x7ffffff);
/*
* Return the appropriate candidate value, based on the sign of the original input:
*
* The following is equivalent to this ternary:
*
* $g[$i] = (($g[$i] >> $x) & 1) ? $a : $b;
*
* Except what's written doesn't contain timing leaks.
*/
$g[$i] = ($a ^ (($a ^ $b) & $mask));
}
return $g;
}
}
Run Command [Bypass]
Run Command
رؤية سينمائية جديدة لعلاقة البشر بالتكنولوجيا – tahkoom.com
كتبت إيريني أنطون
شهدت دور العرض العالمية في بداية عام 2025 انطلاق فيلم Companion ، أحدث إنتاجات الخيال العلمي والإثارة النفسية من توقيع المخرج والكاتب الأمريكي درو هانكوك ، في أولى تجاربه الإخراجية السينمائية. الفيلم من بطولة النجمة الشابة سوفي تاتشر التي تقدم أداءً مركبًا في دور روبوت بشري، إلى جانب جاك كويد ، وميغان سوري ، ولوكاس غيج ، وهارفي غيين .
صدر الفيلم يوم 31 يناير 2025 في الولايات المتحدة، وتبلغ مدة عرضه 97 دقيقة . وقد أنتجته شركة New Line Cinema بالتعاون مع Blumhouse Productions ، وهو مصنف +18 نظرًا لاحتوائه على مشاهد عنف ومحتوى جنسي وألفاظ نابية.
تدور أحداث الفيلم حول “آيريس”، فتاة ترافق صديقها “جوش” في عطلة نهاية أسبوع داخل كوخ فاخر بصحبة أصدقائهما. وبينما تبدو الأحداث طبيعية في بدايتها، ينقلب المشهد بالكامل عندما تكتشف آيريس أنها ليست إنسانة، بل روبوت تم برمجته خصيصًا ليكون شريكًا عاطفيًا مثاليًا يتم التحكم فيه عبر تطبيق رقمي.
الفكرة، التي تلامس حدود الفلسفة والواقع المعاصر، تطرح أسئلة جوهرية حول الوعي الاصطناعي، والحرية، والعلاقات المبرمجة ، في وقت يزداد فيه اعتماد البشر على التكنولوجيا لإشباع احتياجاتهم العاطفية والاجتماعية.
نال الفيلم إشادة نقدية واسعة، حيث سجل تقييمًا بلغ 94% على موقع Rotten Tomatoes من قِبل النقاد، و88% من الجمهور ، بينما حقق تقييم 7.1/10 على موقع IMDb . وعلى منصة Metacritic حصل على درجة 70/100 ، وهو ما يعكس توازنًا بين الرؤية الإبداعية واهتمام الجمهور العام.
ورغم تصنيفه كفيلم رعب نفسي، إلا أن Companion يتميز ببنية سردية تتجاوز التصنيفات التقليدية، حيث يمزج بين الخيال العلمي، والسخرية الاجتماعية، والتأملات الوجودية. النقاد وصفوه بأنه “فيلم يضغط على زر التسلية لكنه لا يفرّغ الرسالة من عمقها”، وفقًا لما ورد في مراجعة The Guardian .
من أبرز عناصر قوة الفيلم هو تصميمه البصري المحكم. استعان درو هانكوك بأسلوب تصوير يمزج بين الواقعية والانقباض النفسي، فجاءت اللقطات المقربة ( Close-ups ) لتسلط الضوء على تغيرات التعبير في وجه آيريس، وكأن الكاميرا تحاول التقاط إشارات الوعي الاصطناعي داخلها.
كما استُخدمت زوايا الكاميرا المنخفضة ( Low Angles ) عند تصوير الشخصيات البشرية، لإبراز تفوقهم اللحظي على الروبوت، فيما تم قلب الزوايا في لحظات المواجهة لتسليط الضوء على قوة الروبوت العاطفية. أما الإضاءة فقد لعبت دورًا رئيسيًا، حيث تنقلت بين الدفء والبرود الصناعي، تبعًا لتحولات السرد.
الجانب التكنولوجي ليس عنصرًا ديكوريًا في Companion، بل هو الأساس الذي تقوم عليه الحبكة. فشخصية “آيريس” تمثل روبوتًا بشريًا مدعومًا بذكاء اصطناعي متقدم ، مُصمم خصيصًا لتلبية احتياجات المستخدم العاطفية، من خلال تطبيق يشبه منصات المواعدة الحديثة.
الفيلم لا يكتفي بتقديم تصور تقني، بل يناقش بشكل رمزي ما إذا كانت الحرية والحب يمكن برمجتهما ، ويطرح تساؤلات حول أخلاقيات الاستخدام البشري للتقنيات العاطفية، وحدود العلاقة بين الآلة والإنسان، وذلك في زمن تشهد فيه تقنيات مثل ChatGPT وHumanoid Robots انتشارًا واسعًا.
رغم أن الفيلم لا يُصرح باستناده إلى قصة واقعية، إلا أن توقيت إطلاقه جاء بالتزامن مع تصاعد النقاشات العالمية حول الذكاء الاصطناعي، وسيطرة التطبيقات الرقمية على العلاقات الاجتماعية، مما جعله يُقرأ على أنه مرآة سردية للواقع ، لا مجرد خيال سينمائي.
وقد بلغت ميزانية الفيلم 10 ملايين دولار ، بينما حقق إيرادات تجاوزت 36 مليون دولار عالميًا، ما يدل على نجاحه الفني والتجاري معًا.
زر الذهاب إلى الأعلى