/htdocs/wp-includes/sodium_compat/src/Core32/Curve25519.php

https://gitlab.com/VTTE/sitios-vtte · PHP · 1270 lines · 837 code · 99 blank · 334 comment · 19 complexity · 1710a1f551e1724849b60c0170863a7f MD5 · raw file

  1. <?php
  2. if (class_exists('ParagonIE_Sodium_Core32_Curve25519', false)) {
  3. return;
  4. }
  5. /**
  6. * Class ParagonIE_Sodium_Core32_Curve25519
  7. *
  8. * Implements Curve25519 core functions
  9. *
  10. * Based on the ref10 curve25519 code provided by libsodium
  11. *
  12. * @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
  13. */
  14. abstract class ParagonIE_Sodium_Core32_Curve25519 extends ParagonIE_Sodium_Core32_Curve25519_H
  15. {
  16. /**
  17. * Get a field element of size 10 with a value of 0
  18. *
  19. * @internal You should not use this directly from another application
  20. *
  21. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  22. * @throws SodiumException
  23. * @throws TypeError
  24. */
  25. public static function fe_0()
  26. {
  27. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  28. array(
  29. new ParagonIE_Sodium_Core32_Int32(),
  30. new ParagonIE_Sodium_Core32_Int32(),
  31. new ParagonIE_Sodium_Core32_Int32(),
  32. new ParagonIE_Sodium_Core32_Int32(),
  33. new ParagonIE_Sodium_Core32_Int32(),
  34. new ParagonIE_Sodium_Core32_Int32(),
  35. new ParagonIE_Sodium_Core32_Int32(),
  36. new ParagonIE_Sodium_Core32_Int32(),
  37. new ParagonIE_Sodium_Core32_Int32(),
  38. new ParagonIE_Sodium_Core32_Int32()
  39. )
  40. );
  41. }
  42. /**
  43. * Get a field element of size 10 with a value of 1
  44. *
  45. * @internal You should not use this directly from another application
  46. *
  47. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  48. * @throws SodiumException
  49. * @throws TypeError
  50. */
  51. public static function fe_1()
  52. {
  53. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  54. array(
  55. ParagonIE_Sodium_Core32_Int32::fromInt(1),
  56. new ParagonIE_Sodium_Core32_Int32(),
  57. new ParagonIE_Sodium_Core32_Int32(),
  58. new ParagonIE_Sodium_Core32_Int32(),
  59. new ParagonIE_Sodium_Core32_Int32(),
  60. new ParagonIE_Sodium_Core32_Int32(),
  61. new ParagonIE_Sodium_Core32_Int32(),
  62. new ParagonIE_Sodium_Core32_Int32(),
  63. new ParagonIE_Sodium_Core32_Int32(),
  64. new ParagonIE_Sodium_Core32_Int32()
  65. )
  66. );
  67. }
  68. /**
  69. * Add two field elements.
  70. *
  71. * @internal You should not use this directly from another application
  72. *
  73. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  74. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
  75. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  76. * @throws SodiumException
  77. * @throws TypeError
  78. * @psalm-suppress MixedAssignment
  79. * @psalm-suppress MixedMethodCall
  80. */
  81. public static function fe_add(
  82. ParagonIE_Sodium_Core32_Curve25519_Fe $f,
  83. ParagonIE_Sodium_Core32_Curve25519_Fe $g
  84. ) {
  85. $arr = array();
  86. for ($i = 0; $i < 10; ++$i) {
  87. $arr[$i] = $f[$i]->addInt32($g[$i]);
  88. }
  89. /** @var array<int, ParagonIE_Sodium_Core32_Int32> $arr */
  90. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($arr);
  91. }
  92. /**
  93. * Constant-time conditional move.
  94. *
  95. * @internal You should not use this directly from another application
  96. *
  97. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  98. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
  99. * @param int $b
  100. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  101. * @throws SodiumException
  102. * @throws TypeError
  103. * @psalm-suppress MixedAssignment
  104. * @psalm-suppress MixedMethodCall
  105. */
  106. public static function fe_cmov(
  107. ParagonIE_Sodium_Core32_Curve25519_Fe $f,
  108. ParagonIE_Sodium_Core32_Curve25519_Fe $g,
  109. $b = 0
  110. ) {
  111. /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
  112. $h = array();
  113. for ($i = 0; $i < 10; ++$i) {
  114. if (!($f[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
  115. throw new TypeError('Expected Int32');
  116. }
  117. if (!($g[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
  118. throw new TypeError('Expected Int32');
  119. }
  120. $h[$i] = $f[$i]->xorInt32(
  121. $f[$i]->xorInt32($g[$i])->mask($b)
  122. );
  123. }
  124. /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
  125. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h);
  126. }
  127. /**
  128. * Create a copy of a field element.
  129. *
  130. * @internal You should not use this directly from another application
  131. *
  132. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  133. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  134. */
  135. public static function fe_copy(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
  136. {
  137. $h = clone $f;
  138. return $h;
  139. }
  140. /**
  141. * Give: 32-byte string.
  142. * Receive: A field element object to use for internal calculations.
  143. *
  144. * @internal You should not use this directly from another application
  145. *
  146. * @param string $s
  147. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  148. * @throws RangeException
  149. * @throws SodiumException
  150. * @throws TypeError
  151. * @psalm-suppress MixedMethodCall
  152. */
  153. public static function fe_frombytes($s)
  154. {
  155. if (self::strlen($s) !== 32) {
  156. throw new RangeException('Expected a 32-byte string.');
  157. }
  158. /** @var ParagonIE_Sodium_Core32_Int32 $h0 */
  159. $h0 = ParagonIE_Sodium_Core32_Int32::fromInt(
  160. self::load_4($s)
  161. );
  162. /** @var ParagonIE_Sodium_Core32_Int32 $h1 */
  163. $h1 = ParagonIE_Sodium_Core32_Int32::fromInt(
  164. self::load_3(self::substr($s, 4, 3)) << 6
  165. );
  166. /** @var ParagonIE_Sodium_Core32_Int32 $h2 */
  167. $h2 = ParagonIE_Sodium_Core32_Int32::fromInt(
  168. self::load_3(self::substr($s, 7, 3)) << 5
  169. );
  170. /** @var ParagonIE_Sodium_Core32_Int32 $h3 */
  171. $h3 = ParagonIE_Sodium_Core32_Int32::fromInt(
  172. self::load_3(self::substr($s, 10, 3)) << 3
  173. );
  174. /** @var ParagonIE_Sodium_Core32_Int32 $h4 */
  175. $h4 = ParagonIE_Sodium_Core32_Int32::fromInt(
  176. self::load_3(self::substr($s, 13, 3)) << 2
  177. );
  178. /** @var ParagonIE_Sodium_Core32_Int32 $h5 */
  179. $h5 = ParagonIE_Sodium_Core32_Int32::fromInt(
  180. self::load_4(self::substr($s, 16, 4))
  181. );
  182. /** @var ParagonIE_Sodium_Core32_Int32 $h6 */
  183. $h6 = ParagonIE_Sodium_Core32_Int32::fromInt(
  184. self::load_3(self::substr($s, 20, 3)) << 7
  185. );
  186. /** @var ParagonIE_Sodium_Core32_Int32 $h7 */
  187. $h7 = ParagonIE_Sodium_Core32_Int32::fromInt(
  188. self::load_3(self::substr($s, 23, 3)) << 5
  189. );
  190. /** @var ParagonIE_Sodium_Core32_Int32 $h8 */
  191. $h8 = ParagonIE_Sodium_Core32_Int32::fromInt(
  192. self::load_3(self::substr($s, 26, 3)) << 4
  193. );
  194. /** @var ParagonIE_Sodium_Core32_Int32 $h9 */
  195. $h9 = ParagonIE_Sodium_Core32_Int32::fromInt(
  196. (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2
  197. );
  198. $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
  199. $h0 = $h0->addInt32($carry9->mulInt(19, 5));
  200. $h9 = $h9->subInt32($carry9->shiftLeft(25));
  201. $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
  202. $h2 = $h2->addInt32($carry1);
  203. $h1 = $h1->subInt32($carry1->shiftLeft(25));
  204. $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
  205. $h4 = $h4->addInt32($carry3);
  206. $h3 = $h3->subInt32($carry3->shiftLeft(25));
  207. $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
  208. $h6 = $h6->addInt32($carry5);
  209. $h5 = $h5->subInt32($carry5->shiftLeft(25));
  210. $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
  211. $h8 = $h8->addInt32($carry7);
  212. $h7 = $h7->subInt32($carry7->shiftLeft(25));
  213. $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
  214. $h1 = $h1->addInt32($carry0);
  215. $h0 = $h0->subInt32($carry0->shiftLeft(26));
  216. $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
  217. $h3 = $h3->addInt32($carry2);
  218. $h2 = $h2->subInt32($carry2->shiftLeft(26));
  219. $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
  220. $h5 = $h5->addInt32($carry4);
  221. $h4 = $h4->subInt32($carry4->shiftLeft(26));
  222. $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
  223. $h7 = $h7->addInt32($carry6);
  224. $h6 = $h6->subInt32($carry6->shiftLeft(26));
  225. $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
  226. $h9 = $h9->addInt32($carry8);
  227. $h8 = $h8->subInt32($carry8->shiftLeft(26));
  228. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  229. array($h0, $h1, $h2,$h3, $h4, $h5, $h6, $h7, $h8, $h9)
  230. );
  231. }
  232. /**
  233. * Convert a field element to a byte string.
  234. *
  235. * @internal You should not use this directly from another application
  236. *
  237. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $h
  238. * @return string
  239. * @throws SodiumException
  240. * @throws TypeError
  241. * @psalm-suppress MixedAssignment
  242. * @psalm-suppress MixedMethodCall
  243. */
  244. public static function fe_tobytes(ParagonIE_Sodium_Core32_Curve25519_Fe $h)
  245. {
  246. /**
  247. * @var ParagonIE_Sodium_Core32_Int64[] $f
  248. * @var ParagonIE_Sodium_Core32_Int64 $q
  249. */
  250. $f = array();
  251. for ($i = 0; $i < 10; ++$i) {
  252. $f[$i] = $h[$i]->toInt64();
  253. }
  254. $q = $f[9]->mulInt(19, 5)->addInt(1 << 14)->shiftRight(25)
  255. ->addInt64($f[0])->shiftRight(26)
  256. ->addInt64($f[1])->shiftRight(25)
  257. ->addInt64($f[2])->shiftRight(26)
  258. ->addInt64($f[3])->shiftRight(25)
  259. ->addInt64($f[4])->shiftRight(26)
  260. ->addInt64($f[5])->shiftRight(25)
  261. ->addInt64($f[6])->shiftRight(26)
  262. ->addInt64($f[7])->shiftRight(25)
  263. ->addInt64($f[8])->shiftRight(26)
  264. ->addInt64($f[9])->shiftRight(25);
  265. $f[0] = $f[0]->addInt64($q->mulInt(19, 5));
  266. $carry0 = $f[0]->shiftRight(26);
  267. $f[1] = $f[1]->addInt64($carry0);
  268. $f[0] = $f[0]->subInt64($carry0->shiftLeft(26));
  269. $carry1 = $f[1]->shiftRight(25);
  270. $f[2] = $f[2]->addInt64($carry1);
  271. $f[1] = $f[1]->subInt64($carry1->shiftLeft(25));
  272. $carry2 = $f[2]->shiftRight(26);
  273. $f[3] = $f[3]->addInt64($carry2);
  274. $f[2] = $f[2]->subInt64($carry2->shiftLeft(26));
  275. $carry3 = $f[3]->shiftRight(25);
  276. $f[4] = $f[4]->addInt64($carry3);
  277. $f[3] = $f[3]->subInt64($carry3->shiftLeft(25));
  278. $carry4 = $f[4]->shiftRight(26);
  279. $f[5] = $f[5]->addInt64($carry4);
  280. $f[4] = $f[4]->subInt64($carry4->shiftLeft(26));
  281. $carry5 = $f[5]->shiftRight(25);
  282. $f[6] = $f[6]->addInt64($carry5);
  283. $f[5] = $f[5]->subInt64($carry5->shiftLeft(25));
  284. $carry6 = $f[6]->shiftRight(26);
  285. $f[7] = $f[7]->addInt64($carry6);
  286. $f[6] = $f[6]->subInt64($carry6->shiftLeft(26));
  287. $carry7 = $f[7]->shiftRight(25);
  288. $f[8] = $f[8]->addInt64($carry7);
  289. $f[7] = $f[7]->subInt64($carry7->shiftLeft(25));
  290. $carry8 = $f[8]->shiftRight(26);
  291. $f[9] = $f[9]->addInt64($carry8);
  292. $f[8] = $f[8]->subInt64($carry8->shiftLeft(26));
  293. $carry9 = $f[9]->shiftRight(25);
  294. $f[9] = $f[9]->subInt64($carry9->shiftLeft(25));
  295. /** @var int $h0 */
  296. $h0 = $f[0]->toInt32()->toInt();
  297. /** @var int $h1 */
  298. $h1 = $f[1]->toInt32()->toInt();
  299. /** @var int $h2 */
  300. $h2 = $f[2]->toInt32()->toInt();
  301. /** @var int $h3 */
  302. $h3 = $f[3]->toInt32()->toInt();
  303. /** @var int $h4 */
  304. $h4 = $f[4]->toInt32()->toInt();
  305. /** @var int $h5 */
  306. $h5 = $f[5]->toInt32()->toInt();
  307. /** @var int $h6 */
  308. $h6 = $f[6]->toInt32()->toInt();
  309. /** @var int $h7 */
  310. $h7 = $f[7]->toInt32()->toInt();
  311. /** @var int $h8 */
  312. $h8 = $f[8]->toInt32()->toInt();
  313. /** @var int $h9 */
  314. $h9 = $f[9]->toInt32()->toInt();
  315. /**
  316. * @var array<int, int>
  317. */
  318. $s = array(
  319. (int) (($h0 >> 0) & 0xff),
  320. (int) (($h0 >> 8) & 0xff),
  321. (int) (($h0 >> 16) & 0xff),
  322. (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
  323. (int) (($h1 >> 6) & 0xff),
  324. (int) (($h1 >> 14) & 0xff),
  325. (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
  326. (int) (($h2 >> 5) & 0xff),
  327. (int) (($h2 >> 13) & 0xff),
  328. (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
  329. (int) (($h3 >> 3) & 0xff),
  330. (int) (($h3 >> 11) & 0xff),
  331. (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
  332. (int) (($h4 >> 2) & 0xff),
  333. (int) (($h4 >> 10) & 0xff),
  334. (int) (($h4 >> 18) & 0xff),
  335. (int) (($h5 >> 0) & 0xff),
  336. (int) (($h5 >> 8) & 0xff),
  337. (int) (($h5 >> 16) & 0xff),
  338. (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
  339. (int) (($h6 >> 7) & 0xff),
  340. (int) (($h6 >> 15) & 0xff),
  341. (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
  342. (int) (($h7 >> 5) & 0xff),
  343. (int) (($h7 >> 13) & 0xff),
  344. (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
  345. (int) (($h8 >> 4) & 0xff),
  346. (int) (($h8 >> 12) & 0xff),
  347. (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
  348. (int) (($h9 >> 2) & 0xff),
  349. (int) (($h9 >> 10) & 0xff),
  350. (int) (($h9 >> 18) & 0xff)
  351. );
  352. return self::intArrayToString($s);
  353. }
  354. /**
  355. * Is a field element negative? (1 = yes, 0 = no. Used in calculations.)
  356. *
  357. * @internal You should not use this directly from another application
  358. *
  359. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  360. * @return int
  361. * @throws SodiumException
  362. * @throws TypeError
  363. */
  364. public static function fe_isnegative(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
  365. {
  366. $str = self::fe_tobytes($f);
  367. return (int) (self::chrToInt($str[0]) & 1);
  368. }
  369. /**
  370. * Returns 0 if this field element results in all NUL bytes.
  371. *
  372. * @internal You should not use this directly from another application
  373. *
  374. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  375. * @return bool
  376. * @throws SodiumException
  377. * @throws TypeError
  378. */
  379. public static function fe_isnonzero(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
  380. {
  381. static $zero;
  382. if ($zero === null) {
  383. $zero = str_repeat("\x00", 32);
  384. }
  385. /** @var string $str */
  386. $str = self::fe_tobytes($f);
  387. /** @var string $zero */
  388. return !self::verify_32($str, $zero);
  389. }
  390. /**
  391. * Multiply two field elements
  392. *
  393. * h = f * g
  394. *
  395. * @internal You should not use this directly from another application
  396. *
  397. * @security Is multiplication a source of timing leaks? If so, can we do
  398. * anything to prevent that from happening?
  399. *
  400. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  401. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
  402. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  403. * @throws SodiumException
  404. * @throws TypeError
  405. */
  406. public static function fe_mul(
  407. ParagonIE_Sodium_Core32_Curve25519_Fe $f,
  408. ParagonIE_Sodium_Core32_Curve25519_Fe $g
  409. ) {
  410. /**
  411. * @var ParagonIE_Sodium_Core32_Int32[] $f
  412. * @var ParagonIE_Sodium_Core32_Int32[] $g
  413. * @var ParagonIE_Sodium_Core32_Int64 $f0
  414. * @var ParagonIE_Sodium_Core32_Int64 $f1
  415. * @var ParagonIE_Sodium_Core32_Int64 $f2
  416. * @var ParagonIE_Sodium_Core32_Int64 $f3
  417. * @var ParagonIE_Sodium_Core32_Int64 $f4
  418. * @var ParagonIE_Sodium_Core32_Int64 $f5
  419. * @var ParagonIE_Sodium_Core32_Int64 $f6
  420. * @var ParagonIE_Sodium_Core32_Int64 $f7
  421. * @var ParagonIE_Sodium_Core32_Int64 $f8
  422. * @var ParagonIE_Sodium_Core32_Int64 $f9
  423. * @var ParagonIE_Sodium_Core32_Int64 $g0
  424. * @var ParagonIE_Sodium_Core32_Int64 $g1
  425. * @var ParagonIE_Sodium_Core32_Int64 $g2
  426. * @var ParagonIE_Sodium_Core32_Int64 $g3
  427. * @var ParagonIE_Sodium_Core32_Int64 $g4
  428. * @var ParagonIE_Sodium_Core32_Int64 $g5
  429. * @var ParagonIE_Sodium_Core32_Int64 $g6
  430. * @var ParagonIE_Sodium_Core32_Int64 $g7
  431. * @var ParagonIE_Sodium_Core32_Int64 $g8
  432. * @var ParagonIE_Sodium_Core32_Int64 $g9
  433. */
  434. $f0 = $f[0]->toInt64();
  435. $f1 = $f[1]->toInt64();
  436. $f2 = $f[2]->toInt64();
  437. $f3 = $f[3]->toInt64();
  438. $f4 = $f[4]->toInt64();
  439. $f5 = $f[5]->toInt64();
  440. $f6 = $f[6]->toInt64();
  441. $f7 = $f[7]->toInt64();
  442. $f8 = $f[8]->toInt64();
  443. $f9 = $f[9]->toInt64();
  444. $g0 = $g[0]->toInt64();
  445. $g1 = $g[1]->toInt64();
  446. $g2 = $g[2]->toInt64();
  447. $g3 = $g[3]->toInt64();
  448. $g4 = $g[4]->toInt64();
  449. $g5 = $g[5]->toInt64();
  450. $g6 = $g[6]->toInt64();
  451. $g7 = $g[7]->toInt64();
  452. $g8 = $g[8]->toInt64();
  453. $g9 = $g[9]->toInt64();
  454. $g1_19 = $g1->mulInt(19, 5); /* 2^4 <= 19 <= 2^5, but we only want 5 bits */
  455. $g2_19 = $g2->mulInt(19, 5);
  456. $g3_19 = $g3->mulInt(19, 5);
  457. $g4_19 = $g4->mulInt(19, 5);
  458. $g5_19 = $g5->mulInt(19, 5);
  459. $g6_19 = $g6->mulInt(19, 5);
  460. $g7_19 = $g7->mulInt(19, 5);
  461. $g8_19 = $g8->mulInt(19, 5);
  462. $g9_19 = $g9->mulInt(19, 5);
  463. /** @var ParagonIE_Sodium_Core32_Int64 $f1_2 */
  464. $f1_2 = $f1->shiftLeft(1);
  465. /** @var ParagonIE_Sodium_Core32_Int64 $f3_2 */
  466. $f3_2 = $f3->shiftLeft(1);
  467. /** @var ParagonIE_Sodium_Core32_Int64 $f5_2 */
  468. $f5_2 = $f5->shiftLeft(1);
  469. /** @var ParagonIE_Sodium_Core32_Int64 $f7_2 */
  470. $f7_2 = $f7->shiftLeft(1);
  471. /** @var ParagonIE_Sodium_Core32_Int64 $f9_2 */
  472. $f9_2 = $f9->shiftLeft(1);
  473. $f0g0 = $f0->mulInt64($g0, 27);
  474. $f0g1 = $f0->mulInt64($g1, 27);
  475. $f0g2 = $f0->mulInt64($g2, 27);
  476. $f0g3 = $f0->mulInt64($g3, 27);
  477. $f0g4 = $f0->mulInt64($g4, 27);
  478. $f0g5 = $f0->mulInt64($g5, 27);
  479. $f0g6 = $f0->mulInt64($g6, 27);
  480. $f0g7 = $f0->mulInt64($g7, 27);
  481. $f0g8 = $f0->mulInt64($g8, 27);
  482. $f0g9 = $f0->mulInt64($g9, 27);
  483. $f1g0 = $f1->mulInt64($g0, 27);
  484. $f1g1_2 = $f1_2->mulInt64($g1, 27);
  485. $f1g2 = $f1->mulInt64($g2, 27);
  486. $f1g3_2 = $f1_2->mulInt64($g3, 27);
  487. $f1g4 = $f1->mulInt64($g4, 30);
  488. $f1g5_2 = $f1_2->mulInt64($g5, 30);
  489. $f1g6 = $f1->mulInt64($g6, 30);
  490. $f1g7_2 = $f1_2->mulInt64($g7, 30);
  491. $f1g8 = $f1->mulInt64($g8, 30);
  492. $f1g9_38 = $g9_19->mulInt64($f1_2, 30);
  493. $f2g0 = $f2->mulInt64($g0, 30);
  494. $f2g1 = $f2->mulInt64($g1, 29);
  495. $f2g2 = $f2->mulInt64($g2, 30);
  496. $f2g3 = $f2->mulInt64($g3, 29);
  497. $f2g4 = $f2->mulInt64($g4, 30);
  498. $f2g5 = $f2->mulInt64($g5, 29);
  499. $f2g6 = $f2->mulInt64($g6, 30);
  500. $f2g7 = $f2->mulInt64($g7, 29);
  501. $f2g8_19 = $g8_19->mulInt64($f2, 30);
  502. $f2g9_19 = $g9_19->mulInt64($f2, 30);
  503. $f3g0 = $f3->mulInt64($g0, 30);
  504. $f3g1_2 = $f3_2->mulInt64($g1, 30);
  505. $f3g2 = $f3->mulInt64($g2, 30);
  506. $f3g3_2 = $f3_2->mulInt64($g3, 30);
  507. $f3g4 = $f3->mulInt64($g4, 30);
  508. $f3g5_2 = $f3_2->mulInt64($g5, 30);
  509. $f3g6 = $f3->mulInt64($g6, 30);
  510. $f3g7_38 = $g7_19->mulInt64($f3_2, 30);
  511. $f3g8_19 = $g8_19->mulInt64($f3, 30);
  512. $f3g9_38 = $g9_19->mulInt64($f3_2, 30);
  513. $f4g0 = $f4->mulInt64($g0, 30);
  514. $f4g1 = $f4->mulInt64($g1, 30);
  515. $f4g2 = $f4->mulInt64($g2, 30);
  516. $f4g3 = $f4->mulInt64($g3, 30);
  517. $f4g4 = $f4->mulInt64($g4, 30);
  518. $f4g5 = $f4->mulInt64($g5, 30);
  519. $f4g6_19 = $g6_19->mulInt64($f4, 30);
  520. $f4g7_19 = $g7_19->mulInt64($f4, 30);
  521. $f4g8_19 = $g8_19->mulInt64($f4, 30);
  522. $f4g9_19 = $g9_19->mulInt64($f4, 30);
  523. $f5g0 = $f5->mulInt64($g0, 30);
  524. $f5g1_2 = $f5_2->mulInt64($g1, 30);
  525. $f5g2 = $f5->mulInt64($g2, 30);
  526. $f5g3_2 = $f5_2->mulInt64($g3, 30);
  527. $f5g4 = $f5->mulInt64($g4, 30);
  528. $f5g5_38 = $g5_19->mulInt64($f5_2, 30);
  529. $f5g6_19 = $g6_19->mulInt64($f5, 30);
  530. $f5g7_38 = $g7_19->mulInt64($f5_2, 30);
  531. $f5g8_19 = $g8_19->mulInt64($f5, 30);
  532. $f5g9_38 = $g9_19->mulInt64($f5_2, 30);
  533. $f6g0 = $f6->mulInt64($g0, 30);
  534. $f6g1 = $f6->mulInt64($g1, 30);
  535. $f6g2 = $f6->mulInt64($g2, 30);
  536. $f6g3 = $f6->mulInt64($g3, 30);
  537. $f6g4_19 = $g4_19->mulInt64($f6, 30);
  538. $f6g5_19 = $g5_19->mulInt64($f6, 30);
  539. $f6g6_19 = $g6_19->mulInt64($f6, 30);
  540. $f6g7_19 = $g7_19->mulInt64($f6, 30);
  541. $f6g8_19 = $g8_19->mulInt64($f6, 30);
  542. $f6g9_19 = $g9_19->mulInt64($f6, 30);
  543. $f7g0 = $f7->mulInt64($g0, 30);
  544. $f7g1_2 = $g1->mulInt64($f7_2, 30);
  545. $f7g2 = $f7->mulInt64($g2, 30);
  546. $f7g3_38 = $g3_19->mulInt64($f7_2, 30);
  547. $f7g4_19 = $g4_19->mulInt64($f7, 30);
  548. $f7g5_38 = $g5_19->mulInt64($f7_2, 30);
  549. $f7g6_19 = $g6_19->mulInt64($f7, 30);
  550. $f7g7_38 = $g7_19->mulInt64($f7_2, 30);
  551. $f7g8_19 = $g8_19->mulInt64($f7, 30);
  552. $f7g9_38 = $g9_19->mulInt64($f7_2, 30);
  553. $f8g0 = $f8->mulInt64($g0, 30);
  554. $f8g1 = $f8->mulInt64($g1, 29);
  555. $f8g2_19 = $g2_19->mulInt64($f8, 30);
  556. $f8g3_19 = $g3_19->mulInt64($f8, 30);
  557. $f8g4_19 = $g4_19->mulInt64($f8, 30);
  558. $f8g5_19 = $g5_19->mulInt64($f8, 30);
  559. $f8g6_19 = $g6_19->mulInt64($f8, 30);
  560. $f8g7_19 = $g7_19->mulInt64($f8, 30);
  561. $f8g8_19 = $g8_19->mulInt64($f8, 30);
  562. $f8g9_19 = $g9_19->mulInt64($f8, 30);
  563. $f9g0 = $f9->mulInt64($g0, 30);
  564. $f9g1_38 = $g1_19->mulInt64($f9_2, 30);
  565. $f9g2_19 = $g2_19->mulInt64($f9, 30);
  566. $f9g3_38 = $g3_19->mulInt64($f9_2, 30);
  567. $f9g4_19 = $g4_19->mulInt64($f9, 30);
  568. $f9g5_38 = $g5_19->mulInt64($f9_2, 30);
  569. $f9g6_19 = $g6_19->mulInt64($f9, 30);
  570. $f9g7_38 = $g7_19->mulInt64($f9_2, 30);
  571. $f9g8_19 = $g8_19->mulInt64($f9, 30);
  572. $f9g9_38 = $g9_19->mulInt64($f9_2, 30);
  573. // $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
  574. $h0 = $f0g0->addInt64($f1g9_38)->addInt64($f2g8_19)->addInt64($f3g7_38)
  575. ->addInt64($f4g6_19)->addInt64($f5g5_38)->addInt64($f6g4_19)
  576. ->addInt64($f7g3_38)->addInt64($f8g2_19)->addInt64($f9g1_38);
  577. // $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
  578. $h1 = $f0g1->addInt64($f1g0)->addInt64($f2g9_19)->addInt64($f3g8_19)
  579. ->addInt64($f4g7_19)->addInt64($f5g6_19)->addInt64($f6g5_19)
  580. ->addInt64($f7g4_19)->addInt64($f8g3_19)->addInt64($f9g2_19);
  581. // $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
  582. $h2 = $f0g2->addInt64($f1g1_2)->addInt64($f2g0)->addInt64($f3g9_38)
  583. ->addInt64($f4g8_19)->addInt64($f5g7_38)->addInt64($f6g6_19)
  584. ->addInt64($f7g5_38)->addInt64($f8g4_19)->addInt64($f9g3_38);
  585. // $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
  586. $h3 = $f0g3->addInt64($f1g2)->addInt64($f2g1)->addInt64($f3g0)
  587. ->addInt64($f4g9_19)->addInt64($f5g8_19)->addInt64($f6g7_19)
  588. ->addInt64($f7g6_19)->addInt64($f8g5_19)->addInt64($f9g4_19);
  589. // $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
  590. $h4 = $f0g4->addInt64($f1g3_2)->addInt64($f2g2)->addInt64($f3g1_2)
  591. ->addInt64($f4g0)->addInt64($f5g9_38)->addInt64($f6g8_19)
  592. ->addInt64($f7g7_38)->addInt64($f8g6_19)->addInt64($f9g5_38);
  593. // $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
  594. $h5 = $f0g5->addInt64($f1g4)->addInt64($f2g3)->addInt64($f3g2)
  595. ->addInt64($f4g1)->addInt64($f5g0)->addInt64($f6g9_19)
  596. ->addInt64($f7g8_19)->addInt64($f8g7_19)->addInt64($f9g6_19);
  597. // $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38;
  598. $h6 = $f0g6->addInt64($f1g5_2)->addInt64($f2g4)->addInt64($f3g3_2)
  599. ->addInt64($f4g2)->addInt64($f5g1_2)->addInt64($f6g0)
  600. ->addInt64($f7g9_38)->addInt64($f8g8_19)->addInt64($f9g7_38);
  601. // $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19;
  602. $h7 = $f0g7->addInt64($f1g6)->addInt64($f2g5)->addInt64($f3g4)
  603. ->addInt64($f4g3)->addInt64($f5g2)->addInt64($f6g1)
  604. ->addInt64($f7g0)->addInt64($f8g9_19)->addInt64($f9g8_19);
  605. // $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38;
  606. $h8 = $f0g8->addInt64($f1g7_2)->addInt64($f2g6)->addInt64($f3g5_2)
  607. ->addInt64($f4g4)->addInt64($f5g3_2)->addInt64($f6g2)
  608. ->addInt64($f7g1_2)->addInt64($f8g0)->addInt64($f9g9_38);
  609. // $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ;
  610. $h9 = $f0g9->addInt64($f1g8)->addInt64($f2g7)->addInt64($f3g6)
  611. ->addInt64($f4g5)->addInt64($f5g4)->addInt64($f6g3)
  612. ->addInt64($f7g2)->addInt64($f8g1)->addInt64($f9g0);
  613. /**
  614. * @var ParagonIE_Sodium_Core32_Int64 $h0
  615. * @var ParagonIE_Sodium_Core32_Int64 $h1
  616. * @var ParagonIE_Sodium_Core32_Int64 $h2
  617. * @var ParagonIE_Sodium_Core32_Int64 $h3
  618. * @var ParagonIE_Sodium_Core32_Int64 $h4
  619. * @var ParagonIE_Sodium_Core32_Int64 $h5
  620. * @var ParagonIE_Sodium_Core32_Int64 $h6
  621. * @var ParagonIE_Sodium_Core32_Int64 $h7
  622. * @var ParagonIE_Sodium_Core32_Int64 $h8
  623. * @var ParagonIE_Sodium_Core32_Int64 $h9
  624. * @var ParagonIE_Sodium_Core32_Int64 $carry0
  625. * @var ParagonIE_Sodium_Core32_Int64 $carry1
  626. * @var ParagonIE_Sodium_Core32_Int64 $carry2
  627. * @var ParagonIE_Sodium_Core32_Int64 $carry3
  628. * @var ParagonIE_Sodium_Core32_Int64 $carry4
  629. * @var ParagonIE_Sodium_Core32_Int64 $carry5
  630. * @var ParagonIE_Sodium_Core32_Int64 $carry6
  631. * @var ParagonIE_Sodium_Core32_Int64 $carry7
  632. * @var ParagonIE_Sodium_Core32_Int64 $carry8
  633. * @var ParagonIE_Sodium_Core32_Int64 $carry9
  634. */
  635. $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
  636. $h1 = $h1->addInt64($carry0);
  637. $h0 = $h0->subInt64($carry0->shiftLeft(26));
  638. $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
  639. $h5 = $h5->addInt64($carry4);
  640. $h4 = $h4->subInt64($carry4->shiftLeft(26));
  641. $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
  642. $h2 = $h2->addInt64($carry1);
  643. $h1 = $h1->subInt64($carry1->shiftLeft(25));
  644. $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
  645. $h6 = $h6->addInt64($carry5);
  646. $h5 = $h5->subInt64($carry5->shiftLeft(25));
  647. $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
  648. $h3 = $h3->addInt64($carry2);
  649. $h2 = $h2->subInt64($carry2->shiftLeft(26));
  650. $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
  651. $h7 = $h7->addInt64($carry6);
  652. $h6 = $h6->subInt64($carry6->shiftLeft(26));
  653. $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
  654. $h4 = $h4->addInt64($carry3);
  655. $h3 = $h3->subInt64($carry3->shiftLeft(25));
  656. $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
  657. $h8 = $h8->addInt64($carry7);
  658. $h7 = $h7->subInt64($carry7->shiftLeft(25));
  659. $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
  660. $h5 = $h5->addInt64($carry4);
  661. $h4 = $h4->subInt64($carry4->shiftLeft(26));
  662. $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
  663. $h9 = $h9->addInt64($carry8);
  664. $h8 = $h8->subInt64($carry8->shiftLeft(26));
  665. $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
  666. $h0 = $h0->addInt64($carry9->mulInt(19, 5));
  667. $h9 = $h9->subInt64($carry9->shiftLeft(25));
  668. $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
  669. $h1 = $h1->addInt64($carry0);
  670. $h0 = $h0->subInt64($carry0->shiftLeft(26));
  671. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  672. array(
  673. $h0->toInt32(),
  674. $h1->toInt32(),
  675. $h2->toInt32(),
  676. $h3->toInt32(),
  677. $h4->toInt32(),
  678. $h5->toInt32(),
  679. $h6->toInt32(),
  680. $h7->toInt32(),
  681. $h8->toInt32(),
  682. $h9->toInt32()
  683. )
  684. );
  685. }
  686. /**
  687. * Get the negative values for each piece of the field element.
  688. *
  689. * h = -f
  690. *
  691. * @internal You should not use this directly from another application
  692. *
  693. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  694. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  695. * @psalm-suppress MixedAssignment
  696. * @psalm-suppress MixedMethodCall
  697. */
  698. public static function fe_neg(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
  699. {
  700. $h = new ParagonIE_Sodium_Core32_Curve25519_Fe();
  701. for ($i = 0; $i < 10; ++$i) {
  702. $h[$i] = $h[$i]->subInt32($f[$i]);
  703. }
  704. return $h;
  705. }
  706. /**
  707. * Square a field element
  708. *
  709. * h = f * f
  710. *
  711. * @internal You should not use this directly from another application
  712. *
  713. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  714. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  715. * @throws SodiumException
  716. * @throws TypeError
  717. * @psalm-suppress MixedMethodCall
  718. */
  719. public static function fe_sq(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
  720. {
  721. /** @var ParagonIE_Sodium_Core32_Int64 $f0 */
  722. $f0 = $f[0]->toInt64();
  723. /** @var ParagonIE_Sodium_Core32_Int64 $f1 */
  724. $f1 = $f[1]->toInt64();
  725. /** @var ParagonIE_Sodium_Core32_Int64 $f2 */
  726. $f2 = $f[2]->toInt64();
  727. /** @var ParagonIE_Sodium_Core32_Int64 $f3 */
  728. $f3 = $f[3]->toInt64();
  729. /** @var ParagonIE_Sodium_Core32_Int64 $f4 */
  730. $f4 = $f[4]->toInt64();
  731. /** @var ParagonIE_Sodium_Core32_Int64 $f5 */
  732. $f5 = $f[5]->toInt64();
  733. /** @var ParagonIE_Sodium_Core32_Int64 $f6 */
  734. $f6 = $f[6]->toInt64();
  735. /** @var ParagonIE_Sodium_Core32_Int64 $f7 */
  736. $f7 = $f[7]->toInt64();
  737. /** @var ParagonIE_Sodium_Core32_Int64 $f8 */
  738. $f8 = $f[8]->toInt64();
  739. /** @var ParagonIE_Sodium_Core32_Int64 $f9 */
  740. $f9 = $f[9]->toInt64();
  741. /** @var ParagonIE_Sodium_Core32_Int64 $f0_2 */
  742. $f0_2 = $f0->shiftLeft(1);
  743. $f1_2 = $f1->shiftLeft(1);
  744. $f2_2 = $f2->shiftLeft(1);
  745. $f3_2 = $f3->shiftLeft(1);
  746. $f4_2 = $f4->shiftLeft(1);
  747. $f5_2 = $f5->shiftLeft(1);
  748. $f6_2 = $f6->shiftLeft(1);
  749. $f7_2 = $f7->shiftLeft(1);
  750. $f5_38 = $f5->mulInt(38, 6);
  751. $f6_19 = $f6->mulInt(19, 5);
  752. $f7_38 = $f7->mulInt(38, 6);
  753. $f8_19 = $f8->mulInt(19, 5);
  754. $f9_38 = $f9->mulInt(38, 6);
  755. /** @var ParagonIE_Sodium_Core32_Int64 $f0f0*/
  756. $f0f0 = $f0->mulInt64($f0, 28);
  757. $f0f1_2 = $f0_2->mulInt64($f1, 28);
  758. $f0f2_2 = $f0_2->mulInt64($f2, 28);
  759. $f0f3_2 = $f0_2->mulInt64($f3, 28);
  760. $f0f4_2 = $f0_2->mulInt64($f4, 28);
  761. $f0f5_2 = $f0_2->mulInt64($f5, 28);
  762. $f0f6_2 = $f0_2->mulInt64($f6, 28);
  763. $f0f7_2 = $f0_2->mulInt64($f7, 28);
  764. $f0f8_2 = $f0_2->mulInt64($f8, 28);
  765. $f0f9_2 = $f0_2->mulInt64($f9, 28);
  766. $f1f1_2 = $f1_2->mulInt64($f1, 28);
  767. $f1f2_2 = $f1_2->mulInt64($f2, 28);
  768. $f1f3_4 = $f1_2->mulInt64($f3_2, 28);
  769. $f1f4_2 = $f1_2->mulInt64($f4, 28);
  770. $f1f5_4 = $f1_2->mulInt64($f5_2, 30);
  771. $f1f6_2 = $f1_2->mulInt64($f6, 28);
  772. $f1f7_4 = $f1_2->mulInt64($f7_2, 28);
  773. $f1f8_2 = $f1_2->mulInt64($f8, 28);
  774. $f1f9_76 = $f9_38->mulInt64($f1_2, 30);
  775. $f2f2 = $f2->mulInt64($f2, 28);
  776. $f2f3_2 = $f2_2->mulInt64($f3, 28);
  777. $f2f4_2 = $f2_2->mulInt64($f4, 28);
  778. $f2f5_2 = $f2_2->mulInt64($f5, 28);
  779. $f2f6_2 = $f2_2->mulInt64($f6, 28);
  780. $f2f7_2 = $f2_2->mulInt64($f7, 28);
  781. $f2f8_38 = $f8_19->mulInt64($f2_2, 30);
  782. $f2f9_38 = $f9_38->mulInt64($f2, 30);
  783. $f3f3_2 = $f3_2->mulInt64($f3, 28);
  784. $f3f4_2 = $f3_2->mulInt64($f4, 28);
  785. $f3f5_4 = $f3_2->mulInt64($f5_2, 30);
  786. $f3f6_2 = $f3_2->mulInt64($f6, 28);
  787. $f3f7_76 = $f7_38->mulInt64($f3_2, 30);
  788. $f3f8_38 = $f8_19->mulInt64($f3_2, 30);
  789. $f3f9_76 = $f9_38->mulInt64($f3_2, 30);
  790. $f4f4 = $f4->mulInt64($f4, 28);
  791. $f4f5_2 = $f4_2->mulInt64($f5, 28);
  792. $f4f6_38 = $f6_19->mulInt64($f4_2, 30);
  793. $f4f7_38 = $f7_38->mulInt64($f4, 30);
  794. $f4f8_38 = $f8_19->mulInt64($f4_2, 30);
  795. $f4f9_38 = $f9_38->mulInt64($f4, 30);
  796. $f5f5_38 = $f5_38->mulInt64($f5, 30);
  797. $f5f6_38 = $f6_19->mulInt64($f5_2, 30);
  798. $f5f7_76 = $f7_38->mulInt64($f5_2, 30);
  799. $f5f8_38 = $f8_19->mulInt64($f5_2, 30);
  800. $f5f9_76 = $f9_38->mulInt64($f5_2, 30);
  801. $f6f6_19 = $f6_19->mulInt64($f6, 30);
  802. $f6f7_38 = $f7_38->mulInt64($f6, 30);
  803. $f6f8_38 = $f8_19->mulInt64($f6_2, 30);
  804. $f6f9_38 = $f9_38->mulInt64($f6, 30);
  805. $f7f7_38 = $f7_38->mulInt64($f7, 28);
  806. $f7f8_38 = $f8_19->mulInt64($f7_2, 30);
  807. $f7f9_76 = $f9_38->mulInt64($f7_2, 30);
  808. $f8f8_19 = $f8_19->mulInt64($f8, 30);
  809. $f8f9_38 = $f9_38->mulInt64($f8, 30);
  810. $f9f9_38 = $f9_38->mulInt64($f9, 28);
  811. $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
  812. $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
  813. $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
  814. $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
  815. $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
  816. $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
  817. $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
  818. $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
  819. $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
  820. $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
  821. /**
  822. * @var ParagonIE_Sodium_Core32_Int64 $h0
  823. * @var ParagonIE_Sodium_Core32_Int64 $h1
  824. * @var ParagonIE_Sodium_Core32_Int64 $h2
  825. * @var ParagonIE_Sodium_Core32_Int64 $h3
  826. * @var ParagonIE_Sodium_Core32_Int64 $h4
  827. * @var ParagonIE_Sodium_Core32_Int64 $h5
  828. * @var ParagonIE_Sodium_Core32_Int64 $h6
  829. * @var ParagonIE_Sodium_Core32_Int64 $h7
  830. * @var ParagonIE_Sodium_Core32_Int64 $h8
  831. * @var ParagonIE_Sodium_Core32_Int64 $h9
  832. */
  833. $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
  834. $h1 = $h1->addInt64($carry0);
  835. $h0 = $h0->subInt64($carry0->shiftLeft(26));
  836. $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
  837. $h5 = $h5->addInt64($carry4);
  838. $h4 = $h4->subInt64($carry4->shiftLeft(26));
  839. $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
  840. $h2 = $h2->addInt64($carry1);
  841. $h1 = $h1->subInt64($carry1->shiftLeft(25));
  842. $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
  843. $h6 = $h6->addInt64($carry5);
  844. $h5 = $h5->subInt64($carry5->shiftLeft(25));
  845. $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
  846. $h3 = $h3->addInt64($carry2);
  847. $h2 = $h2->subInt64($carry2->shiftLeft(26));
  848. $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
  849. $h7 = $h7->addInt64($carry6);
  850. $h6 = $h6->subInt64($carry6->shiftLeft(26));
  851. $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
  852. $h4 = $h4->addInt64($carry3);
  853. $h3 = $h3->subInt64($carry3->shiftLeft(25));
  854. $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
  855. $h8 = $h8->addInt64($carry7);
  856. $h7 = $h7->subInt64($carry7->shiftLeft(25));
  857. $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
  858. $h5 = $h5->addInt64($carry4);
  859. $h4 = $h4->subInt64($carry4->shiftLeft(26));
  860. $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
  861. $h9 = $h9->addInt64($carry8);
  862. $h8 = $h8->subInt64($carry8->shiftLeft(26));
  863. $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
  864. $h0 = $h0->addInt64($carry9->mulInt(19, 5));
  865. $h9 = $h9->subInt64($carry9->shiftLeft(25));
  866. $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
  867. $h1 = $h1->addInt64($carry0);
  868. $h0 = $h0->subInt64($carry0->shiftLeft(26));
  869. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  870. array(
  871. $h0->toInt32(),
  872. $h1->toInt32(),
  873. $h2->toInt32(),
  874. $h3->toInt32(),
  875. $h4->toInt32(),
  876. $h5->toInt32(),
  877. $h6->toInt32(),
  878. $h7->toInt32(),
  879. $h8->toInt32(),
  880. $h9->toInt32()
  881. )
  882. );
  883. }
  884. /**
  885. * Square and double a field element
  886. *
  887. * h = 2 * f * f
  888. *
  889. * @internal You should not use this directly from another application
  890. *
  891. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
  892. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  893. * @throws SodiumException
  894. * @throws TypeError
  895. * @psalm-suppress MixedMethodCall
  896. */
  897. public static function fe_sq2(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
  898. {
  899. /** @var ParagonIE_Sodium_Core32_Int64 $f0 */
  900. $f0 = $f[0]->toInt64();
  901. /** @var ParagonIE_Sodium_Core32_Int64 $f1 */
  902. $f1 = $f[1]->toInt64();
  903. /** @var ParagonIE_Sodium_Core32_Int64 $f2 */
  904. $f2 = $f[2]->toInt64();
  905. /** @var ParagonIE_Sodium_Core32_Int64 $f3 */
  906. $f3 = $f[3]->toInt64();
  907. /** @var ParagonIE_Sodium_Core32_Int64 $f4 */
  908. $f4 = $f[4]->toInt64();
  909. /** @var ParagonIE_Sodium_Core32_Int64 $f5 */
  910. $f5 = $f[5]->toInt64();
  911. /** @var ParagonIE_Sodium_Core32_Int64 $f6 */
  912. $f6 = $f[6]->toInt64();
  913. /** @var ParagonIE_Sodium_Core32_Int64 $f7 */
  914. $f7 = $f[7]->toInt64();
  915. /** @var ParagonIE_Sodium_Core32_Int64 $f8 */
  916. $f8 = $f[8]->toInt64();
  917. /** @var ParagonIE_Sodium_Core32_Int64 $f9 */
  918. $f9 = $f[9]->toInt64();
  919. $f0_2 = $f0->shiftLeft(1);
  920. $f1_2 = $f1->shiftLeft(1);
  921. $f2_2 = $f2->shiftLeft(1);
  922. $f3_2 = $f3->shiftLeft(1);
  923. $f4_2 = $f4->shiftLeft(1);
  924. $f5_2 = $f5->shiftLeft(1);
  925. $f6_2 = $f6->shiftLeft(1);
  926. $f7_2 = $f7->shiftLeft(1);
  927. $f5_38 = $f5->mulInt(38, 6); /* 1.959375*2^30 */
  928. $f6_19 = $f6->mulInt(19, 5); /* 1.959375*2^30 */
  929. $f7_38 = $f7->mulInt(38, 6); /* 1.959375*2^30 */
  930. $f8_19 = $f8->mulInt(19, 5); /* 1.959375*2^30 */
  931. $f9_38 = $f9->mulInt(38, 6); /* 1.959375*2^30 */
  932. $f0f0 = $f0->mulInt64($f0, 28);
  933. $f0f1_2 = $f0_2->mulInt64($f1, 28);
  934. $f0f2_2 = $f0_2->mulInt64($f2, 28);
  935. $f0f3_2 = $f0_2->mulInt64($f3, 28);
  936. $f0f4_2 = $f0_2->mulInt64($f4, 28);
  937. $f0f5_2 = $f0_2->mulInt64($f5, 28);
  938. $f0f6_2 = $f0_2->mulInt64($f6, 28);
  939. $f0f7_2 = $f0_2->mulInt64($f7, 28);
  940. $f0f8_2 = $f0_2->mulInt64($f8, 28);
  941. $f0f9_2 = $f0_2->mulInt64($f9, 28);
  942. $f1f1_2 = $f1_2->mulInt64($f1, 28);
  943. $f1f2_2 = $f1_2->mulInt64($f2, 28);
  944. $f1f3_4 = $f1_2->mulInt64($f3_2, 29);
  945. $f1f4_2 = $f1_2->mulInt64($f4, 28);
  946. $f1f5_4 = $f1_2->mulInt64($f5_2, 29);
  947. $f1f6_2 = $f1_2->mulInt64($f6, 28);
  948. $f1f7_4 = $f1_2->mulInt64($f7_2, 29);
  949. $f1f8_2 = $f1_2->mulInt64($f8, 28);
  950. $f1f9_76 = $f9_38->mulInt64($f1_2, 29);
  951. $f2f2 = $f2->mulInt64($f2, 28);
  952. $f2f3_2 = $f2_2->mulInt64($f3, 28);
  953. $f2f4_2 = $f2_2->mulInt64($f4, 28);
  954. $f2f5_2 = $f2_2->mulInt64($f5, 28);
  955. $f2f6_2 = $f2_2->mulInt64($f6, 28);
  956. $f2f7_2 = $f2_2->mulInt64($f7, 28);
  957. $f2f8_38 = $f8_19->mulInt64($f2_2, 29);
  958. $f2f9_38 = $f9_38->mulInt64($f2, 29);
  959. $f3f3_2 = $f3_2->mulInt64($f3, 28);
  960. $f3f4_2 = $f3_2->mulInt64($f4, 28);
  961. $f3f5_4 = $f3_2->mulInt64($f5_2, 28);
  962. $f3f6_2 = $f3_2->mulInt64($f6, 28);
  963. $f3f7_76 = $f7_38->mulInt64($f3_2, 29);
  964. $f3f8_38 = $f8_19->mulInt64($f3_2, 29);
  965. $f3f9_76 = $f9_38->mulInt64($f3_2, 29);
  966. $f4f4 = $f4->mulInt64($f4, 28);
  967. $f4f5_2 = $f4_2->mulInt64($f5, 28);
  968. $f4f6_38 = $f6_19->mulInt64($f4_2, 29);
  969. $f4f7_38 = $f7_38->mulInt64($f4, 29);
  970. $f4f8_38 = $f8_19->mulInt64($f4_2, 29);
  971. $f4f9_38 = $f9_38->mulInt64($f4, 29);
  972. $f5f5_38 = $f5_38->mulInt64($f5, 29);
  973. $f5f6_38 = $f6_19->mulInt64($f5_2, 29);
  974. $f5f7_76 = $f7_38->mulInt64($f5_2, 29);
  975. $f5f8_38 = $f8_19->mulInt64($f5_2, 29);
  976. $f5f9_76 = $f9_38->mulInt64($f5_2, 29);
  977. $f6f6_19 = $f6_19->mulInt64($f6, 29);
  978. $f6f7_38 = $f7_38->mulInt64($f6, 29);
  979. $f6f8_38 = $f8_19->mulInt64($f6_2, 29);
  980. $f6f9_38 = $f9_38->mulInt64($f6, 29);
  981. $f7f7_38 = $f7_38->mulInt64($f7, 29);
  982. $f7f8_38 = $f8_19->mulInt64($f7_2, 29);
  983. $f7f9_76 = $f9_38->mulInt64($f7_2, 29);
  984. $f8f8_19 = $f8_19->mulInt64($f8, 29);
  985. $f8f9_38 = $f9_38->mulInt64($f8, 29);
  986. $f9f9_38 = $f9_38->mulInt64($f9, 29);
  987. $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
  988. $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
  989. $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
  990. $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
  991. $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
  992. $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
  993. $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
  994. $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
  995. $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
  996. $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
  997. /**
  998. * @var ParagonIE_Sodium_Core32_Int64 $h0
  999. * @var ParagonIE_Sodium_Core32_Int64 $h1
  1000. * @var ParagonIE_Sodium_Core32_Int64 $h2
  1001. * @var ParagonIE_Sodium_Core32_Int64 $h3
  1002. * @var ParagonIE_Sodium_Core32_Int64 $h4
  1003. * @var ParagonIE_Sodium_Core32_Int64 $h5
  1004. * @var ParagonIE_Sodium_Core32_Int64 $h6
  1005. * @var ParagonIE_Sodium_Core32_Int64 $h7
  1006. * @var ParagonIE_Sodium_Core32_Int64 $h8
  1007. * @var ParagonIE_Sodium_Core32_Int64 $h9
  1008. */
  1009. $h0 = $h0->shiftLeft(1);
  1010. $h1 = $h1->shiftLeft(1);
  1011. $h2 = $h2->shiftLeft(1);
  1012. $h3 = $h3->shiftLeft(1);
  1013. $h4 = $h4->shiftLeft(1);
  1014. $h5 = $h5->shiftLeft(1);
  1015. $h6 = $h6->shiftLeft(1);
  1016. $h7 = $h7->shiftLeft(1);
  1017. $h8 = $h8->shiftLeft(1);
  1018. $h9 = $h9->shiftLeft(1);
  1019. $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
  1020. $h1 = $h1->addInt64($carry0);
  1021. $h0 = $h0->subInt64($carry0->shiftLeft(26));
  1022. $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
  1023. $h5 = $h5->addInt64($carry4);
  1024. $h4 = $h4->subInt64($carry4->shiftLeft(26));
  1025. $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
  1026. $h2 = $h2->addInt64($carry1);
  1027. $h1 = $h1->subInt64($carry1->shiftLeft(25));
  1028. $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
  1029. $h6 = $h6->addInt64($carry5);
  1030. $h5 = $h5->subInt64($carry5->shiftLeft(25));
  1031. $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
  1032. $h3 = $h3->addInt64($carry2);
  1033. $h2 = $h2->subInt64($carry2->shiftLeft(26));
  1034. $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
  1035. $h7 = $h7->addInt64($carry6);
  1036. $h6 = $h6->subInt64($carry6->shiftLeft(26));
  1037. $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
  1038. $h4 = $h4->addInt64($carry3);
  1039. $h3 = $h3->subInt64($carry3->shiftLeft(25));
  1040. $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
  1041. $h8 = $h8->addInt64($carry7);
  1042. $h7 = $h7->subInt64($carry7->shiftLeft(25));
  1043. $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
  1044. $h5 = $h5->addInt64($carry4);
  1045. $h4 = $h4->subInt64($carry4->shiftLeft(26));
  1046. $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
  1047. $h9 = $h9->addInt64($carry8);
  1048. $h8 = $h8->subInt64($carry8->shiftLeft(26));
  1049. $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
  1050. $h0 = $h0->addInt64($carry9->mulInt(19, 5));
  1051. $h9 = $h9->subInt64($carry9->shiftLeft(25));
  1052. $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
  1053. $h1 = $h1->addInt64($carry0);
  1054. $h0 = $h0->subInt64($carry0->shiftLeft(26));
  1055. return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
  1056. array(
  1057. $h0->toInt32(),
  1058. $h1->toInt32(),
  1059. $h2->toInt32(),
  1060. $h3->toInt32(),
  1061. $h4->toInt32(),
  1062. $h5->toInt32(),
  1063. $h6->toInt32(),
  1064. $h7->toInt32(),
  1065. $h8->toInt32(),
  1066. $h9->toInt32()
  1067. )
  1068. );
  1069. }
  1070. /**
  1071. * @internal You should not use this directly from another application
  1072. *
  1073. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $Z
  1074. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  1075. * @throws SodiumException
  1076. * @throws TypeError
  1077. */
  1078. public static function fe_invert(ParagonIE_Sodium_Core32_Curve25519_Fe $Z)
  1079. {
  1080. $z = clone $Z;
  1081. $t0 = self::fe_sq($z);
  1082. $t1 = self::fe_sq($t0);
  1083. $t1 = self::fe_sq($t1);
  1084. $t1 = self::fe_mul($z, $t1);
  1085. $t0 = self::fe_mul($t0, $t1);
  1086. $t2 = self::fe_sq($t0);
  1087. $t1 = self::fe_mul($t1, $t2);
  1088. $t2 = self::fe_sq($t1);
  1089. for ($i = 1; $i < 5; ++$i) {
  1090. $t2 = self::fe_sq($t2);
  1091. }
  1092. $t1 = self::fe_mul($t2, $t1);
  1093. $t2 = self::fe_sq($t1);
  1094. for ($i = 1; $i < 10; ++$i) {
  1095. $t2 = self::fe_sq($t2);
  1096. }
  1097. $t2 = self::fe_mul($t2, $t1);
  1098. $t3 = self::fe_sq($t2);
  1099. for ($i = 1; $i < 20; ++$i) {
  1100. $t3 = self::fe_sq($t3);
  1101. }
  1102. $t2 = self::fe_mul($t3, $t2);
  1103. $t2 = self::fe_sq($t2);
  1104. for ($i = 1; $i < 10; ++$i) {
  1105. $t2 = self::fe_sq($t2);
  1106. }
  1107. $t1 = self::fe_mul($t2, $t1);
  1108. $t2 = self::fe_sq($t1);
  1109. for ($i = 1; $i < 50; ++$i) {
  1110. $t2 = self::fe_sq($t2);
  1111. }
  1112. $t2 = self::fe_mul($t2, $t1);
  1113. $t3 = self::fe_sq($t2);
  1114. for ($i = 1; $i < 100; ++$i) {
  1115. $t3 = self::fe_sq($t3);
  1116. }
  1117. $t2 = self::fe_mul($t3, $t2);
  1118. $t2 = self::fe_sq($t2);
  1119. for ($i = 1; $i < 50; ++$i) {
  1120. $t2 = self::fe_sq($t2);
  1121. }
  1122. $t1 = self::fe_mul($t2, $t1);
  1123. $t1 = self::fe_sq($t1);
  1124. for ($i = 1; $i < 5; ++$i) {
  1125. $t1 = self::fe_sq($t1);
  1126. }
  1127. return self::fe_mul($t1, $t0);
  1128. }
  1129. /**
  1130. * @internal You should not use this directly from another application
  1131. *
  1132. * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
  1133. *
  1134. * @param ParagonIE_Sodium_Core32_Curve25519_Fe $z
  1135. * @return ParagonIE_Sodium_Core32_Curve25519_Fe
  1136. * @throws SodiumException
  1137. * @throws TypeError
  1138. */
  1139. public static function fe_pow22523(ParagonIE_Sodium_Core32_Curve25519_Fe $z)
  1140. {
  1141. # fe_sq(t0, z);
  1142. # fe_sq(t1, t0);
  1143. # fe_sq(t1, t1);
  1144. # fe_mul(t1, z, t1);
  1145. # fe_mul(t0, t0, t1);
  1146. # fe_sq(t0, t0);
  1147. # fe_mul(t0, t1, t0);
  1148. # fe_sq(t1, t0);
  1149. $t0 = self::fe_sq($z);
  1150. $t1 = self::fe_sq($t0);
  1151. $t1 = self::fe_sq($t1);
  1152. $t1 = self::fe_mul($z, $t1);
  1153. $t0 = self::fe_mul($t0, $t1);
  1154. $t0 = self::fe_sq($t0);
  1155. $t0 = self::fe_mul($t1, $t0);
  1156. $t1 = self::fe_sq($t0);
  1157. # for (i = 1; i < 5; ++i) {
  1158. # fe_sq(t1, t1);
  1159. # }
  1160. for ($i = 1; $i < 5; ++$i) {
  1161. $t1 = self::fe_sq($t1);
  1162. }
  1163. # fe_mul(t0, t1, t0);
  1164. # fe_sq(t1, t0);
  1165. $t0 = self::fe_mul($t1, $t0);
  1166. $t1 = self::fe_sq($t0);
  1167. # for (i = 1; i < 10; ++i) {
  1168. # fe_sq(t1, t1);
  1169. # }
  1170. for ($i = 1; $i < 10; ++$i) {
  1171. $t1 =