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