Curve25519.php (150637B)
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 $x = (($f[$i] ^ $g[$i]) & $b); 90 $h[$i] = ($f[$i]) ^ $x; 91 } 92 return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h); 93 } 94 95 /** 96 * Create a copy of a field element. 97 * 98 * @internal You should not use this directly from another application 99 * 100 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 101 * @return ParagonIE_Sodium_Core_Curve25519_Fe 102 */ 103 public static function fe_copy(ParagonIE_Sodium_Core_Curve25519_Fe $f) 104 { 105 $h = clone $f; 106 return $h; 107 } 108 109 /** 110 * Give: 32-byte string. 111 * Receive: A field element object to use for internal calculations. 112 * 113 * @internal You should not use this directly from another application 114 * 115 * @param string $s 116 * @return ParagonIE_Sodium_Core_Curve25519_Fe 117 * @throws RangeException 118 * @throws TypeError 119 */ 120 public static function fe_frombytes($s) 121 { 122 if (self::strlen($s) !== 32) { 123 throw new RangeException('Expected a 32-byte string.'); 124 } 125 /** @var int $h0 */ 126 $h0 = self::load_4($s); 127 /** @var int $h1 */ 128 $h1 = self::load_3(self::substr($s, 4, 3)) << 6; 129 /** @var int $h2 */ 130 $h2 = self::load_3(self::substr($s, 7, 3)) << 5; 131 /** @var int $h3 */ 132 $h3 = self::load_3(self::substr($s, 10, 3)) << 3; 133 /** @var int $h4 */ 134 $h4 = self::load_3(self::substr($s, 13, 3)) << 2; 135 /** @var int $h5 */ 136 $h5 = self::load_4(self::substr($s, 16, 4)); 137 /** @var int $h6 */ 138 $h6 = self::load_3(self::substr($s, 20, 3)) << 7; 139 /** @var int $h7 */ 140 $h7 = self::load_3(self::substr($s, 23, 3)) << 5; 141 /** @var int $h8 */ 142 $h8 = self::load_3(self::substr($s, 26, 3)) << 4; 143 /** @var int $h9 */ 144 $h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2; 145 146 /** @var int $carry9 */ 147 $carry9 = ($h9 + (1 << 24)) >> 25; 148 $h0 += self::mul($carry9, 19, 5); 149 $h9 -= $carry9 << 25; 150 /** @var int $carry1 */ 151 $carry1 = ($h1 + (1 << 24)) >> 25; 152 $h2 += $carry1; 153 $h1 -= $carry1 << 25; 154 /** @var int $carry3 */ 155 $carry3 = ($h3 + (1 << 24)) >> 25; 156 $h4 += $carry3; 157 $h3 -= $carry3 << 25; 158 /** @var int $carry5 */ 159 $carry5 = ($h5 + (1 << 24)) >> 25; 160 $h6 += $carry5; 161 $h5 -= $carry5 << 25; 162 /** @var int $carry7 */ 163 $carry7 = ($h7 + (1 << 24)) >> 25; 164 $h8 += $carry7; 165 $h7 -= $carry7 << 25; 166 167 /** @var int $carry0 */ 168 $carry0 = ($h0 + (1 << 25)) >> 26; 169 $h1 += $carry0; 170 $h0 -= $carry0 << 26; 171 /** @var int $carry2 */ 172 $carry2 = ($h2 + (1 << 25)) >> 26; 173 $h3 += $carry2; 174 $h2 -= $carry2 << 26; 175 /** @var int $carry4 */ 176 $carry4 = ($h4 + (1 << 25)) >> 26; 177 $h5 += $carry4; 178 $h4 -= $carry4 << 26; 179 /** @var int $carry6 */ 180 $carry6 = ($h6 + (1 << 25)) >> 26; 181 $h7 += $carry6; 182 $h6 -= $carry6 << 26; 183 /** @var int $carry8 */ 184 $carry8 = ($h8 + (1 << 25)) >> 26; 185 $h9 += $carry8; 186 $h8 -= $carry8 << 26; 187 188 return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( 189 array( 190 (int) $h0, 191 (int) $h1, 192 (int) $h2, 193 (int) $h3, 194 (int) $h4, 195 (int) $h5, 196 (int) $h6, 197 (int) $h7, 198 (int) $h8, 199 (int) $h9 200 ) 201 ); 202 } 203 204 /** 205 * Convert a field element to a byte string. 206 * 207 * @internal You should not use this directly from another application 208 * 209 * @param ParagonIE_Sodium_Core_Curve25519_Fe $h 210 * @return string 211 */ 212 public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe $h) 213 { 214 /** @var int $h0 */ 215 $h0 = (int) $h[0]; 216 /** @var int $h1 */ 217 $h1 = (int) $h[1]; 218 /** @var int $h2 */ 219 $h2 = (int) $h[2]; 220 /** @var int $h3 */ 221 $h3 = (int) $h[3]; 222 /** @var int $h4 */ 223 $h4 = (int) $h[4]; 224 /** @var int $h5 */ 225 $h5 = (int) $h[5]; 226 /** @var int $h6 */ 227 $h6 = (int) $h[6]; 228 /** @var int $h7 */ 229 $h7 = (int) $h[7]; 230 /** @var int $h8 */ 231 $h8 = (int) $h[8]; 232 /** @var int $h9 */ 233 $h9 = (int) $h[9]; 234 235 /** @var int $q */ 236 $q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25; 237 /** @var int $q */ 238 $q = ($h0 + $q) >> 26; 239 /** @var int $q */ 240 $q = ($h1 + $q) >> 25; 241 /** @var int $q */ 242 $q = ($h2 + $q) >> 26; 243 /** @var int $q */ 244 $q = ($h3 + $q) >> 25; 245 /** @var int $q */ 246 $q = ($h4 + $q) >> 26; 247 /** @var int $q */ 248 $q = ($h5 + $q) >> 25; 249 /** @var int $q */ 250 $q = ($h6 + $q) >> 26; 251 /** @var int $q */ 252 $q = ($h7 + $q) >> 25; 253 /** @var int $q */ 254 $q = ($h8 + $q) >> 26; 255 /** @var int $q */ 256 $q = ($h9 + $q) >> 25; 257 258 $h0 += self::mul($q, 19, 5); 259 260 /** @var int $carry0 */ 261 $carry0 = $h0 >> 26; 262 $h1 += $carry0; 263 $h0 -= $carry0 << 26; 264 /** @var int $carry1 */ 265 $carry1 = $h1 >> 25; 266 $h2 += $carry1; 267 $h1 -= $carry1 << 25; 268 /** @var int $carry2 */ 269 $carry2 = $h2 >> 26; 270 $h3 += $carry2; 271 $h2 -= $carry2 << 26; 272 /** @var int $carry3 */ 273 $carry3 = $h3 >> 25; 274 $h4 += $carry3; 275 $h3 -= $carry3 << 25; 276 /** @var int $carry4 */ 277 $carry4 = $h4 >> 26; 278 $h5 += $carry4; 279 $h4 -= $carry4 << 26; 280 /** @var int $carry5 */ 281 $carry5 = $h5 >> 25; 282 $h6 += $carry5; 283 $h5 -= $carry5 << 25; 284 /** @var int $carry6 */ 285 $carry6 = $h6 >> 26; 286 $h7 += $carry6; 287 $h6 -= $carry6 << 26; 288 /** @var int $carry7 */ 289 $carry7 = $h7 >> 25; 290 $h8 += $carry7; 291 $h7 -= $carry7 << 25; 292 /** @var int $carry8 */ 293 $carry8 = $h8 >> 26; 294 $h9 += $carry8; 295 $h8 -= $carry8 << 26; 296 /** @var int $carry9 */ 297 $carry9 = $h9 >> 25; 298 $h9 -= $carry9 << 25; 299 300 /** 301 * @var array<int, int> 302 */ 303 $s = array( 304 (int) (($h0 >> 0) & 0xff), 305 (int) (($h0 >> 8) & 0xff), 306 (int) (($h0 >> 16) & 0xff), 307 (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff), 308 (int) (($h1 >> 6) & 0xff), 309 (int) (($h1 >> 14) & 0xff), 310 (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff), 311 (int) (($h2 >> 5) & 0xff), 312 (int) (($h2 >> 13) & 0xff), 313 (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff), 314 (int) (($h3 >> 3) & 0xff), 315 (int) (($h3 >> 11) & 0xff), 316 (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff), 317 (int) (($h4 >> 2) & 0xff), 318 (int) (($h4 >> 10) & 0xff), 319 (int) (($h4 >> 18) & 0xff), 320 (int) (($h5 >> 0) & 0xff), 321 (int) (($h5 >> 8) & 0xff), 322 (int) (($h5 >> 16) & 0xff), 323 (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff), 324 (int) (($h6 >> 7) & 0xff), 325 (int) (($h6 >> 15) & 0xff), 326 (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff), 327 (int) (($h7 >> 5) & 0xff), 328 (int) (($h7 >> 13) & 0xff), 329 (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff), 330 (int) (($h8 >> 4) & 0xff), 331 (int) (($h8 >> 12) & 0xff), 332 (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff), 333 (int) (($h9 >> 2) & 0xff), 334 (int) (($h9 >> 10) & 0xff), 335 (int) (($h9 >> 18) & 0xff) 336 ); 337 return self::intArrayToString($s); 338 } 339 340 /** 341 * Is a field element negative? (1 = yes, 0 = no. Used in calculations.) 342 * 343 * @internal You should not use this directly from another application 344 * 345 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 346 * @return int 347 * @throws SodiumException 348 * @throws TypeError 349 */ 350 public static function fe_isnegative(ParagonIE_Sodium_Core_Curve25519_Fe $f) 351 { 352 $str = self::fe_tobytes($f); 353 return (int) (self::chrToInt($str[0]) & 1); 354 } 355 356 /** 357 * Returns 0 if this field element results in all NUL bytes. 358 * 359 * @internal You should not use this directly from another application 360 * 361 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 362 * @return bool 363 * @throws SodiumException 364 * @throws TypeError 365 */ 366 public static function fe_isnonzero(ParagonIE_Sodium_Core_Curve25519_Fe $f) 367 { 368 static $zero; 369 if ($zero === null) { 370 $zero = str_repeat("\x00", 32); 371 } 372 /** @var string $zero */ 373 /** @var string $str */ 374 $str = self::fe_tobytes($f); 375 return !self::verify_32($str, (string) $zero); 376 } 377 378 /** 379 * Multiply two field elements 380 * 381 * h = f * g 382 * 383 * @internal You should not use this directly from another application 384 * 385 * @security Is multiplication a source of timing leaks? If so, can we do 386 * anything to prevent that from happening? 387 * 388 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 389 * @param ParagonIE_Sodium_Core_Curve25519_Fe $g 390 * @return ParagonIE_Sodium_Core_Curve25519_Fe 391 */ 392 public static function fe_mul( 393 ParagonIE_Sodium_Core_Curve25519_Fe $f, 394 ParagonIE_Sodium_Core_Curve25519_Fe $g 395 ) { 396 /** @var int $f0 */ 397 $f0 = $f[0]; 398 /** @var int $f1 */ 399 $f1 = $f[1]; 400 /** @var int $f2 */ 401 $f2 = $f[2]; 402 /** @var int $f3 */ 403 $f3 = $f[3]; 404 /** @var int $f4 */ 405 $f4 = $f[4]; 406 /** @var int $f5 */ 407 $f5 = $f[5]; 408 /** @var int $f6 */ 409 $f6 = $f[6]; 410 /** @var int $f7 */ 411 $f7 = $f[7]; 412 /** @var int $f8 */ 413 $f8 = $f[8]; 414 /** @var int $f9 */ 415 $f9 = $f[9]; 416 /** @var int $g0 */ 417 $g0 = $g[0]; 418 /** @var int $g1 */ 419 $g1 = $g[1]; 420 /** @var int $g2 */ 421 $g2 = $g[2]; 422 /** @var int $g3 */ 423 $g3 = $g[3]; 424 /** @var int $g4 */ 425 $g4 = $g[4]; 426 /** @var int $g5 */ 427 $g5 = $g[5]; 428 /** @var int $g6 */ 429 $g6 = $g[6]; 430 /** @var int $g7 */ 431 $g7 = $g[7]; 432 /** @var int $g8 */ 433 $g8 = $g[8]; 434 /** @var int $g9 */ 435 $g9 = $g[9]; 436 $g1_19 = self::mul($g1, 19, 5); 437 $g2_19 = self::mul($g2, 19, 5); 438 $g3_19 = self::mul($g3, 19, 5); 439 $g4_19 = self::mul($g4, 19, 5); 440 $g5_19 = self::mul($g5, 19, 5); 441 $g6_19 = self::mul($g6, 19, 5); 442 $g7_19 = self::mul($g7, 19, 5); 443 $g8_19 = self::mul($g8, 19, 5); 444 $g9_19 = self::mul($g9, 19, 5); 445 /** @var int $f1_2 */ 446 $f1_2 = $f1 << 1; 447 /** @var int $f3_2 */ 448 $f3_2 = $f3 << 1; 449 /** @var int $f5_2 */ 450 $f5_2 = $f5 << 1; 451 /** @var int $f7_2 */ 452 $f7_2 = $f7 << 1; 453 /** @var int $f9_2 */ 454 $f9_2 = $f9 << 1; 455 $f0g0 = self::mul($f0, $g0, 26); 456 $f0g1 = self::mul($f0, $g1, 25); 457 $f0g2 = self::mul($f0, $g2, 26); 458 $f0g3 = self::mul($f0, $g3, 25); 459 $f0g4 = self::mul($f0, $g4, 26); 460 $f0g5 = self::mul($f0, $g5, 25); 461 $f0g6 = self::mul($f0, $g6, 26); 462 $f0g7 = self::mul($f0, $g7, 25); 463 $f0g8 = self::mul($f0, $g8, 26); 464 $f0g9 = self::mul($f0, $g9, 26); 465 $f1g0 = self::mul($f1, $g0, 26); 466 $f1g1_2 = self::mul($f1_2, $g1, 25); 467 $f1g2 = self::mul($f1, $g2, 26); 468 $f1g3_2 = self::mul($f1_2, $g3, 25); 469 $f1g4 = self::mul($f1, $g4, 26); 470 $f1g5_2 = self::mul($f1_2, $g5, 25); 471 $f1g6 = self::mul($f1, $g6, 26); 472 $f1g7_2 = self::mul($f1_2, $g7, 25); 473 $f1g8 = self::mul($f1, $g8, 26); 474 $f1g9_38 = self::mul($g9_19, $f1_2, 26); 475 $f2g0 = self::mul($f2, $g0, 26); 476 $f2g1 = self::mul($f2, $g1, 25); 477 $f2g2 = self::mul($f2, $g2, 26); 478 $f2g3 = self::mul($f2, $g3, 25); 479 $f2g4 = self::mul($f2, $g4, 26); 480 $f2g5 = self::mul($f2, $g5, 25); 481 $f2g6 = self::mul($f2, $g6, 26); 482 $f2g7 = self::mul($f2, $g7, 25); 483 $f2g8_19 = self::mul($g8_19, $f2, 26); 484 $f2g9_19 = self::mul($g9_19, $f2, 26); 485 $f3g0 = self::mul($f3, $g0, 26); 486 $f3g1_2 = self::mul($f3_2, $g1, 25); 487 $f3g2 = self::mul($f3, $g2, 26); 488 $f3g3_2 = self::mul($f3_2, $g3, 25); 489 $f3g4 = self::mul($f3, $g4, 26); 490 $f3g5_2 = self::mul($f3_2, $g5, 25); 491 $f3g6 = self::mul($f3, $g6, 26); 492 $f3g7_38 = self::mul($g7_19, $f3_2, 26); 493 $f3g8_19 = self::mul($g8_19, $f3, 25); 494 $f3g9_38 = self::mul($g9_19, $f3_2, 26); 495 $f4g0 = self::mul($f4, $g0, 26); 496 $f4g1 = self::mul($f4, $g1, 25); 497 $f4g2 = self::mul($f4, $g2, 26); 498 $f4g3 = self::mul($f4, $g3, 25); 499 $f4g4 = self::mul($f4, $g4, 26); 500 $f4g5 = self::mul($f4, $g5, 25); 501 $f4g6_19 = self::mul($g6_19, $f4, 26); 502 $f4g7_19 = self::mul($g7_19, $f4, 26); 503 $f4g8_19 = self::mul($g8_19, $f4, 26); 504 $f4g9_19 = self::mul($g9_19, $f4, 26); 505 $f5g0 = self::mul($f5, $g0, 26); 506 $f5g1_2 = self::mul($f5_2, $g1, 25); 507 $f5g2 = self::mul($f5, $g2, 26); 508 $f5g3_2 = self::mul($f5_2, $g3, 25); 509 $f5g4 = self::mul($f5, $g4, 26); 510 $f5g5_38 = self::mul($g5_19, $f5_2, 26); 511 $f5g6_19 = self::mul($g6_19, $f5, 25); 512 $f5g7_38 = self::mul($g7_19, $f5_2, 26); 513 $f5g8_19 = self::mul($g8_19, $f5, 25); 514 $f5g9_38 = self::mul($g9_19, $f5_2, 26); 515 $f6g0 = self::mul($f6, $g0, 26); 516 $f6g1 = self::mul($f6, $g1, 25); 517 $f6g2 = self::mul($f6, $g2, 26); 518 $f6g3 = self::mul($f6, $g3, 25); 519 $f6g4_19 = self::mul($g4_19, $f6, 26); 520 $f6g5_19 = self::mul($g5_19, $f6, 26); 521 $f6g6_19 = self::mul($g6_19, $f6, 26); 522 $f6g7_19 = self::mul($g7_19, $f6, 26); 523 $f6g8_19 = self::mul($g8_19, $f6, 26); 524 $f6g9_19 = self::mul($g9_19, $f6, 26); 525 $f7g0 = self::mul($f7, $g0, 26); 526 $f7g1_2 = self::mul($f7_2, $g1, 25); 527 $f7g2 = self::mul($f7, $g2, 26); 528 $f7g3_38 = self::mul($g3_19, $f7_2, 26); 529 $f7g4_19 = self::mul($g4_19, $f7, 26); 530 $f7g5_38 = self::mul($g5_19, $f7_2, 26); 531 $f7g6_19 = self::mul($g6_19, $f7, 25); 532 $f7g7_38 = self::mul($g7_19, $f7_2, 26); 533 $f7g8_19 = self::mul($g8_19, $f7, 25); 534 $f7g9_38 = self::mul($g9_19,$f7_2, 26); 535 $f8g0 = self::mul($f8, $g0, 26); 536 $f8g1 = self::mul($f8, $g1, 25); 537 $f8g2_19 = self::mul($g2_19, $f8, 26); 538 $f8g3_19 = self::mul($g3_19, $f8, 26); 539 $f8g4_19 = self::mul($g4_19, $f8, 26); 540 $f8g5_19 = self::mul($g5_19, $f8, 26); 541 $f8g6_19 = self::mul($g6_19, $f8, 26); 542 $f8g7_19 = self::mul($g7_19, $f8, 26); 543 $f8g8_19 = self::mul($g8_19, $f8, 26); 544 $f8g9_19 = self::mul($g9_19, $f8, 26); 545 $f9g0 = self::mul($f9, $g0, 26); 546 $f9g1_38 = self::mul($g1_19, $f9_2, 26); 547 $f9g2_19 = self::mul($g2_19, $f9, 25); 548 $f9g3_38 = self::mul($g3_19, $f9_2, 26); 549 $f9g4_19 = self::mul($g4_19, $f9, 25); 550 $f9g5_38 = self::mul($g5_19, $f9_2, 26); 551 $f9g6_19 = self::mul($g6_19, $f9, 25); 552 $f9g7_38 = self::mul($g7_19, $f9_2, 26); 553 $f9g8_19 = self::mul($g8_19, $f9, 25); 554 $f9g9_38 = self::mul($g9_19, $f9_2, 26); 555 $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38; 556 $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19; 557 $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38; 558 $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19; 559 $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38; 560 $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19; 561 $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38; 562 $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19; 563 $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38; 564 $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ; 565 566 /** @var int $carry0 */ 567 $carry0 = ($h0 + (1 << 25)) >> 26; 568 $h1 += $carry0; 569 $h0 -= $carry0 << 26; 570 /** @var int $carry4 */ 571 $carry4 = ($h4 + (1 << 25)) >> 26; 572 $h5 += $carry4; 573 $h4 -= $carry4 << 26; 574 575 /** @var int $carry1 */ 576 $carry1 = ($h1 + (1 << 24)) >> 25; 577 $h2 += $carry1; 578 $h1 -= $carry1 << 25; 579 /** @var int $carry5 */ 580 $carry5 = ($h5 + (1 << 24)) >> 25; 581 $h6 += $carry5; 582 $h5 -= $carry5 << 25; 583 584 /** @var int $carry2 */ 585 $carry2 = ($h2 + (1 << 25)) >> 26; 586 $h3 += $carry2; 587 $h2 -= $carry2 << 26; 588 /** @var int $carry6 */ 589 $carry6 = ($h6 + (1 << 25)) >> 26; 590 $h7 += $carry6; 591 $h6 -= $carry6 << 26; 592 593 /** @var int $carry3 */ 594 $carry3 = ($h3 + (1 << 24)) >> 25; 595 $h4 += $carry3; 596 $h3 -= $carry3 << 25; 597 /** @var int $carry7 */ 598 $carry7 = ($h7 + (1 << 24)) >> 25; 599 $h8 += $carry7; 600 $h7 -= $carry7 << 25; 601 602 /** @var int $carry4 */ 603 $carry4 = ($h4 + (1 << 25)) >> 26; 604 $h5 += $carry4; 605 $h4 -= $carry4 << 26; 606 /** @var int $carry8 */ 607 $carry8 = ($h8 + (1 << 25)) >> 26; 608 $h9 += $carry8; 609 $h8 -= $carry8 << 26; 610 611 /** @var int $carry9 */ 612 $carry9 = ($h9 + (1 << 24)) >> 25; 613 $h0 += self::mul($carry9, 19, 5); 614 $h9 -= $carry9 << 25; 615 616 /** @var int $carry0 */ 617 $carry0 = ($h0 + (1 << 25)) >> 26; 618 $h1 += $carry0; 619 $h0 -= $carry0 << 26; 620 621 return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( 622 array( 623 (int) $h0, 624 (int) $h1, 625 (int) $h2, 626 (int) $h3, 627 (int) $h4, 628 (int) $h5, 629 (int) $h6, 630 (int) $h7, 631 (int) $h8, 632 (int) $h9 633 ) 634 ); 635 } 636 637 /** 638 * Get the negative values for each piece of the field element. 639 * 640 * h = -f 641 * 642 * @internal You should not use this directly from another application 643 * 644 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 645 * @return ParagonIE_Sodium_Core_Curve25519_Fe 646 * @psalm-suppress MixedAssignment 647 */ 648 public static function fe_neg(ParagonIE_Sodium_Core_Curve25519_Fe $f) 649 { 650 $h = new ParagonIE_Sodium_Core_Curve25519_Fe(); 651 for ($i = 0; $i < 10; ++$i) { 652 $h[$i] = -$f[$i]; 653 } 654 return $h; 655 } 656 657 /** 658 * Square a field element 659 * 660 * h = f * f 661 * 662 * @internal You should not use this directly from another application 663 * 664 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 665 * @return ParagonIE_Sodium_Core_Curve25519_Fe 666 */ 667 public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f) 668 { 669 $f0 = (int) $f[0]; 670 $f1 = (int) $f[1]; 671 $f2 = (int) $f[2]; 672 $f3 = (int) $f[3]; 673 $f4 = (int) $f[4]; 674 $f5 = (int) $f[5]; 675 $f6 = (int) $f[6]; 676 $f7 = (int) $f[7]; 677 $f8 = (int) $f[8]; 678 $f9 = (int) $f[9]; 679 680 /** @var int $f0_2 */ 681 $f0_2 = $f0 << 1; 682 /** @var int $f1_2 */ 683 $f1_2 = $f1 << 1; 684 /** @var int $f2_2 */ 685 $f2_2 = $f2 << 1; 686 /** @var int $f3_2 */ 687 $f3_2 = $f3 << 1; 688 /** @var int $f4_2 */ 689 $f4_2 = $f4 << 1; 690 /** @var int $f5_2 */ 691 $f5_2 = $f5 << 1; 692 /** @var int $f6_2 */ 693 $f6_2 = $f6 << 1; 694 /** @var int $f7_2 */ 695 $f7_2 = $f7 << 1; 696 $f5_38 = self::mul($f5, 38, 6); 697 $f6_19 = self::mul($f6, 19, 5); 698 $f7_38 = self::mul($f7, 38, 6); 699 $f8_19 = self::mul($f8, 19, 5); 700 $f9_38 = self::mul($f9, 38, 6); 701 $f0f0 = self::mul($f0, $f0, 25); 702 $f0f1_2 = self::mul($f0_2, $f1, 24); 703 $f0f2_2 = self::mul($f0_2, $f2, 26); 704 $f0f3_2 = self::mul($f0_2, $f3, 24); 705 $f0f4_2 = self::mul($f0_2, $f4, 25); 706 $f0f5_2 = self::mul($f0_2, $f5, 25); 707 $f0f6_2 = self::mul($f0_2, $f6, 25); 708 $f0f7_2 = self::mul($f0_2, $f7, 24); 709 $f0f8_2 = self::mul($f0_2, $f8, 25); 710 $f0f9_2 = self::mul($f0_2, $f9, 25); 711 $f1f1_2 = self::mul($f1_2, $f1, 24); 712 $f1f2_2 = self::mul($f1_2, $f2, 26); 713 $f1f3_4 = self::mul($f1_2, $f3_2, 25); 714 $f1f4_2 = self::mul($f1_2, $f4, 25); 715 $f1f5_4 = self::mul($f1_2, $f5_2, 26); 716 $f1f6_2 = self::mul($f1_2, $f6, 25); 717 $f1f7_4 = self::mul($f1_2, $f7_2, 25); 718 $f1f8_2 = self::mul($f1_2, $f8, 25); 719 $f1f9_76 = self::mul($f9_38, $f1_2, 25); 720 $f2f2 = self::mul($f2, $f2, 26); 721 $f2f3_2 = self::mul($f2_2, $f3, 24); 722 $f2f4_2 = self::mul($f2_2, $f4, 25); 723 $f2f5_2 = self::mul($f2_2, $f5, 25); 724 $f2f6_2 = self::mul($f2_2, $f6, 25); 725 $f2f7_2 = self::mul($f2_2, $f7, 25); 726 $f2f8_38 = self::mul($f8_19, $f2_2, 27); 727 $f2f9_38 = self::mul($f9_38, $f2, 26); 728 $f3f3_2 = self::mul($f3_2, $f3, 25); 729 $f3f4_2 = self::mul($f3_2, $f4, 25); 730 $f3f5_4 = self::mul($f3_2, $f5_2, 26); 731 $f3f6_2 = self::mul($f3_2, $f6, 25); 732 $f3f7_76 = self::mul($f7_38, $f3_2, 25); 733 $f3f8_38 = self::mul($f8_19, $f3_2, 25); 734 $f3f9_76 = self::mul($f9_38, $f3_2, 25); 735 $f4f4 = self::mul($f4, $f4, 25); 736 $f4f5_2 = self::mul($f4_2, $f5, 25); 737 $f4f6_38 = self::mul($f6_19, $f4_2, 26); 738 $f4f7_38 = self::mul($f7_38, $f4, 25); 739 $f4f8_38 = self::mul($f8_19, $f4_2, 26); 740 $f4f9_38 = self::mul($f9_38, $f4, 25); 741 $f5f5_38 = self::mul($f5_38, $f5, 25); 742 $f5f6_38 = self::mul($f6_19, $f5_2, 26); 743 $f5f7_76 = self::mul($f7_38, $f5_2, 26); 744 $f5f8_38 = self::mul($f8_19, $f5_2, 26); 745 $f5f9_76 = self::mul($f9_38, $f5_2, 26); 746 $f6f6_19 = self::mul($f6_19, $f6, 25); 747 $f6f7_38 = self::mul($f7_38, $f6, 25); 748 $f6f8_38 = self::mul($f8_19, $f6_2, 26); 749 $f6f9_38 = self::mul($f9_38, $f6, 25); 750 $f7f7_38 = self::mul($f7_38, $f7, 24); 751 $f7f8_38 = self::mul($f8_19, $f7_2, 25); 752 $f7f9_76 = self::mul($f9_38, $f7_2, 25); 753 $f8f8_19 = self::mul($f8_19, $f8, 25); 754 $f8f9_38 = self::mul($f9_38, $f8, 25); 755 $f9f9_38 = self::mul($f9_38, $f9, 25); 756 $h0 = $f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38; 757 $h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38; 758 $h2 = $f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19; 759 $h3 = $f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38; 760 $h4 = $f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38; 761 $h5 = $f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38; 762 $h6 = $f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19; 763 $h7 = $f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38; 764 $h8 = $f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38; 765 $h9 = $f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2; 766 767 /** @var int $carry0 */ 768 $carry0 = ($h0 + (1 << 25)) >> 26; 769 $h1 += $carry0; 770 $h0 -= $carry0 << 26; 771 /** @var int $carry4 */ 772 $carry4 = ($h4 + (1 << 25)) >> 26; 773 $h5 += $carry4; 774 $h4 -= $carry4 << 26; 775 776 /** @var int $carry1 */ 777 $carry1 = ($h1 + (1 << 24)) >> 25; 778 $h2 += $carry1; 779 $h1 -= $carry1 << 25; 780 /** @var int $carry5 */ 781 $carry5 = ($h5 + (1 << 24)) >> 25; 782 $h6 += $carry5; 783 $h5 -= $carry5 << 25; 784 785 /** @var int $carry2 */ 786 $carry2 = ($h2 + (1 << 25)) >> 26; 787 $h3 += $carry2; 788 $h2 -= $carry2 << 26; 789 /** @var int $carry6 */ 790 $carry6 = ($h6 + (1 << 25)) >> 26; 791 $h7 += $carry6; 792 $h6 -= $carry6 << 26; 793 794 /** @var int $carry3 */ 795 $carry3 = ($h3 + (1 << 24)) >> 25; 796 $h4 += $carry3; 797 $h3 -= $carry3 << 25; 798 /** @var int $carry7 */ 799 $carry7 = ($h7 + (1 << 24)) >> 25; 800 $h8 += $carry7; 801 $h7 -= $carry7 << 25; 802 803 /** @var int $carry4 */ 804 $carry4 = ($h4 + (1 << 25)) >> 26; 805 $h5 += $carry4; 806 $h4 -= $carry4 << 26; 807 /** @var int $carry8 */ 808 $carry8 = ($h8 + (1 << 25)) >> 26; 809 $h9 += $carry8; 810 $h8 -= $carry8 << 26; 811 812 /** @var int $carry9 */ 813 $carry9 = ($h9 + (1 << 24)) >> 25; 814 $h0 += self::mul($carry9, 19, 5); 815 $h9 -= $carry9 << 25; 816 817 /** @var int $carry0 */ 818 $carry0 = ($h0 + (1 << 25)) >> 26; 819 $h1 += $carry0; 820 $h0 -= $carry0 << 26; 821 822 return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( 823 array( 824 (int) $h0, 825 (int) $h1, 826 (int) $h2, 827 (int) $h3, 828 (int) $h4, 829 (int) $h5, 830 (int) $h6, 831 (int) $h7, 832 (int) $h8, 833 (int) $h9 834 ) 835 ); 836 } 837 838 839 /** 840 * Square and double a field element 841 * 842 * h = 2 * f * f 843 * 844 * @internal You should not use this directly from another application 845 * 846 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 847 * @return ParagonIE_Sodium_Core_Curve25519_Fe 848 */ 849 public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f) 850 { 851 $f0 = (int) $f[0]; 852 $f1 = (int) $f[1]; 853 $f2 = (int) $f[2]; 854 $f3 = (int) $f[3]; 855 $f4 = (int) $f[4]; 856 $f5 = (int) $f[5]; 857 $f6 = (int) $f[6]; 858 $f7 = (int) $f[7]; 859 $f8 = (int) $f[8]; 860 $f9 = (int) $f[9]; 861 862 /** @var int $f0_2 */ 863 $f0_2 = $f0 << 1; 864 /** @var int $f1_2 */ 865 $f1_2 = $f1 << 1; 866 /** @var int $f2_2 */ 867 $f2_2 = $f2 << 1; 868 /** @var int $f3_2 */ 869 $f3_2 = $f3 << 1; 870 /** @var int $f4_2 */ 871 $f4_2 = $f4 << 1; 872 /** @var int $f5_2 */ 873 $f5_2 = $f5 << 1; 874 /** @var int $f6_2 */ 875 $f6_2 = $f6 << 1; 876 /** @var int $f7_2 */ 877 $f7_2 = $f7 << 1; 878 $f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */ 879 $f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */ 880 $f7_38 = self::mul($f7, 38, 6); /* 1.959375*2^30 */ 881 $f8_19 = self::mul($f8, 19, 5); /* 1.959375*2^30 */ 882 $f9_38 = self::mul($f9, 38, 6); /* 1.959375*2^30 */ 883 $f0f0 = self::mul($f0, $f0, 24); 884 $f0f1_2 = self::mul($f0_2, $f1, 24); 885 $f0f2_2 = self::mul($f0_2, $f2, 24); 886 $f0f3_2 = self::mul($f0_2, $f3, 24); 887 $f0f4_2 = self::mul($f0_2, $f4, 24); 888 $f0f5_2 = self::mul($f0_2, $f5, 24); 889 $f0f6_2 = self::mul($f0_2, $f6, 24); 890 $f0f7_2 = self::mul($f0_2, $f7, 24); 891 $f0f8_2 = self::mul($f0_2, $f8, 24); 892 $f0f9_2 = self::mul($f0_2, $f9, 24); 893 $f1f1_2 = self::mul($f1_2, $f1, 24); 894 $f1f2_2 = self::mul($f1_2, $f2, 24); 895 $f1f3_4 = self::mul($f1_2, $f3_2, 24); 896 $f1f4_2 = self::mul($f1_2, $f4, 24); 897 $f1f5_4 = self::mul($f1_2, $f5_2, 24); 898 $f1f6_2 = self::mul($f1_2, $f6, 24); 899 $f1f7_4 = self::mul($f1_2, $f7_2, 24); 900 $f1f8_2 = self::mul($f1_2, $f8, 24); 901 $f1f9_76 = self::mul($f9_38, $f1_2, 24); 902 $f2f2 = self::mul($f2, $f2, 24); 903 $f2f3_2 = self::mul($f2_2, $f3, 24); 904 $f2f4_2 = self::mul($f2_2, $f4, 24); 905 $f2f5_2 = self::mul($f2_2, $f5, 24); 906 $f2f6_2 = self::mul($f2_2, $f6, 24); 907 $f2f7_2 = self::mul($f2_2, $f7, 24); 908 $f2f8_38 = self::mul($f8_19, $f2_2, 25); 909 $f2f9_38 = self::mul($f9_38, $f2, 24); 910 $f3f3_2 = self::mul($f3_2, $f3, 24); 911 $f3f4_2 = self::mul($f3_2, $f4, 24); 912 $f3f5_4 = self::mul($f3_2, $f5_2, 24); 913 $f3f6_2 = self::mul($f3_2, $f6, 24); 914 $f3f7_76 = self::mul($f7_38, $f3_2, 24); 915 $f3f8_38 = self::mul($f8_19, $f3_2, 24); 916 $f3f9_76 = self::mul($f9_38, $f3_2, 24); 917 $f4f4 = self::mul($f4, $f4, 24); 918 $f4f5_2 = self::mul($f4_2, $f5, 24); 919 $f4f6_38 = self::mul($f6_19, $f4_2, 25); 920 $f4f7_38 = self::mul($f7_38, $f4, 24); 921 $f4f8_38 = self::mul($f8_19, $f4_2, 25); 922 $f4f9_38 = self::mul($f9_38, $f4, 24); 923 $f5f5_38 = self::mul($f5_38, $f5, 24); 924 $f5f6_38 = self::mul($f6_19, $f5_2, 24); 925 $f5f7_76 = self::mul($f7_38, $f5_2, 24); 926 $f5f8_38 = self::mul($f8_19, $f5_2, 24); 927 $f5f9_76 = self::mul($f9_38, $f5_2, 24); 928 $f6f6_19 = self::mul($f6_19, $f6, 24); 929 $f6f7_38 = self::mul($f7_38, $f6, 24); 930 $f6f8_38 = self::mul($f8_19, $f6_2, 25); 931 $f6f9_38 = self::mul($f9_38, $f6, 24); 932 $f7f7_38 = self::mul($f7_38, $f7, 24); 933 $f7f8_38 = self::mul($f8_19, $f7_2, 24); 934 $f7f9_76 = self::mul($f9_38, $f7_2, 24); 935 $f8f8_19 = self::mul($f8_19, $f8, 24); 936 $f8f9_38 = self::mul($f9_38, $f8, 24); 937 $f9f9_38 = self::mul($f9_38, $f9, 24); 938 939 /** @var int $h0 */ 940 $h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38) << 1; 941 /** @var int $h1 */ 942 $h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38) << 1; 943 /** @var int $h2 */ 944 $h2 = (int) ($f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19) << 1; 945 /** @var int $h3 */ 946 $h3 = (int) ($f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38) << 1; 947 /** @var int $h4 */ 948 $h4 = (int) ($f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38) << 1; 949 /** @var int $h5 */ 950 $h5 = (int) ($f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38) << 1; 951 /** @var int $h6 */ 952 $h6 = (int) ($f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19) << 1; 953 /** @var int $h7 */ 954 $h7 = (int) ($f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38) << 1; 955 /** @var int $h8 */ 956 $h8 = (int) ($f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38) << 1; 957 /** @var int $h9 */ 958 $h9 = (int) ($f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2) << 1; 959 960 /** @var int $carry0 */ 961 $carry0 = ($h0 + (1 << 25)) >> 26; 962 $h1 += $carry0; 963 $h0 -= $carry0 << 26; 964 /** @var int $carry4 */ 965 $carry4 = ($h4 + (1 << 25)) >> 26; 966 $h5 += $carry4; 967 $h4 -= $carry4 << 26; 968 969 /** @var int $carry1 */ 970 $carry1 = ($h1 + (1 << 24)) >> 25; 971 $h2 += $carry1; 972 $h1 -= $carry1 << 25; 973 /** @var int $carry5 */ 974 $carry5 = ($h5 + (1 << 24)) >> 25; 975 $h6 += $carry5; 976 $h5 -= $carry5 << 25; 977 978 /** @var int $carry2 */ 979 $carry2 = ($h2 + (1 << 25)) >> 26; 980 $h3 += $carry2; 981 $h2 -= $carry2 << 26; 982 /** @var int $carry6 */ 983 $carry6 = ($h6 + (1 << 25)) >> 26; 984 $h7 += $carry6; 985 $h6 -= $carry6 << 26; 986 987 /** @var int $carry3 */ 988 $carry3 = ($h3 + (1 << 24)) >> 25; 989 $h4 += $carry3; 990 $h3 -= $carry3 << 25; 991 /** @var int $carry7 */ 992 $carry7 = ($h7 + (1 << 24)) >> 25; 993 $h8 += $carry7; 994 $h7 -= $carry7 << 25; 995 996 /** @var int $carry4 */ 997 $carry4 = ($h4 + (1 << 25)) >> 26; 998 $h5 += $carry4; 999 $h4 -= $carry4 << 26; 1000 /** @var int $carry8 */ 1001 $carry8 = ($h8 + (1 << 25)) >> 26; 1002 $h9 += $carry8; 1003 $h8 -= $carry8 << 26; 1004 1005 /** @var int $carry9 */ 1006 $carry9 = ($h9 + (1 << 24)) >> 25; 1007 $h0 += self::mul($carry9, 19, 5); 1008 $h9 -= $carry9 << 25; 1009 1010 /** @var int $carry0 */ 1011 $carry0 = ($h0 + (1 << 25)) >> 26; 1012 $h1 += $carry0; 1013 $h0 -= $carry0 << 26; 1014 1015 return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( 1016 array( 1017 (int) $h0, 1018 (int) $h1, 1019 (int) $h2, 1020 (int) $h3, 1021 (int) $h4, 1022 (int) $h5, 1023 (int) $h6, 1024 (int) $h7, 1025 (int) $h8, 1026 (int) $h9 1027 ) 1028 ); 1029 } 1030 1031 /** 1032 * @internal You should not use this directly from another application 1033 * 1034 * @param ParagonIE_Sodium_Core_Curve25519_Fe $Z 1035 * @return ParagonIE_Sodium_Core_Curve25519_Fe 1036 */ 1037 public static function fe_invert(ParagonIE_Sodium_Core_Curve25519_Fe $Z) 1038 { 1039 $z = clone $Z; 1040 $t0 = self::fe_sq($z); 1041 $t1 = self::fe_sq($t0); 1042 $t1 = self::fe_sq($t1); 1043 $t1 = self::fe_mul($z, $t1); 1044 $t0 = self::fe_mul($t0, $t1); 1045 $t2 = self::fe_sq($t0); 1046 $t1 = self::fe_mul($t1, $t2); 1047 $t2 = self::fe_sq($t1); 1048 for ($i = 1; $i < 5; ++$i) { 1049 $t2 = self::fe_sq($t2); 1050 } 1051 $t1 = self::fe_mul($t2, $t1); 1052 $t2 = self::fe_sq($t1); 1053 for ($i = 1; $i < 10; ++$i) { 1054 $t2 = self::fe_sq($t2); 1055 } 1056 $t2 = self::fe_mul($t2, $t1); 1057 $t3 = self::fe_sq($t2); 1058 for ($i = 1; $i < 20; ++$i) { 1059 $t3 = self::fe_sq($t3); 1060 } 1061 $t2 = self::fe_mul($t3, $t2); 1062 $t2 = self::fe_sq($t2); 1063 for ($i = 1; $i < 10; ++$i) { 1064 $t2 = self::fe_sq($t2); 1065 } 1066 $t1 = self::fe_mul($t2, $t1); 1067 $t2 = self::fe_sq($t1); 1068 for ($i = 1; $i < 50; ++$i) { 1069 $t2 = self::fe_sq($t2); 1070 } 1071 $t2 = self::fe_mul($t2, $t1); 1072 $t3 = self::fe_sq($t2); 1073 for ($i = 1; $i < 100; ++$i) { 1074 $t3 = self::fe_sq($t3); 1075 } 1076 $t2 = self::fe_mul($t3, $t2); 1077 $t2 = self::fe_sq($t2); 1078 for ($i = 1; $i < 50; ++$i) { 1079 $t2 = self::fe_sq($t2); 1080 } 1081 $t1 = self::fe_mul($t2, $t1); 1082 $t1 = self::fe_sq($t1); 1083 for ($i = 1; $i < 5; ++$i) { 1084 $t1 = self::fe_sq($t1); 1085 } 1086 return self::fe_mul($t1, $t0); 1087 } 1088 1089 /** 1090 * @internal You should not use this directly from another application 1091 * 1092 * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106 1093 * 1094 * @param ParagonIE_Sodium_Core_Curve25519_Fe $z 1095 * @return ParagonIE_Sodium_Core_Curve25519_Fe 1096 */ 1097 public static function fe_pow22523(ParagonIE_Sodium_Core_Curve25519_Fe $z) 1098 { 1099 # fe_sq(t0, z); 1100 # fe_sq(t1, t0); 1101 # fe_sq(t1, t1); 1102 # fe_mul(t1, z, t1); 1103 # fe_mul(t0, t0, t1); 1104 # fe_sq(t0, t0); 1105 # fe_mul(t0, t1, t0); 1106 # fe_sq(t1, t0); 1107 $t0 = self::fe_sq($z); 1108 $t1 = self::fe_sq($t0); 1109 $t1 = self::fe_sq($t1); 1110 $t1 = self::fe_mul($z, $t1); 1111 $t0 = self::fe_mul($t0, $t1); 1112 $t0 = self::fe_sq($t0); 1113 $t0 = self::fe_mul($t1, $t0); 1114 $t1 = self::fe_sq($t0); 1115 1116 # for (i = 1; i < 5; ++i) { 1117 # fe_sq(t1, t1); 1118 # } 1119 for ($i = 1; $i < 5; ++$i) { 1120 $t1 = self::fe_sq($t1); 1121 } 1122 1123 # fe_mul(t0, t1, t0); 1124 # fe_sq(t1, t0); 1125 $t0 = self::fe_mul($t1, $t0); 1126 $t1 = self::fe_sq($t0); 1127 1128 # for (i = 1; i < 10; ++i) { 1129 # fe_sq(t1, t1); 1130 # } 1131 for ($i = 1; $i < 10; ++$i) { 1132 $t1 = self::fe_sq($t1); 1133 } 1134 1135 # fe_mul(t1, t1, t0); 1136 # fe_sq(t2, t1); 1137 $t1 = self::fe_mul($t1, $t0); 1138 $t2 = self::fe_sq($t1); 1139 1140 # for (i = 1; i < 20; ++i) { 1141 # fe_sq(t2, t2); 1142 # } 1143 for ($i = 1; $i < 20; ++$i) { 1144 $t2 = self::fe_sq($t2); 1145 } 1146 1147 # fe_mul(t1, t2, t1); 1148 # fe_sq(t1, t1); 1149 $t1 = self::fe_mul($t2, $t1); 1150 $t1 = self::fe_sq($t1); 1151 1152 # for (i = 1; i < 10; ++i) { 1153 # fe_sq(t1, t1); 1154 # } 1155 for ($i = 1; $i < 10; ++$i) { 1156 $t1 = self::fe_sq($t1); 1157 } 1158 1159 # fe_mul(t0, t1, t0); 1160 # fe_sq(t1, t0); 1161 $t0 = self::fe_mul($t1, $t0); 1162 $t1 = self::fe_sq($t0); 1163 1164 # for (i = 1; i < 50; ++i) { 1165 # fe_sq(t1, t1); 1166 # } 1167 for ($i = 1; $i < 50; ++$i) { 1168 $t1 = self::fe_sq($t1); 1169 } 1170 1171 # fe_mul(t1, t1, t0); 1172 # fe_sq(t2, t1); 1173 $t1 = self::fe_mul($t1, $t0); 1174 $t2 = self::fe_sq($t1); 1175 1176 # for (i = 1; i < 100; ++i) { 1177 # fe_sq(t2, t2); 1178 # } 1179 for ($i = 1; $i < 100; ++$i) { 1180 $t2 = self::fe_sq($t2); 1181 } 1182 1183 # fe_mul(t1, t2, t1); 1184 # fe_sq(t1, t1); 1185 $t1 = self::fe_mul($t2, $t1); 1186 $t1 = self::fe_sq($t1); 1187 1188 # for (i = 1; i < 50; ++i) { 1189 # fe_sq(t1, t1); 1190 # } 1191 for ($i = 1; $i < 50; ++$i) { 1192 $t1 = self::fe_sq($t1); 1193 } 1194 1195 # fe_mul(t0, t1, t0); 1196 # fe_sq(t0, t0); 1197 # fe_sq(t0, t0); 1198 # fe_mul(out, t0, z); 1199 $t0 = self::fe_mul($t1, $t0); 1200 $t0 = self::fe_sq($t0); 1201 $t0 = self::fe_sq($t0); 1202 return self::fe_mul($t0, $z); 1203 } 1204 1205 /** 1206 * Subtract two field elements. 1207 * 1208 * h = f - g 1209 * 1210 * Preconditions: 1211 * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 1212 * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 1213 * 1214 * Postconditions: 1215 * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 1216 * 1217 * @internal You should not use this directly from another application 1218 * 1219 * @param ParagonIE_Sodium_Core_Curve25519_Fe $f 1220 * @param ParagonIE_Sodium_Core_Curve25519_Fe $g 1221 * @return ParagonIE_Sodium_Core_Curve25519_Fe 1222 * @psalm-suppress MixedOperand 1223 */ 1224 public static function fe_sub(ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g) 1225 { 1226 return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( 1227 array( 1228 (int) ($f[0] - $g[0]), 1229 (int) ($f[1] - $g[1]), 1230 (int) ($f[2] - $g[2]), 1231 (int) ($f[3] - $g[3]), 1232 (int) ($f[4] - $g[4]), 1233 (int) ($f[5] - $g[5]), 1234 (int) ($f[6] - $g[6]), 1235 (int) ($f[7] - $g[7]), 1236 (int) ($f[8] - $g[8]), 1237 (int) ($f[9] - $g[9]) 1238 ) 1239 ); 1240 } 1241 1242 /** 1243 * Add two group elements. 1244 * 1245 * r = p + q 1246 * 1247 * @internal You should not use this directly from another application 1248 * 1249 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1250 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q 1251 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 1252 */ 1253 public static function ge_add( 1254 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, 1255 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q 1256 ) { 1257 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); 1258 $r->X = self::fe_add($p->Y, $p->X); 1259 $r->Y = self::fe_sub($p->Y, $p->X); 1260 $r->Z = self::fe_mul($r->X, $q->YplusX); 1261 $r->Y = self::fe_mul($r->Y, $q->YminusX); 1262 $r->T = self::fe_mul($q->T2d, $p->T); 1263 $r->X = self::fe_mul($p->Z, $q->Z); 1264 $t0 = self::fe_add($r->X, $r->X); 1265 $r->X = self::fe_sub($r->Z, $r->Y); 1266 $r->Y = self::fe_add($r->Z, $r->Y); 1267 $r->Z = self::fe_add($t0, $r->T); 1268 $r->T = self::fe_sub($t0, $r->T); 1269 return $r; 1270 } 1271 1272 /** 1273 * @internal You should not use this directly from another application 1274 * 1275 * @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215 1276 * @param string $a 1277 * @return array<int, mixed> 1278 * @throws SodiumException 1279 * @throws TypeError 1280 */ 1281 public static function slide($a) 1282 { 1283 if (self::strlen($a) < 256) { 1284 if (self::strlen($a) < 16) { 1285 $a = str_pad($a, 256, '0', STR_PAD_RIGHT); 1286 } 1287 } 1288 /** @var array<int, int> $r */ 1289 $r = array(); 1290 1291 /** @var int $i */ 1292 for ($i = 0; $i < 256; ++$i) { 1293 $r[$i] = (int) ( 1294 1 & ( 1295 self::chrToInt($a[(int) ($i >> 3)]) 1296 >> 1297 ($i & 7) 1298 ) 1299 ); 1300 } 1301 1302 for ($i = 0;$i < 256;++$i) { 1303 if ($r[$i]) { 1304 for ($b = 1;$b <= 6 && $i + $b < 256;++$b) { 1305 if ($r[$i + $b]) { 1306 if ($r[$i] + ($r[$i + $b] << $b) <= 15) { 1307 $r[$i] += $r[$i + $b] << $b; 1308 $r[$i + $b] = 0; 1309 } elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) { 1310 $r[$i] -= $r[$i + $b] << $b; 1311 for ($k = $i + $b; $k < 256; ++$k) { 1312 if (!$r[$k]) { 1313 $r[$k] = 1; 1314 break; 1315 } 1316 $r[$k] = 0; 1317 } 1318 } else { 1319 break; 1320 } 1321 } 1322 } 1323 } 1324 } 1325 return $r; 1326 } 1327 1328 /** 1329 * @internal You should not use this directly from another application 1330 * 1331 * @param string $s 1332 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 1333 * @throws SodiumException 1334 * @throws TypeError 1335 */ 1336 public static function ge_frombytes_negate_vartime($s) 1337 { 1338 static $d = null; 1339 if (!$d) { 1340 $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d); 1341 } 1342 1343 # fe_frombytes(h->Y,s); 1344 # fe_1(h->Z); 1345 $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3( 1346 self::fe_0(), 1347 self::fe_frombytes($s), 1348 self::fe_1() 1349 ); 1350 1351 # fe_sq(u,h->Y); 1352 # fe_mul(v,u,d); 1353 # fe_sub(u,u,h->Z); /* u = y^2-1 */ 1354 # fe_add(v,v,h->Z); /* v = dy^2+1 */ 1355 $u = self::fe_sq($h->Y); 1356 /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d */ 1357 $v = self::fe_mul($u, $d); 1358 $u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */ 1359 $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */ 1360 1361 # fe_sq(v3,v); 1362 # fe_mul(v3,v3,v); /* v3 = v^3 */ 1363 # fe_sq(h->X,v3); 1364 # fe_mul(h->X,h->X,v); 1365 # fe_mul(h->X,h->X,u); /* x = uv^7 */ 1366 $v3 = self::fe_sq($v); 1367 $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */ 1368 $h->X = self::fe_sq($v3); 1369 $h->X = self::fe_mul($h->X, $v); 1370 $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */ 1371 1372 # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ 1373 # fe_mul(h->X,h->X,v3); 1374 # fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ 1375 $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */ 1376 $h->X = self::fe_mul($h->X, $v3); 1377 $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */ 1378 1379 # fe_sq(vxx,h->X); 1380 # fe_mul(vxx,vxx,v); 1381 # fe_sub(check,vxx,u); /* vx^2-u */ 1382 $vxx = self::fe_sq($h->X); 1383 $vxx = self::fe_mul($vxx, $v); 1384 $check = self::fe_sub($vxx, $u); /* vx^2 - u */ 1385 1386 # if (fe_isnonzero(check)) { 1387 # fe_add(check,vxx,u); /* vx^2+u */ 1388 # if (fe_isnonzero(check)) { 1389 # return -1; 1390 # } 1391 # fe_mul(h->X,h->X,sqrtm1); 1392 # } 1393 if (self::fe_isnonzero($check)) { 1394 $check = self::fe_add($vxx, $u); /* vx^2 + u */ 1395 if (self::fe_isnonzero($check)) { 1396 throw new RangeException('Internal check failed.'); 1397 } 1398 $h->X = self::fe_mul( 1399 $h->X, 1400 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1) 1401 ); 1402 } 1403 1404 # if (fe_isnegative(h->X) == (s[31] >> 7)) { 1405 # fe_neg(h->X,h->X); 1406 # } 1407 $i = self::chrToInt($s[31]); 1408 if (self::fe_isnegative($h->X) === ($i >> 7)) { 1409 $h->X = self::fe_neg($h->X); 1410 } 1411 1412 # fe_mul(h->T,h->X,h->Y); 1413 $h->T = self::fe_mul($h->X, $h->Y); 1414 return $h; 1415 } 1416 1417 /** 1418 * @internal You should not use this directly from another application 1419 * 1420 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R 1421 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1422 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q 1423 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 1424 */ 1425 public static function ge_madd( 1426 ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R, 1427 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, 1428 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q 1429 ) { 1430 $r = clone $R; 1431 $r->X = self::fe_add($p->Y, $p->X); 1432 $r->Y = self::fe_sub($p->Y, $p->X); 1433 $r->Z = self::fe_mul($r->X, $q->yplusx); 1434 $r->Y = self::fe_mul($r->Y, $q->yminusx); 1435 $r->T = self::fe_mul($q->xy2d, $p->T); 1436 $t0 = self::fe_add(clone $p->Z, clone $p->Z); 1437 $r->X = self::fe_sub($r->Z, $r->Y); 1438 $r->Y = self::fe_add($r->Z, $r->Y); 1439 $r->Z = self::fe_add($t0, $r->T); 1440 $r->T = self::fe_sub($t0, $r->T); 1441 1442 return $r; 1443 } 1444 1445 /** 1446 * @internal You should not use this directly from another application 1447 * 1448 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R 1449 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1450 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q 1451 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 1452 */ 1453 public static function ge_msub( 1454 ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R, 1455 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, 1456 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q 1457 ) { 1458 $r = clone $R; 1459 1460 $r->X = self::fe_add($p->Y, $p->X); 1461 $r->Y = self::fe_sub($p->Y, $p->X); 1462 $r->Z = self::fe_mul($r->X, $q->yminusx); 1463 $r->Y = self::fe_mul($r->Y, $q->yplusx); 1464 $r->T = self::fe_mul($q->xy2d, $p->T); 1465 $t0 = self::fe_add($p->Z, $p->Z); 1466 $r->X = self::fe_sub($r->Z, $r->Y); 1467 $r->Y = self::fe_add($r->Z, $r->Y); 1468 $r->Z = self::fe_sub($t0, $r->T); 1469 $r->T = self::fe_add($t0, $r->T); 1470 1471 return $r; 1472 } 1473 1474 /** 1475 * @internal You should not use this directly from another application 1476 * 1477 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p 1478 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 1479 */ 1480 public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p) 1481 { 1482 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P2(); 1483 $r->X = self::fe_mul($p->X, $p->T); 1484 $r->Y = self::fe_mul($p->Y, $p->Z); 1485 $r->Z = self::fe_mul($p->Z, $p->T); 1486 return $r; 1487 } 1488 1489 /** 1490 * @internal You should not use this directly from another application 1491 * 1492 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p 1493 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 1494 */ 1495 public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p) 1496 { 1497 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(); 1498 $r->X = self::fe_mul($p->X, $p->T); 1499 $r->Y = self::fe_mul($p->Y, $p->Z); 1500 $r->Z = self::fe_mul($p->Z, $p->T); 1501 $r->T = self::fe_mul($p->X, $p->Y); 1502 return $r; 1503 } 1504 1505 /** 1506 * @internal You should not use this directly from another application 1507 * 1508 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 1509 */ 1510 public static function ge_p2_0() 1511 { 1512 return new ParagonIE_Sodium_Core_Curve25519_Ge_P2( 1513 self::fe_0(), 1514 self::fe_1(), 1515 self::fe_1() 1516 ); 1517 } 1518 1519 /** 1520 * @internal You should not use this directly from another application 1521 * 1522 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p 1523 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 1524 */ 1525 public static function ge_p2_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p) 1526 { 1527 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); 1528 1529 $r->X = self::fe_sq($p->X); 1530 $r->Z = self::fe_sq($p->Y); 1531 $r->T = self::fe_sq2($p->Z); 1532 $r->Y = self::fe_add($p->X, $p->Y); 1533 $t0 = self::fe_sq($r->Y); 1534 $r->Y = self::fe_add($r->Z, $r->X); 1535 $r->Z = self::fe_sub($r->Z, $r->X); 1536 $r->X = self::fe_sub($t0, $r->Y); 1537 $r->T = self::fe_sub($r->T, $r->Z); 1538 1539 return $r; 1540 } 1541 1542 /** 1543 * @internal You should not use this directly from another application 1544 * 1545 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 1546 */ 1547 public static function ge_p3_0() 1548 { 1549 return new ParagonIE_Sodium_Core_Curve25519_Ge_P3( 1550 self::fe_0(), 1551 self::fe_1(), 1552 self::fe_1(), 1553 self::fe_0() 1554 ); 1555 } 1556 1557 /** 1558 * @internal You should not use this directly from another application 1559 * 1560 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1561 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached 1562 */ 1563 public static function ge_p3_to_cached(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) 1564 { 1565 static $d2 = null; 1566 if ($d2 === null) { 1567 $d2 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d2); 1568 } 1569 /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d2 */ 1570 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(); 1571 $r->YplusX = self::fe_add($p->Y, $p->X); 1572 $r->YminusX = self::fe_sub($p->Y, $p->X); 1573 $r->Z = self::fe_copy($p->Z); 1574 $r->T2d = self::fe_mul($p->T, $d2); 1575 return $r; 1576 } 1577 1578 /** 1579 * @internal You should not use this directly from another application 1580 * 1581 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1582 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 1583 */ 1584 public static function ge_p3_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) 1585 { 1586 return new ParagonIE_Sodium_Core_Curve25519_Ge_P2( 1587 self::fe_copy($p->X), 1588 self::fe_copy($p->Y), 1589 self::fe_copy($p->Z) 1590 ); 1591 } 1592 1593 /** 1594 * @internal You should not use this directly from another application 1595 * 1596 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h 1597 * @return string 1598 * @throws SodiumException 1599 * @throws TypeError 1600 */ 1601 public static function ge_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h) 1602 { 1603 $recip = self::fe_invert($h->Z); 1604 $x = self::fe_mul($h->X, $recip); 1605 $y = self::fe_mul($h->Y, $recip); 1606 $s = self::fe_tobytes($y); 1607 $s[31] = self::intToChr( 1608 self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7) 1609 ); 1610 return $s; 1611 } 1612 1613 /** 1614 * @internal You should not use this directly from another application 1615 * 1616 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1617 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 1618 */ 1619 public static function ge_p3_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) 1620 { 1621 $q = self::ge_p3_to_p2($p); 1622 return self::ge_p2_dbl($q); 1623 } 1624 1625 /** 1626 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp 1627 */ 1628 public static function ge_precomp_0() 1629 { 1630 return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( 1631 self::fe_1(), 1632 self::fe_1(), 1633 self::fe_0() 1634 ); 1635 } 1636 1637 /** 1638 * @internal You should not use this directly from another application 1639 * 1640 * @param int $b 1641 * @param int $c 1642 * @return int 1643 */ 1644 public static function equal($b, $c) 1645 { 1646 return (int) ((($b ^ $c) - 1) >> 31) & 1; 1647 } 1648 1649 /** 1650 * @internal You should not use this directly from another application 1651 * 1652 * @param int|string $char 1653 * @return int (1 = yes, 0 = no) 1654 * @throws SodiumException 1655 * @throws TypeError 1656 */ 1657 public static function negative($char) 1658 { 1659 if (is_int($char)) { 1660 return ($char >> 63) & 1; 1661 } 1662 $x = self::chrToInt(self::substr($char, 0, 1)); 1663 return (int) ($x >> 63); 1664 } 1665 1666 /** 1667 * Conditional move 1668 * 1669 * @internal You should not use this directly from another application 1670 * 1671 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t 1672 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u 1673 * @param int $b 1674 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp 1675 */ 1676 public static function cmov( 1677 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t, 1678 ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u, 1679 $b 1680 ) { 1681 if (!is_int($b)) { 1682 throw new InvalidArgumentException('Expected an integer.'); 1683 } 1684 return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( 1685 self::fe_cmov($t->yplusx, $u->yplusx, $b), 1686 self::fe_cmov($t->yminusx, $u->yminusx, $b), 1687 self::fe_cmov($t->xy2d, $u->xy2d, $b) 1688 ); 1689 } 1690 1691 /** 1692 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t 1693 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u 1694 * @param int $b 1695 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached 1696 */ 1697 public static function ge_cmov_cached( 1698 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t, 1699 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u, 1700 $b 1701 ) { 1702 $b &= 1; 1703 $ret = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(); 1704 $ret->YplusX = self::fe_cmov($t->YplusX, $u->YplusX, $b); 1705 $ret->YminusX = self::fe_cmov($t->YminusX, $u->YminusX, $b); 1706 $ret->Z = self::fe_cmov($t->Z, $u->Z, $b); 1707 $ret->T2d = self::fe_cmov($t->T2d, $u->T2d, $b); 1708 return $ret; 1709 } 1710 1711 /** 1712 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $cached 1713 * @param int $b 1714 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached 1715 * @throws SodiumException 1716 */ 1717 public static function ge_cmov8_cached(array $cached, $b) 1718 { 1719 // const unsigned char bnegative = negative(b); 1720 // const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1)); 1721 $bnegative = self::negative($b); 1722 $babs = $b - (((-$bnegative) & $b) << 1); 1723 1724 // ge25519_cached_0(t); 1725 $t = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( 1726 self::fe_1(), 1727 self::fe_1(), 1728 self::fe_1(), 1729 self::fe_0() 1730 ); 1731 1732 // ge25519_cmov_cached(t, &cached[0], equal(babs, 1)); 1733 // ge25519_cmov_cached(t, &cached[1], equal(babs, 2)); 1734 // ge25519_cmov_cached(t, &cached[2], equal(babs, 3)); 1735 // ge25519_cmov_cached(t, &cached[3], equal(babs, 4)); 1736 // ge25519_cmov_cached(t, &cached[4], equal(babs, 5)); 1737 // ge25519_cmov_cached(t, &cached[5], equal(babs, 6)); 1738 // ge25519_cmov_cached(t, &cached[6], equal(babs, 7)); 1739 // ge25519_cmov_cached(t, &cached[7], equal(babs, 8)); 1740 for ($x = 0; $x < 8; ++$x) { 1741 $t = self::ge_cmov_cached($t, $cached[$x], self::equal($babs, $x + 1)); 1742 } 1743 1744 // fe25519_copy(minust.YplusX, t->YminusX); 1745 // fe25519_copy(minust.YminusX, t->YplusX); 1746 // fe25519_copy(minust.Z, t->Z); 1747 // fe25519_neg(minust.T2d, t->T2d); 1748 $minust = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( 1749 self::fe_copy($t->YminusX), 1750 self::fe_copy($t->YplusX), 1751 self::fe_copy($t->Z), 1752 self::fe_neg($t->T2d) 1753 ); 1754 return self::ge_cmov_cached($t, $minust, $bnegative); 1755 } 1756 1757 /** 1758 * @internal You should not use this directly from another application 1759 * 1760 * @param int $pos 1761 * @param int $b 1762 * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp 1763 * @throws SodiumException 1764 * @throws TypeError 1765 * @psalm-suppress MixedArgument 1766 * @psalm-suppress MixedArrayAccess 1767 * @psalm-suppress MixedArrayOffset 1768 */ 1769 public static function ge_select($pos = 0, $b = 0) 1770 { 1771 static $base = null; 1772 if ($base === null) { 1773 $base = array(); 1774 /** @var int $i */ 1775 foreach (self::$base as $i => $bas) { 1776 for ($j = 0; $j < 8; ++$j) { 1777 $base[$i][$j] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( 1778 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][0]), 1779 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][1]), 1780 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][2]) 1781 ); 1782 } 1783 } 1784 } 1785 /** @var array<int, array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp>> $base */ 1786 if (!is_int($pos)) { 1787 throw new InvalidArgumentException('Position must be an integer'); 1788 } 1789 if ($pos < 0 || $pos > 31) { 1790 throw new RangeException('Position is out of range [0, 31]'); 1791 } 1792 1793 /** @var int $bnegative */ 1794 $bnegative = self::negative($b); 1795 /** @var int $babs */ 1796 $babs = $b - (((-$bnegative) & $b) << 1); 1797 1798 $t = self::ge_precomp_0(); 1799 for ($i = 0; $i < 8; ++$i) { 1800 $t = self::cmov( 1801 $t, 1802 $base[$pos][$i], 1803 self::equal($babs, $i + 1) 1804 ); 1805 } 1806 $minusT = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( 1807 self::fe_copy($t->yminusx), 1808 self::fe_copy($t->yplusx), 1809 self::fe_neg($t->xy2d) 1810 ); 1811 return self::cmov($t, $minusT, $bnegative); 1812 } 1813 1814 /** 1815 * Subtract two group elements. 1816 * 1817 * r = p - q 1818 * 1819 * @internal You should not use this directly from another application 1820 * 1821 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1822 * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q 1823 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 1824 */ 1825 public static function ge_sub( 1826 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, 1827 ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q 1828 ) { 1829 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); 1830 1831 $r->X = self::fe_add($p->Y, $p->X); 1832 $r->Y = self::fe_sub($p->Y, $p->X); 1833 $r->Z = self::fe_mul($r->X, $q->YminusX); 1834 $r->Y = self::fe_mul($r->Y, $q->YplusX); 1835 $r->T = self::fe_mul($q->T2d, $p->T); 1836 $r->X = self::fe_mul($p->Z, $q->Z); 1837 $t0 = self::fe_add($r->X, $r->X); 1838 $r->X = self::fe_sub($r->Z, $r->Y); 1839 $r->Y = self::fe_add($r->Z, $r->Y); 1840 $r->Z = self::fe_sub($t0, $r->T); 1841 $r->T = self::fe_add($t0, $r->T); 1842 1843 return $r; 1844 } 1845 1846 /** 1847 * Convert a group element to a byte string. 1848 * 1849 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h 1850 * @return string 1851 * @throws SodiumException 1852 * @throws TypeError 1853 */ 1854 public static function ge_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h) 1855 { 1856 $recip = self::fe_invert($h->Z); 1857 $x = self::fe_mul($h->X, $recip); 1858 $y = self::fe_mul($h->Y, $recip); 1859 $s = self::fe_tobytes($y); 1860 $s[31] = self::intToChr( 1861 self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7) 1862 ); 1863 return $s; 1864 } 1865 1866 /** 1867 * @internal You should not use this directly from another application 1868 * 1869 * @param string $a 1870 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A 1871 * @param string $b 1872 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 1873 * @throws SodiumException 1874 * @throws TypeError 1875 * @psalm-suppress MixedArgument 1876 * @psalm-suppress MixedArrayAccess 1877 */ 1878 public static function ge_double_scalarmult_vartime( 1879 $a, 1880 ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A, 1881 $b 1882 ) { 1883 /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai */ 1884 $Ai = array(); 1885 1886 /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp> $Bi */ 1887 static $Bi = array(); 1888 if (!$Bi) { 1889 for ($i = 0; $i < 8; ++$i) { 1890 $Bi[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( 1891 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][0]), 1892 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][1]), 1893 ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][2]) 1894 ); 1895 } 1896 } 1897 for ($i = 0; $i < 8; ++$i) { 1898 $Ai[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( 1899 self::fe_0(), 1900 self::fe_0(), 1901 self::fe_0(), 1902 self::fe_0() 1903 ); 1904 } 1905 1906 # slide(aslide,a); 1907 # slide(bslide,b); 1908 /** @var array<int, int> $aslide */ 1909 $aslide = self::slide($a); 1910 /** @var array<int, int> $bslide */ 1911 $bslide = self::slide($b); 1912 1913 # ge_p3_to_cached(&Ai[0],A); 1914 # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); 1915 $Ai[0] = self::ge_p3_to_cached($A); 1916 $t = self::ge_p3_dbl($A); 1917 $A2 = self::ge_p1p1_to_p3($t); 1918 1919 # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); 1920 # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); 1921 # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); 1922 # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); 1923 # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); 1924 # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); 1925 # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); 1926 for ($i = 0; $i < 7; ++$i) { 1927 $t = self::ge_add($A2, $Ai[$i]); 1928 $u = self::ge_p1p1_to_p3($t); 1929 $Ai[$i + 1] = self::ge_p3_to_cached($u); 1930 } 1931 1932 # ge_p2_0(r); 1933 $r = self::ge_p2_0(); 1934 1935 # for (i = 255;i >= 0;--i) { 1936 # if (aslide[i] || bslide[i]) break; 1937 # } 1938 $i = 255; 1939 for (; $i >= 0; --$i) { 1940 if ($aslide[$i] || $bslide[$i]) { 1941 break; 1942 } 1943 } 1944 1945 # for (;i >= 0;--i) { 1946 for (; $i >= 0; --$i) { 1947 # ge_p2_dbl(&t,r); 1948 $t = self::ge_p2_dbl($r); 1949 1950 # if (aslide[i] > 0) { 1951 if ($aslide[$i] > 0) { 1952 # ge_p1p1_to_p3(&u,&t); 1953 # ge_add(&t,&u,&Ai[aslide[i]/2]); 1954 $u = self::ge_p1p1_to_p3($t); 1955 $t = self::ge_add( 1956 $u, 1957 $Ai[(int) floor($aslide[$i] / 2)] 1958 ); 1959 # } else if (aslide[i] < 0) { 1960 } elseif ($aslide[$i] < 0) { 1961 # ge_p1p1_to_p3(&u,&t); 1962 # ge_sub(&t,&u,&Ai[(-aslide[i])/2]); 1963 $u = self::ge_p1p1_to_p3($t); 1964 $t = self::ge_sub( 1965 $u, 1966 $Ai[(int) floor(-$aslide[$i] / 2)] 1967 ); 1968 } 1969 1970 # if (bslide[i] > 0) { 1971 if ($bslide[$i] > 0) { 1972 /** @var int $index */ 1973 $index = (int) floor($bslide[$i] / 2); 1974 # ge_p1p1_to_p3(&u,&t); 1975 # ge_madd(&t,&u,&Bi[bslide[i]/2]); 1976 $u = self::ge_p1p1_to_p3($t); 1977 $t = self::ge_madd($t, $u, $Bi[$index]); 1978 # } else if (bslide[i] < 0) { 1979 } elseif ($bslide[$i] < 0) { 1980 /** @var int $index */ 1981 $index = (int) floor(-$bslide[$i] / 2); 1982 # ge_p1p1_to_p3(&u,&t); 1983 # ge_msub(&t,&u,&Bi[(-bslide[i])/2]); 1984 $u = self::ge_p1p1_to_p3($t); 1985 $t = self::ge_msub($t, $u, $Bi[$index]); 1986 } 1987 # ge_p1p1_to_p2(r,&t); 1988 $r = self::ge_p1p1_to_p2($t); 1989 } 1990 return $r; 1991 } 1992 1993 /** 1994 * @internal You should not use this directly from another application 1995 * 1996 * @param string $a 1997 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p 1998 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 1999 * @throws SodiumException 2000 * @throws TypeError 2001 * @psalm-suppress MixedAssignment 2002 * @psalm-suppress MixedOperand 2003 */ 2004 public static function ge_scalarmult($a, $p) 2005 { 2006 $e = array_fill(0, 64, 0); 2007 2008 /** @var ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $pi */ 2009 $pi = array(); 2010 2011 // ge25519_p3_to_cached(&pi[1 - 1], p); /* p */ 2012 $pi[0] = self::ge_p3_to_cached($p); 2013 2014 // ge25519_p3_dbl(&t2, p); 2015 // ge25519_p1p1_to_p3(&p2, &t2); 2016 // ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */ 2017 $t2 = self::ge_p3_dbl($p); 2018 $p2 = self::ge_p1p1_to_p3($t2); 2019 $pi[1] = self::ge_p3_to_cached($p2); 2020 2021 // ge25519_add_cached(&t3, p, &pi[2 - 1]); 2022 // ge25519_p1p1_to_p3(&p3, &t3); 2023 // ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */ 2024 $t3 = self::ge_add($p, $pi[1]); 2025 $p3 = self::ge_p1p1_to_p3($t3); 2026 $pi[2] = self::ge_p3_to_cached($p3); 2027 2028 // ge25519_p3_dbl(&t4, &p2); 2029 // ge25519_p1p1_to_p3(&p4, &t4); 2030 // ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */ 2031 $t4 = self::ge_p3_dbl($p2); 2032 $p4 = self::ge_p1p1_to_p3($t4); 2033 $pi[3] = self::ge_p3_to_cached($p4); 2034 2035 // ge25519_add_cached(&t5, p, &pi[4 - 1]); 2036 // ge25519_p1p1_to_p3(&p5, &t5); 2037 // ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */ 2038 $t5 = self::ge_add($p, $pi[3]); 2039 $p5 = self::ge_p1p1_to_p3($t5); 2040 $pi[4] = self::ge_p3_to_cached($p5); 2041 2042 // ge25519_p3_dbl(&t6, &p3); 2043 // ge25519_p1p1_to_p3(&p6, &t6); 2044 // ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */ 2045 $t6 = self::ge_p3_dbl($p3); 2046 $p6 = self::ge_p1p1_to_p3($t6); 2047 $pi[5] = self::ge_p3_to_cached($p6); 2048 2049 // ge25519_add_cached(&t7, p, &pi[6 - 1]); 2050 // ge25519_p1p1_to_p3(&p7, &t7); 2051 // ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */ 2052 $t7 = self::ge_add($p, $pi[5]); 2053 $p7 = self::ge_p1p1_to_p3($t7); 2054 $pi[6] = self::ge_p3_to_cached($p7); 2055 2056 // ge25519_p3_dbl(&t8, &p4); 2057 // ge25519_p1p1_to_p3(&p8, &t8); 2058 // ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */ 2059 $t8 = self::ge_p3_dbl($p4); 2060 $p8 = self::ge_p1p1_to_p3($t8); 2061 $pi[7] = self::ge_p3_to_cached($p8); 2062 2063 2064 // for (i = 0; i < 32; ++i) { 2065 // e[2 * i + 0] = (a[i] >> 0) & 15; 2066 // e[2 * i + 1] = (a[i] >> 4) & 15; 2067 // } 2068 for ($i = 0; $i < 32; ++$i) { 2069 $e[($i << 1) ] = self::chrToInt($a[$i]) & 15; 2070 $e[($i << 1) + 1] = (self::chrToInt($a[$i]) >> 4) & 15; 2071 } 2072 // /* each e[i] is between 0 and 15 */ 2073 // /* e[63] is between 0 and 7 */ 2074 2075 // carry = 0; 2076 // for (i = 0; i < 63; ++i) { 2077 // e[i] += carry; 2078 // carry = e[i] + 8; 2079 // carry >>= 4; 2080 // e[i] -= carry * ((signed char) 1 << 4); 2081 // } 2082 $carry = 0; 2083 for ($i = 0; $i < 64; ++$i) { 2084 $e[$i] += $carry; 2085 $carry = $e[$i] + 8; 2086 $carry >>= 4; 2087 $e[$i] -= $carry << 4; 2088 } 2089 // e[63] += carry; 2090 // /* each e[i] is between -8 and 8 */ 2091 $e[63] += $carry; 2092 2093 // ge25519_p3_0(h); 2094 $h = self::ge_p3_0(); 2095 2096 // for (i = 63; i != 0; i--) { 2097 for ($i = 63; $i != 0; --$i) { 2098 // ge25519_cmov8_cached(&t, pi, e[i]); 2099 $t = self::ge_cmov8_cached($pi, $e[$i]); 2100 // ge25519_add_cached(&r, h, &t); 2101 $r = self::ge_add($h, $t); 2102 2103 // ge25519_p1p1_to_p2(&s, &r); 2104 // ge25519_p2_dbl(&r, &s); 2105 // ge25519_p1p1_to_p2(&s, &r); 2106 // ge25519_p2_dbl(&r, &s); 2107 // ge25519_p1p1_to_p2(&s, &r); 2108 // ge25519_p2_dbl(&r, &s); 2109 // ge25519_p1p1_to_p2(&s, &r); 2110 // ge25519_p2_dbl(&r, &s); 2111 $s = self::ge_p1p1_to_p2($r); 2112 $r = self::ge_p2_dbl($s); 2113 $s = self::ge_p1p1_to_p2($r); 2114 $r = self::ge_p2_dbl($s); 2115 $s = self::ge_p1p1_to_p2($r); 2116 $r = self::ge_p2_dbl($s); 2117 $s = self::ge_p1p1_to_p2($r); 2118 $r = self::ge_p2_dbl($s); 2119 2120 // ge25519_p1p1_to_p3(h, &r); /* *16 */ 2121 $h = self::ge_p1p1_to_p3($r); /* *16 */ 2122 } 2123 2124 // ge25519_cmov8_cached(&t, pi, e[i]); 2125 // ge25519_add_cached(&r, h, &t); 2126 // ge25519_p1p1_to_p3(h, &r); 2127 $t = self::ge_cmov8_cached($pi, $e[0]); 2128 $r = self::ge_add($h, $t); 2129 return self::ge_p1p1_to_p3($r); 2130 } 2131 2132 /** 2133 * @internal You should not use this directly from another application 2134 * 2135 * @param string $a 2136 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 2137 * @throws SodiumException 2138 * @throws TypeError 2139 * @psalm-suppress MixedAssignment 2140 * @psalm-suppress MixedOperand 2141 */ 2142 public static function ge_scalarmult_base($a) 2143 { 2144 /** @var array<int, int> $e */ 2145 $e = array(); 2146 $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); 2147 2148 for ($i = 0; $i < 32; ++$i) { 2149 /** @var int $dbl */ 2150 $dbl = (int) $i << 1; 2151 $e[$dbl] = (int) self::chrToInt($a[$i]) & 15; 2152 $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15; 2153 } 2154 2155 /** @var int $carry */ 2156 $carry = 0; 2157 for ($i = 0; $i < 63; ++$i) { 2158 $e[$i] += $carry; 2159 /** @var int $carry */ 2160 $carry = $e[$i] + 8; 2161 /** @var int $carry */ 2162 $carry >>= 4; 2163 $e[$i] -= $carry << 4; 2164 } 2165 /** @var array<int, int> $e */ 2166 $e[63] += (int) $carry; 2167 2168 $h = self::ge_p3_0(); 2169 2170 for ($i = 1; $i < 64; $i += 2) { 2171 $t = self::ge_select((int) floor($i / 2), (int) $e[$i]); 2172 $r = self::ge_madd($r, $h, $t); 2173 $h = self::ge_p1p1_to_p3($r); 2174 } 2175 2176 $r = self::ge_p3_dbl($h); 2177 2178 $s = self::ge_p1p1_to_p2($r); 2179 $r = self::ge_p2_dbl($s); 2180 $s = self::ge_p1p1_to_p2($r); 2181 $r = self::ge_p2_dbl($s); 2182 $s = self::ge_p1p1_to_p2($r); 2183 $r = self::ge_p2_dbl($s); 2184 2185 $h = self::ge_p1p1_to_p3($r); 2186 2187 for ($i = 0; $i < 64; $i += 2) { 2188 $t = self::ge_select($i >> 1, (int) $e[$i]); 2189 $r = self::ge_madd($r, $h, $t); 2190 $h = self::ge_p1p1_to_p3($r); 2191 } 2192 return $h; 2193 } 2194 2195 /** 2196 * Calculates (ab + c) mod l 2197 * where l = 2^252 + 27742317777372353535851937790883648493 2198 * 2199 * @internal You should not use this directly from another application 2200 * 2201 * @param string $a 2202 * @param string $b 2203 * @param string $c 2204 * @return string 2205 * @throws TypeError 2206 */ 2207 public static function sc_muladd($a, $b, $c) 2208 { 2209 /** @var int $a0 */ 2210 $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); 2211 /** @var int $a1 */ 2212 $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); 2213 /** @var int $a2 */ 2214 $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); 2215 /** @var int $a3 */ 2216 $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); 2217 /** @var int $a4 */ 2218 $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); 2219 /** @var int $a5 */ 2220 $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); 2221 /** @var int $a6 */ 2222 $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); 2223 /** @var int $a7 */ 2224 $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); 2225 /** @var int $a8 */ 2226 $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); 2227 /** @var int $a9 */ 2228 $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); 2229 /** @var int $a10 */ 2230 $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); 2231 /** @var int $a11 */ 2232 $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); 2233 2234 /** @var int $b0 */ 2235 $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); 2236 /** @var int $b1 */ 2237 $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); 2238 /** @var int $b2 */ 2239 $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); 2240 /** @var int $b3 */ 2241 $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); 2242 /** @var int $b4 */ 2243 $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); 2244 /** @var int $b5 */ 2245 $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); 2246 /** @var int $b6 */ 2247 $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); 2248 /** @var int $b7 */ 2249 $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); 2250 /** @var int $b8 */ 2251 $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); 2252 /** @var int $b9 */ 2253 $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); 2254 /** @var int $b10 */ 2255 $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); 2256 /** @var int $b11 */ 2257 $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); 2258 2259 /** @var int $c0 */ 2260 $c0 = 2097151 & self::load_3(self::substr($c, 0, 3)); 2261 /** @var int $c1 */ 2262 $c1 = 2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5); 2263 /** @var int $c2 */ 2264 $c2 = 2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2); 2265 /** @var int $c3 */ 2266 $c3 = 2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7); 2267 /** @var int $c4 */ 2268 $c4 = 2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4); 2269 /** @var int $c5 */ 2270 $c5 = 2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1); 2271 /** @var int $c6 */ 2272 $c6 = 2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6); 2273 /** @var int $c7 */ 2274 $c7 = 2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3); 2275 /** @var int $c8 */ 2276 $c8 = 2097151 & self::load_3(self::substr($c, 21, 3)); 2277 /** @var int $c9 */ 2278 $c9 = 2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5); 2279 /** @var int $c10 */ 2280 $c10 = 2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2); 2281 /** @var int $c11 */ 2282 $c11 = (self::load_4(self::substr($c, 28, 4)) >> 7); 2283 2284 /* Can't really avoid the pyramid here: */ 2285 $s0 = $c0 + self::mul($a0, $b0, 24); 2286 $s1 = $c1 + self::mul($a0, $b1, 24) + self::mul($a1, $b0, 24); 2287 $s2 = $c2 + self::mul($a0, $b2, 24) + self::mul($a1, $b1, 24) + self::mul($a2, $b0, 24); 2288 $s3 = $c3 + self::mul($a0, $b3, 24) + self::mul($a1, $b2, 24) + self::mul($a2, $b1, 24) + self::mul($a3, $b0, 24); 2289 $s4 = $c4 + self::mul($a0, $b4, 24) + self::mul($a1, $b3, 24) + self::mul($a2, $b2, 24) + self::mul($a3, $b1, 24) + 2290 self::mul($a4, $b0, 24); 2291 $s5 = $c5 + self::mul($a0, $b5, 24) + self::mul($a1, $b4, 24) + self::mul($a2, $b3, 24) + self::mul($a3, $b2, 24) + 2292 self::mul($a4, $b1, 24) + self::mul($a5, $b0, 24); 2293 $s6 = $c6 + self::mul($a0, $b6, 24) + self::mul($a1, $b5, 24) + self::mul($a2, $b4, 24) + self::mul($a3, $b3, 24) + 2294 self::mul($a4, $b2, 24) + self::mul($a5, $b1, 24) + self::mul($a6, $b0, 24); 2295 $s7 = $c7 + self::mul($a0, $b7, 24) + self::mul($a1, $b6, 24) + self::mul($a2, $b5, 24) + self::mul($a3, $b4, 24) + 2296 self::mul($a4, $b3, 24) + self::mul($a5, $b2, 24) + self::mul($a6, $b1, 24) + self::mul($a7, $b0, 24); 2297 $s8 = $c8 + self::mul($a0, $b8, 24) + self::mul($a1, $b7, 24) + self::mul($a2, $b6, 24) + self::mul($a3, $b5, 24) + 2298 self::mul($a4, $b4, 24) + self::mul($a5, $b3, 24) + self::mul($a6, $b2, 24) + self::mul($a7, $b1, 24) + 2299 self::mul($a8, $b0, 24); 2300 $s9 = $c9 + self::mul($a0, $b9, 24) + self::mul($a1, $b8, 24) + self::mul($a2, $b7, 24) + self::mul($a3, $b6, 24) + 2301 self::mul($a4, $b5, 24) + self::mul($a5, $b4, 24) + self::mul($a6, $b3, 24) + self::mul($a7, $b2, 24) + 2302 self::mul($a8, $b1, 24) + self::mul($a9, $b0, 24); 2303 $s10 = $c10 + self::mul($a0, $b10, 24) + self::mul($a1, $b9, 24) + self::mul($a2, $b8, 24) + self::mul($a3, $b7, 24) + 2304 self::mul($a4, $b6, 24) + self::mul($a5, $b5, 24) + self::mul($a6, $b4, 24) + self::mul($a7, $b3, 24) + 2305 self::mul($a8, $b2, 24) + self::mul($a9, $b1, 24) + self::mul($a10, $b0, 24); 2306 $s11 = $c11 + self::mul($a0, $b11, 24) + self::mul($a1, $b10, 24) + self::mul($a2, $b9, 24) + self::mul($a3, $b8, 24) + 2307 self::mul($a4, $b7, 24) + self::mul($a5, $b6, 24) + self::mul($a6, $b5, 24) + self::mul($a7, $b4, 24) + 2308 self::mul($a8, $b3, 24) + self::mul($a9, $b2, 24) + self::mul($a10, $b1, 24) + self::mul($a11, $b0, 24); 2309 $s12 = self::mul($a1, $b11, 24) + self::mul($a2, $b10, 24) + self::mul($a3, $b9, 24) + self::mul($a4, $b8, 24) + 2310 self::mul($a5, $b7, 24) + self::mul($a6, $b6, 24) + self::mul($a7, $b5, 24) + self::mul($a8, $b4, 24) + 2311 self::mul($a9, $b3, 24) + self::mul($a10, $b2, 24) + self::mul($a11, $b1, 24); 2312 $s13 = self::mul($a2, $b11, 24) + self::mul($a3, $b10, 24) + self::mul($a4, $b9, 24) + self::mul($a5, $b8, 24) + 2313 self::mul($a6, $b7, 24) + self::mul($a7, $b6, 24) + self::mul($a8, $b5, 24) + self::mul($a9, $b4, 24) + 2314 self::mul($a10, $b3, 24) + self::mul($a11, $b2, 24); 2315 $s14 = self::mul($a3, $b11, 24) + self::mul($a4, $b10, 24) + self::mul($a5, $b9, 24) + self::mul($a6, $b8, 24) + 2316 self::mul($a7, $b7, 24) + self::mul($a8, $b6, 24) + self::mul($a9, $b5, 24) + self::mul($a10, $b4, 24) + 2317 self::mul($a11, $b3, 24); 2318 $s15 = self::mul($a4, $b11, 24) + self::mul($a5, $b10, 24) + self::mul($a6, $b9, 24) + self::mul($a7, $b8, 24) + 2319 self::mul($a8, $b7, 24) + self::mul($a9, $b6, 24) + self::mul($a10, $b5, 24) + self::mul($a11, $b4, 24); 2320 $s16 = self::mul($a5, $b11, 24) + self::mul($a6, $b10, 24) + self::mul($a7, $b9, 24) + self::mul($a8, $b8, 24) + 2321 self::mul($a9, $b7, 24) + self::mul($a10, $b6, 24) + self::mul($a11, $b5, 24); 2322 $s17 = self::mul($a6, $b11, 24) + self::mul($a7, $b10, 24) + self::mul($a8, $b9, 24) + self::mul($a9, $b8, 24) + 2323 self::mul($a10, $b7, 24) + self::mul($a11, $b6, 24); 2324 $s18 = self::mul($a7, $b11, 24) + self::mul($a8, $b10, 24) + self::mul($a9, $b9, 24) + self::mul($a10, $b8, 24) + 2325 self::mul($a11, $b7, 24); 2326 $s19 = self::mul($a8, $b11, 24) + self::mul($a9, $b10, 24) + self::mul($a10, $b9, 24) + self::mul($a11, $b8, 24); 2327 $s20 = self::mul($a9, $b11, 24) + self::mul($a10, $b10, 24) + self::mul($a11, $b9, 24); 2328 $s21 = self::mul($a10, $b11, 24) + self::mul($a11, $b10, 24); 2329 $s22 = self::mul($a11, $b11, 24); 2330 $s23 = 0; 2331 2332 /** @var int $carry0 */ 2333 $carry0 = ($s0 + (1 << 20)) >> 21; 2334 $s1 += $carry0; 2335 $s0 -= $carry0 << 21; 2336 /** @var int $carry2 */ 2337 $carry2 = ($s2 + (1 << 20)) >> 21; 2338 $s3 += $carry2; 2339 $s2 -= $carry2 << 21; 2340 /** @var int $carry4 */ 2341 $carry4 = ($s4 + (1 << 20)) >> 21; 2342 $s5 += $carry4; 2343 $s4 -= $carry4 << 21; 2344 /** @var int $carry6 */ 2345 $carry6 = ($s6 + (1 << 20)) >> 21; 2346 $s7 += $carry6; 2347 $s6 -= $carry6 << 21; 2348 /** @var int $carry8 */ 2349 $carry8 = ($s8 + (1 << 20)) >> 21; 2350 $s9 += $carry8; 2351 $s8 -= $carry8 << 21; 2352 /** @var int $carry10 */ 2353 $carry10 = ($s10 + (1 << 20)) >> 21; 2354 $s11 += $carry10; 2355 $s10 -= $carry10 << 21; 2356 /** @var int $carry12 */ 2357 $carry12 = ($s12 + (1 << 20)) >> 21; 2358 $s13 += $carry12; 2359 $s12 -= $carry12 << 21; 2360 /** @var int $carry14 */ 2361 $carry14 = ($s14 + (1 << 20)) >> 21; 2362 $s15 += $carry14; 2363 $s14 -= $carry14 << 21; 2364 /** @var int $carry16 */ 2365 $carry16 = ($s16 + (1 << 20)) >> 21; 2366 $s17 += $carry16; 2367 $s16 -= $carry16 << 21; 2368 /** @var int $carry18 */ 2369 $carry18 = ($s18 + (1 << 20)) >> 21; 2370 $s19 += $carry18; 2371 $s18 -= $carry18 << 21; 2372 /** @var int $carry20 */ 2373 $carry20 = ($s20 + (1 << 20)) >> 21; 2374 $s21 += $carry20; 2375 $s20 -= $carry20 << 21; 2376 /** @var int $carry22 */ 2377 $carry22 = ($s22 + (1 << 20)) >> 21; 2378 $s23 += $carry22; 2379 $s22 -= $carry22 << 21; 2380 2381 /** @var int $carry1 */ 2382 $carry1 = ($s1 + (1 << 20)) >> 21; 2383 $s2 += $carry1; 2384 $s1 -= $carry1 << 21; 2385 /** @var int $carry3 */ 2386 $carry3 = ($s3 + (1 << 20)) >> 21; 2387 $s4 += $carry3; 2388 $s3 -= $carry3 << 21; 2389 /** @var int $carry5 */ 2390 $carry5 = ($s5 + (1 << 20)) >> 21; 2391 $s6 += $carry5; 2392 $s5 -= $carry5 << 21; 2393 /** @var int $carry7 */ 2394 $carry7 = ($s7 + (1 << 20)) >> 21; 2395 $s8 += $carry7; 2396 $s7 -= $carry7 << 21; 2397 /** @var int $carry9 */ 2398 $carry9 = ($s9 + (1 << 20)) >> 21; 2399 $s10 += $carry9; 2400 $s9 -= $carry9 << 21; 2401 /** @var int $carry11 */ 2402 $carry11 = ($s11 + (1 << 20)) >> 21; 2403 $s12 += $carry11; 2404 $s11 -= $carry11 << 21; 2405 /** @var int $carry13 */ 2406 $carry13 = ($s13 + (1 << 20)) >> 21; 2407 $s14 += $carry13; 2408 $s13 -= $carry13 << 21; 2409 /** @var int $carry15 */ 2410 $carry15 = ($s15 + (1 << 20)) >> 21; 2411 $s16 += $carry15; 2412 $s15 -= $carry15 << 21; 2413 /** @var int $carry17 */ 2414 $carry17 = ($s17 + (1 << 20)) >> 21; 2415 $s18 += $carry17; 2416 $s17 -= $carry17 << 21; 2417 /** @var int $carry19 */ 2418 $carry19 = ($s19 + (1 << 20)) >> 21; 2419 $s20 += $carry19; 2420 $s19 -= $carry19 << 21; 2421 /** @var int $carry21 */ 2422 $carry21 = ($s21 + (1 << 20)) >> 21; 2423 $s22 += $carry21; 2424 $s21 -= $carry21 << 21; 2425 2426 $s11 += self::mul($s23, 666643, 20); 2427 $s12 += self::mul($s23, 470296, 19); 2428 $s13 += self::mul($s23, 654183, 20); 2429 $s14 -= self::mul($s23, 997805, 20); 2430 $s15 += self::mul($s23, 136657, 18); 2431 $s16 -= self::mul($s23, 683901, 20); 2432 2433 $s10 += self::mul($s22, 666643, 20); 2434 $s11 += self::mul($s22, 470296, 19); 2435 $s12 += self::mul($s22, 654183, 20); 2436 $s13 -= self::mul($s22, 997805, 20); 2437 $s14 += self::mul($s22, 136657, 18); 2438 $s15 -= self::mul($s22, 683901, 20); 2439 2440 $s9 += self::mul($s21, 666643, 20); 2441 $s10 += self::mul($s21, 470296, 19); 2442 $s11 += self::mul($s21, 654183, 20); 2443 $s12 -= self::mul($s21, 997805, 20); 2444 $s13 += self::mul($s21, 136657, 18); 2445 $s14 -= self::mul($s21, 683901, 20); 2446 2447 $s8 += self::mul($s20, 666643, 20); 2448 $s9 += self::mul($s20, 470296, 19); 2449 $s10 += self::mul($s20, 654183, 20); 2450 $s11 -= self::mul($s20, 997805, 20); 2451 $s12 += self::mul($s20, 136657, 18); 2452 $s13 -= self::mul($s20, 683901, 20); 2453 2454 $s7 += self::mul($s19, 666643, 20); 2455 $s8 += self::mul($s19, 470296, 19); 2456 $s9 += self::mul($s19, 654183, 20); 2457 $s10 -= self::mul($s19, 997805, 20); 2458 $s11 += self::mul($s19, 136657, 18); 2459 $s12 -= self::mul($s19, 683901, 20); 2460 2461 $s6 += self::mul($s18, 666643, 20); 2462 $s7 += self::mul($s18, 470296, 19); 2463 $s8 += self::mul($s18, 654183, 20); 2464 $s9 -= self::mul($s18, 997805, 20); 2465 $s10 += self::mul($s18, 136657, 18); 2466 $s11 -= self::mul($s18, 683901, 20); 2467 2468 /** @var int $carry6 */ 2469 $carry6 = ($s6 + (1 << 20)) >> 21; 2470 $s7 += $carry6; 2471 $s6 -= $carry6 << 21; 2472 /** @var int $carry8 */ 2473 $carry8 = ($s8 + (1 << 20)) >> 21; 2474 $s9 += $carry8; 2475 $s8 -= $carry8 << 21; 2476 /** @var int $carry10 */ 2477 $carry10 = ($s10 + (1 << 20)) >> 21; 2478 $s11 += $carry10; 2479 $s10 -= $carry10 << 21; 2480 /** @var int $carry12 */ 2481 $carry12 = ($s12 + (1 << 20)) >> 21; 2482 $s13 += $carry12; 2483 $s12 -= $carry12 << 21; 2484 /** @var int $carry14 */ 2485 $carry14 = ($s14 + (1 << 20)) >> 21; 2486 $s15 += $carry14; 2487 $s14 -= $carry14 << 21; 2488 /** @var int $carry16 */ 2489 $carry16 = ($s16 + (1 << 20)) >> 21; 2490 $s17 += $carry16; 2491 $s16 -= $carry16 << 21; 2492 2493 /** @var int $carry7 */ 2494 $carry7 = ($s7 + (1 << 20)) >> 21; 2495 $s8 += $carry7; 2496 $s7 -= $carry7 << 21; 2497 /** @var int $carry9 */ 2498 $carry9 = ($s9 + (1 << 20)) >> 21; 2499 $s10 += $carry9; 2500 $s9 -= $carry9 << 21; 2501 /** @var int $carry11 */ 2502 $carry11 = ($s11 + (1 << 20)) >> 21; 2503 $s12 += $carry11; 2504 $s11 -= $carry11 << 21; 2505 /** @var int $carry13 */ 2506 $carry13 = ($s13 + (1 << 20)) >> 21; 2507 $s14 += $carry13; 2508 $s13 -= $carry13 << 21; 2509 /** @var int $carry15 */ 2510 $carry15 = ($s15 + (1 << 20)) >> 21; 2511 $s16 += $carry15; 2512 $s15 -= $carry15 << 21; 2513 2514 $s5 += self::mul($s17, 666643, 20); 2515 $s6 += self::mul($s17, 470296, 19); 2516 $s7 += self::mul($s17, 654183, 20); 2517 $s8 -= self::mul($s17, 997805, 20); 2518 $s9 += self::mul($s17, 136657, 18); 2519 $s10 -= self::mul($s17, 683901, 20); 2520 2521 $s4 += self::mul($s16, 666643, 20); 2522 $s5 += self::mul($s16, 470296, 19); 2523 $s6 += self::mul($s16, 654183, 20); 2524 $s7 -= self::mul($s16, 997805, 20); 2525 $s8 += self::mul($s16, 136657, 18); 2526 $s9 -= self::mul($s16, 683901, 20); 2527 2528 $s3 += self::mul($s15, 666643, 20); 2529 $s4 += self::mul($s15, 470296, 19); 2530 $s5 += self::mul($s15, 654183, 20); 2531 $s6 -= self::mul($s15, 997805, 20); 2532 $s7 += self::mul($s15, 136657, 18); 2533 $s8 -= self::mul($s15, 683901, 20); 2534 2535 $s2 += self::mul($s14, 666643, 20); 2536 $s3 += self::mul($s14, 470296, 19); 2537 $s4 += self::mul($s14, 654183, 20); 2538 $s5 -= self::mul($s14, 997805, 20); 2539 $s6 += self::mul($s14, 136657, 18); 2540 $s7 -= self::mul($s14, 683901, 20); 2541 2542 $s1 += self::mul($s13, 666643, 20); 2543 $s2 += self::mul($s13, 470296, 19); 2544 $s3 += self::mul($s13, 654183, 20); 2545 $s4 -= self::mul($s13, 997805, 20); 2546 $s5 += self::mul($s13, 136657, 18); 2547 $s6 -= self::mul($s13, 683901, 20); 2548 2549 $s0 += self::mul($s12, 666643, 20); 2550 $s1 += self::mul($s12, 470296, 19); 2551 $s2 += self::mul($s12, 654183, 20); 2552 $s3 -= self::mul($s12, 997805, 20); 2553 $s4 += self::mul($s12, 136657, 18); 2554 $s5 -= self::mul($s12, 683901, 20); 2555 $s12 = 0; 2556 2557 /** @var int $carry0 */ 2558 $carry0 = ($s0 + (1 << 20)) >> 21; 2559 $s1 += $carry0; 2560 $s0 -= $carry0 << 21; 2561 /** @var int $carry2 */ 2562 $carry2 = ($s2 + (1 << 20)) >> 21; 2563 $s3 += $carry2; 2564 $s2 -= $carry2 << 21; 2565 /** @var int $carry4 */ 2566 $carry4 = ($s4 + (1 << 20)) >> 21; 2567 $s5 += $carry4; 2568 $s4 -= $carry4 << 21; 2569 /** @var int $carry6 */ 2570 $carry6 = ($s6 + (1 << 20)) >> 21; 2571 $s7 += $carry6; 2572 $s6 -= $carry6 << 21; 2573 /** @var int $carry8 */ 2574 $carry8 = ($s8 + (1 << 20)) >> 21; 2575 $s9 += $carry8; 2576 $s8 -= $carry8 << 21; 2577 /** @var int $carry10 */ 2578 $carry10 = ($s10 + (1 << 20)) >> 21; 2579 $s11 += $carry10; 2580 $s10 -= $carry10 << 21; 2581 2582 /** @var int $carry1 */ 2583 $carry1 = ($s1 + (1 << 20)) >> 21; 2584 $s2 += $carry1; 2585 $s1 -= $carry1 << 21; 2586 /** @var int $carry3 */ 2587 $carry3 = ($s3 + (1 << 20)) >> 21; 2588 $s4 += $carry3; 2589 $s3 -= $carry3 << 21; 2590 /** @var int $carry5 */ 2591 $carry5 = ($s5 + (1 << 20)) >> 21; 2592 $s6 += $carry5; 2593 $s5 -= $carry5 << 21; 2594 /** @var int $carry7 */ 2595 $carry7 = ($s7 + (1 << 20)) >> 21; 2596 $s8 += $carry7; 2597 $s7 -= $carry7 << 21; 2598 /** @var int $carry9 */ 2599 $carry9 = ($s9 + (1 << 20)) >> 21; 2600 $s10 += $carry9; 2601 $s9 -= $carry9 << 21; 2602 /** @var int $carry11 */ 2603 $carry11 = ($s11 + (1 << 20)) >> 21; 2604 $s12 += $carry11; 2605 $s11 -= $carry11 << 21; 2606 2607 $s0 += self::mul($s12, 666643, 20); 2608 $s1 += self::mul($s12, 470296, 19); 2609 $s2 += self::mul($s12, 654183, 20); 2610 $s3 -= self::mul($s12, 997805, 20); 2611 $s4 += self::mul($s12, 136657, 18); 2612 $s5 -= self::mul($s12, 683901, 20); 2613 $s12 = 0; 2614 2615 /** @var int $carry0 */ 2616 $carry0 = $s0 >> 21; 2617 $s1 += $carry0; 2618 $s0 -= $carry0 << 21; 2619 /** @var int $carry1 */ 2620 $carry1 = $s1 >> 21; 2621 $s2 += $carry1; 2622 $s1 -= $carry1 << 21; 2623 /** @var int $carry2 */ 2624 $carry2 = $s2 >> 21; 2625 $s3 += $carry2; 2626 $s2 -= $carry2 << 21; 2627 /** @var int $carry3 */ 2628 $carry3 = $s3 >> 21; 2629 $s4 += $carry3; 2630 $s3 -= $carry3 << 21; 2631 /** @var int $carry4 */ 2632 $carry4 = $s4 >> 21; 2633 $s5 += $carry4; 2634 $s4 -= $carry4 << 21; 2635 /** @var int $carry5 */ 2636 $carry5 = $s5 >> 21; 2637 $s6 += $carry5; 2638 $s5 -= $carry5 << 21; 2639 /** @var int $carry6 */ 2640 $carry6 = $s6 >> 21; 2641 $s7 += $carry6; 2642 $s6 -= $carry6 << 21; 2643 /** @var int $carry7 */ 2644 $carry7 = $s7 >> 21; 2645 $s8 += $carry7; 2646 $s7 -= $carry7 << 21; 2647 /** @var int $carry8 */ 2648 $carry8 = $s8 >> 21; 2649 $s9 += $carry8; 2650 $s8 -= $carry8 << 21; 2651 /** @var int $carry9 */ 2652 $carry9 = $s9 >> 21; 2653 $s10 += $carry9; 2654 $s9 -= $carry9 << 21; 2655 /** @var int $carry10 */ 2656 $carry10 = $s10 >> 21; 2657 $s11 += $carry10; 2658 $s10 -= $carry10 << 21; 2659 /** @var int $carry11 */ 2660 $carry11 = $s11 >> 21; 2661 $s12 += $carry11; 2662 $s11 -= $carry11 << 21; 2663 2664 $s0 += self::mul($s12, 666643, 20); 2665 $s1 += self::mul($s12, 470296, 19); 2666 $s2 += self::mul($s12, 654183, 20); 2667 $s3 -= self::mul($s12, 997805, 20); 2668 $s4 += self::mul($s12, 136657, 18); 2669 $s5 -= self::mul($s12, 683901, 20); 2670 2671 /** @var int $carry0 */ 2672 $carry0 = $s0 >> 21; 2673 $s1 += $carry0; 2674 $s0 -= $carry0 << 21; 2675 /** @var int $carry1 */ 2676 $carry1 = $s1 >> 21; 2677 $s2 += $carry1; 2678 $s1 -= $carry1 << 21; 2679 /** @var int $carry2 */ 2680 $carry2 = $s2 >> 21; 2681 $s3 += $carry2; 2682 $s2 -= $carry2 << 21; 2683 /** @var int $carry3 */ 2684 $carry3 = $s3 >> 21; 2685 $s4 += $carry3; 2686 $s3 -= $carry3 << 21; 2687 /** @var int $carry4 */ 2688 $carry4 = $s4 >> 21; 2689 $s5 += $carry4; 2690 $s4 -= $carry4 << 21; 2691 /** @var int $carry5 */ 2692 $carry5 = $s5 >> 21; 2693 $s6 += $carry5; 2694 $s5 -= $carry5 << 21; 2695 /** @var int $carry6 */ 2696 $carry6 = $s6 >> 21; 2697 $s7 += $carry6; 2698 $s6 -= $carry6 << 21; 2699 /** @var int $carry7 */ 2700 $carry7 = $s7 >> 21; 2701 $s8 += $carry7; 2702 $s7 -= $carry7 << 21; 2703 /** @var int $carry8 */ 2704 $carry8 = $s8 >> 21; 2705 $s9 += $carry8; 2706 $s8 -= $carry8 << 21; 2707 /** @var int $carry9 */ 2708 $carry9 = $s9 >> 21; 2709 $s10 += $carry9; 2710 $s9 -= $carry9 << 21; 2711 /** @var int $carry10 */ 2712 $carry10 = $s10 >> 21; 2713 $s11 += $carry10; 2714 $s10 -= $carry10 << 21; 2715 2716 /** 2717 * @var array<int, int> 2718 */ 2719 $arr = array( 2720 (int) (0xff & ($s0 >> 0)), 2721 (int) (0xff & ($s0 >> 8)), 2722 (int) (0xff & (($s0 >> 16) | $s1 << 5)), 2723 (int) (0xff & ($s1 >> 3)), 2724 (int) (0xff & ($s1 >> 11)), 2725 (int) (0xff & (($s1 >> 19) | $s2 << 2)), 2726 (int) (0xff & ($s2 >> 6)), 2727 (int) (0xff & (($s2 >> 14) | $s3 << 7)), 2728 (int) (0xff & ($s3 >> 1)), 2729 (int) (0xff & ($s3 >> 9)), 2730 (int) (0xff & (($s3 >> 17) | $s4 << 4)), 2731 (int) (0xff & ($s4 >> 4)), 2732 (int) (0xff & ($s4 >> 12)), 2733 (int) (0xff & (($s4 >> 20) | $s5 << 1)), 2734 (int) (0xff & ($s5 >> 7)), 2735 (int) (0xff & (($s5 >> 15) | $s6 << 6)), 2736 (int) (0xff & ($s6 >> 2)), 2737 (int) (0xff & ($s6 >> 10)), 2738 (int) (0xff & (($s6 >> 18) | $s7 << 3)), 2739 (int) (0xff & ($s7 >> 5)), 2740 (int) (0xff & ($s7 >> 13)), 2741 (int) (0xff & ($s8 >> 0)), 2742 (int) (0xff & ($s8 >> 8)), 2743 (int) (0xff & (($s8 >> 16) | $s9 << 5)), 2744 (int) (0xff & ($s9 >> 3)), 2745 (int) (0xff & ($s9 >> 11)), 2746 (int) (0xff & (($s9 >> 19) | $s10 << 2)), 2747 (int) (0xff & ($s10 >> 6)), 2748 (int) (0xff & (($s10 >> 14) | $s11 << 7)), 2749 (int) (0xff & ($s11 >> 1)), 2750 (int) (0xff & ($s11 >> 9)), 2751 0xff & ($s11 >> 17) 2752 ); 2753 return self::intArrayToString($arr); 2754 } 2755 2756 /** 2757 * @internal You should not use this directly from another application 2758 * 2759 * @param string $s 2760 * @return string 2761 * @throws TypeError 2762 */ 2763 public static function sc_reduce($s) 2764 { 2765 /** @var int $s0 */ 2766 $s0 = 2097151 & self::load_3(self::substr($s, 0, 3)); 2767 /** @var int $s1 */ 2768 $s1 = 2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5); 2769 /** @var int $s2 */ 2770 $s2 = 2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2); 2771 /** @var int $s3 */ 2772 $s3 = 2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7); 2773 /** @var int $s4 */ 2774 $s4 = 2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4); 2775 /** @var int $s5 */ 2776 $s5 = 2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1); 2777 /** @var int $s6 */ 2778 $s6 = 2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6); 2779 /** @var int $s7 */ 2780 $s7 = 2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3); 2781 /** @var int $s8 */ 2782 $s8 = 2097151 & self::load_3(self::substr($s, 21, 3)); 2783 /** @var int $s9 */ 2784 $s9 = 2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5); 2785 /** @var int $s10 */ 2786 $s10 = 2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2); 2787 /** @var int $s11 */ 2788 $s11 = 2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7); 2789 /** @var int $s12 */ 2790 $s12 = 2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4); 2791 /** @var int $s13 */ 2792 $s13 = 2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1); 2793 /** @var int $s14 */ 2794 $s14 = 2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6); 2795 /** @var int $s15 */ 2796 $s15 = 2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3); 2797 /** @var int $s16 */ 2798 $s16 = 2097151 & self::load_3(self::substr($s, 42, 3)); 2799 /** @var int $s17 */ 2800 $s17 = 2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5); 2801 /** @var int $s18 */ 2802 $s18 = 2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2); 2803 /** @var int $s19 */ 2804 $s19 = 2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7); 2805 /** @var int $s20 */ 2806 $s20 = 2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4); 2807 /** @var int $s21 */ 2808 $s21 = 2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1); 2809 /** @var int $s22 */ 2810 $s22 = 2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6); 2811 /** @var int $s23 */ 2812 $s23 = (self::load_4(self::substr($s, 60, 4)) >> 3); 2813 2814 $s11 += self::mul($s23, 666643, 20); 2815 $s12 += self::mul($s23, 470296, 19); 2816 $s13 += self::mul($s23, 654183, 20); 2817 $s14 -= self::mul($s23, 997805, 20); 2818 $s15 += self::mul($s23, 136657, 18); 2819 $s16 -= self::mul($s23, 683901, 20); 2820 2821 $s10 += self::mul($s22, 666643, 20); 2822 $s11 += self::mul($s22, 470296, 19); 2823 $s12 += self::mul($s22, 654183, 20); 2824 $s13 -= self::mul($s22, 997805, 20); 2825 $s14 += self::mul($s22, 136657, 18); 2826 $s15 -= self::mul($s22, 683901, 20); 2827 2828 $s9 += self::mul($s21, 666643, 20); 2829 $s10 += self::mul($s21, 470296, 19); 2830 $s11 += self::mul($s21, 654183, 20); 2831 $s12 -= self::mul($s21, 997805, 20); 2832 $s13 += self::mul($s21, 136657, 18); 2833 $s14 -= self::mul($s21, 683901, 20); 2834 2835 $s8 += self::mul($s20, 666643, 20); 2836 $s9 += self::mul($s20, 470296, 19); 2837 $s10 += self::mul($s20, 654183, 20); 2838 $s11 -= self::mul($s20, 997805, 20); 2839 $s12 += self::mul($s20, 136657, 18); 2840 $s13 -= self::mul($s20, 683901, 20); 2841 2842 $s7 += self::mul($s19, 666643, 20); 2843 $s8 += self::mul($s19, 470296, 19); 2844 $s9 += self::mul($s19, 654183, 20); 2845 $s10 -= self::mul($s19, 997805, 20); 2846 $s11 += self::mul($s19, 136657, 18); 2847 $s12 -= self::mul($s19, 683901, 20); 2848 2849 $s6 += self::mul($s18, 666643, 20); 2850 $s7 += self::mul($s18, 470296, 19); 2851 $s8 += self::mul($s18, 654183, 20); 2852 $s9 -= self::mul($s18, 997805, 20); 2853 $s10 += self::mul($s18, 136657, 18); 2854 $s11 -= self::mul($s18, 683901, 20); 2855 2856 /** @var int $carry6 */ 2857 $carry6 = ($s6 + (1 << 20)) >> 21; 2858 $s7 += $carry6; 2859 $s6 -= $carry6 << 21; 2860 /** @var int $carry8 */ 2861 $carry8 = ($s8 + (1 << 20)) >> 21; 2862 $s9 += $carry8; 2863 $s8 -= $carry8 << 21; 2864 /** @var int $carry10 */ 2865 $carry10 = ($s10 + (1 << 20)) >> 21; 2866 $s11 += $carry10; 2867 $s10 -= $carry10 << 21; 2868 /** @var int $carry12 */ 2869 $carry12 = ($s12 + (1 << 20)) >> 21; 2870 $s13 += $carry12; 2871 $s12 -= $carry12 << 21; 2872 /** @var int $carry14 */ 2873 $carry14 = ($s14 + (1 << 20)) >> 21; 2874 $s15 += $carry14; 2875 $s14 -= $carry14 << 21; 2876 /** @var int $carry16 */ 2877 $carry16 = ($s16 + (1 << 20)) >> 21; 2878 $s17 += $carry16; 2879 $s16 -= $carry16 << 21; 2880 2881 /** @var int $carry7 */ 2882 $carry7 = ($s7 + (1 << 20)) >> 21; 2883 $s8 += $carry7; 2884 $s7 -= $carry7 << 21; 2885 /** @var int $carry9 */ 2886 $carry9 = ($s9 + (1 << 20)) >> 21; 2887 $s10 += $carry9; 2888 $s9 -= $carry9 << 21; 2889 /** @var int $carry11 */ 2890 $carry11 = ($s11 + (1 << 20)) >> 21; 2891 $s12 += $carry11; 2892 $s11 -= $carry11 << 21; 2893 /** @var int $carry13 */ 2894 $carry13 = ($s13 + (1 << 20)) >> 21; 2895 $s14 += $carry13; 2896 $s13 -= $carry13 << 21; 2897 /** @var int $carry15 */ 2898 $carry15 = ($s15 + (1 << 20)) >> 21; 2899 $s16 += $carry15; 2900 $s15 -= $carry15 << 21; 2901 2902 $s5 += self::mul($s17, 666643, 20); 2903 $s6 += self::mul($s17, 470296, 19); 2904 $s7 += self::mul($s17, 654183, 20); 2905 $s8 -= self::mul($s17, 997805, 20); 2906 $s9 += self::mul($s17, 136657, 18); 2907 $s10 -= self::mul($s17, 683901, 20); 2908 2909 $s4 += self::mul($s16, 666643, 20); 2910 $s5 += self::mul($s16, 470296, 19); 2911 $s6 += self::mul($s16, 654183, 20); 2912 $s7 -= self::mul($s16, 997805, 20); 2913 $s8 += self::mul($s16, 136657, 18); 2914 $s9 -= self::mul($s16, 683901, 20); 2915 2916 $s3 += self::mul($s15, 666643, 20); 2917 $s4 += self::mul($s15, 470296, 19); 2918 $s5 += self::mul($s15, 654183, 20); 2919 $s6 -= self::mul($s15, 997805, 20); 2920 $s7 += self::mul($s15, 136657, 18); 2921 $s8 -= self::mul($s15, 683901, 20); 2922 2923 $s2 += self::mul($s14, 666643, 20); 2924 $s3 += self::mul($s14, 470296, 19); 2925 $s4 += self::mul($s14, 654183, 20); 2926 $s5 -= self::mul($s14, 997805, 20); 2927 $s6 += self::mul($s14, 136657, 18); 2928 $s7 -= self::mul($s14, 683901, 20); 2929 2930 $s1 += self::mul($s13, 666643, 20); 2931 $s2 += self::mul($s13, 470296, 19); 2932 $s3 += self::mul($s13, 654183, 20); 2933 $s4 -= self::mul($s13, 997805, 20); 2934 $s5 += self::mul($s13, 136657, 18); 2935 $s6 -= self::mul($s13, 683901, 20); 2936 2937 $s0 += self::mul($s12, 666643, 20); 2938 $s1 += self::mul($s12, 470296, 19); 2939 $s2 += self::mul($s12, 654183, 20); 2940 $s3 -= self::mul($s12, 997805, 20); 2941 $s4 += self::mul($s12, 136657, 18); 2942 $s5 -= self::mul($s12, 683901, 20); 2943 $s12 = 0; 2944 2945 /** @var int $carry0 */ 2946 $carry0 = ($s0 + (1 << 20)) >> 21; 2947 $s1 += $carry0; 2948 $s0 -= $carry0 << 21; 2949 /** @var int $carry2 */ 2950 $carry2 = ($s2 + (1 << 20)) >> 21; 2951 $s3 += $carry2; 2952 $s2 -= $carry2 << 21; 2953 /** @var int $carry4 */ 2954 $carry4 = ($s4 + (1 << 20)) >> 21; 2955 $s5 += $carry4; 2956 $s4 -= $carry4 << 21; 2957 /** @var int $carry6 */ 2958 $carry6 = ($s6 + (1 << 20)) >> 21; 2959 $s7 += $carry6; 2960 $s6 -= $carry6 << 21; 2961 /** @var int $carry8 */ 2962 $carry8 = ($s8 + (1 << 20)) >> 21; 2963 $s9 += $carry8; 2964 $s8 -= $carry8 << 21; 2965 /** @var int $carry10 */ 2966 $carry10 = ($s10 + (1 << 20)) >> 21; 2967 $s11 += $carry10; 2968 $s10 -= $carry10 << 21; 2969 2970 /** @var int $carry1 */ 2971 $carry1 = ($s1 + (1 << 20)) >> 21; 2972 $s2 += $carry1; 2973 $s1 -= $carry1 << 21; 2974 /** @var int $carry3 */ 2975 $carry3 = ($s3 + (1 << 20)) >> 21; 2976 $s4 += $carry3; 2977 $s3 -= $carry3 << 21; 2978 /** @var int $carry5 */ 2979 $carry5 = ($s5 + (1 << 20)) >> 21; 2980 $s6 += $carry5; 2981 $s5 -= $carry5 << 21; 2982 /** @var int $carry7 */ 2983 $carry7 = ($s7 + (1 << 20)) >> 21; 2984 $s8 += $carry7; 2985 $s7 -= $carry7 << 21; 2986 /** @var int $carry9 */ 2987 $carry9 = ($s9 + (1 << 20)) >> 21; 2988 $s10 += $carry9; 2989 $s9 -= $carry9 << 21; 2990 /** @var int $carry11 */ 2991 $carry11 = ($s11 + (1 << 20)) >> 21; 2992 $s12 += $carry11; 2993 $s11 -= $carry11 << 21; 2994 2995 $s0 += self::mul($s12, 666643, 20); 2996 $s1 += self::mul($s12, 470296, 19); 2997 $s2 += self::mul($s12, 654183, 20); 2998 $s3 -= self::mul($s12, 997805, 20); 2999 $s4 += self::mul($s12, 136657, 18); 3000 $s5 -= self::mul($s12, 683901, 20); 3001 $s12 = 0; 3002 3003 /** @var int $carry0 */ 3004 $carry0 = $s0 >> 21; 3005 $s1 += $carry0; 3006 $s0 -= $carry0 << 21; 3007 /** @var int $carry1 */ 3008 $carry1 = $s1 >> 21; 3009 $s2 += $carry1; 3010 $s1 -= $carry1 << 21; 3011 /** @var int $carry2 */ 3012 $carry2 = $s2 >> 21; 3013 $s3 += $carry2; 3014 $s2 -= $carry2 << 21; 3015 /** @var int $carry3 */ 3016 $carry3 = $s3 >> 21; 3017 $s4 += $carry3; 3018 $s3 -= $carry3 << 21; 3019 /** @var int $carry4 */ 3020 $carry4 = $s4 >> 21; 3021 $s5 += $carry4; 3022 $s4 -= $carry4 << 21; 3023 /** @var int $carry5 */ 3024 $carry5 = $s5 >> 21; 3025 $s6 += $carry5; 3026 $s5 -= $carry5 << 21; 3027 /** @var int $carry6 */ 3028 $carry6 = $s6 >> 21; 3029 $s7 += $carry6; 3030 $s6 -= $carry6 << 21; 3031 /** @var int $carry7 */ 3032 $carry7 = $s7 >> 21; 3033 $s8 += $carry7; 3034 $s7 -= $carry7 << 21; 3035 /** @var int $carry8 */ 3036 $carry8 = $s8 >> 21; 3037 $s9 += $carry8; 3038 $s8 -= $carry8 << 21; 3039 /** @var int $carry9 */ 3040 $carry9 = $s9 >> 21; 3041 $s10 += $carry9; 3042 $s9 -= $carry9 << 21; 3043 /** @var int $carry10 */ 3044 $carry10 = $s10 >> 21; 3045 $s11 += $carry10; 3046 $s10 -= $carry10 << 21; 3047 /** @var int $carry11 */ 3048 $carry11 = $s11 >> 21; 3049 $s12 += $carry11; 3050 $s11 -= $carry11 << 21; 3051 3052 $s0 += self::mul($s12, 666643, 20); 3053 $s1 += self::mul($s12, 470296, 19); 3054 $s2 += self::mul($s12, 654183, 20); 3055 $s3 -= self::mul($s12, 997805, 20); 3056 $s4 += self::mul($s12, 136657, 18); 3057 $s5 -= self::mul($s12, 683901, 20); 3058 3059 /** @var int $carry0 */ 3060 $carry0 = $s0 >> 21; 3061 $s1 += $carry0; 3062 $s0 -= $carry0 << 21; 3063 /** @var int $carry1 */ 3064 $carry1 = $s1 >> 21; 3065 $s2 += $carry1; 3066 $s1 -= $carry1 << 21; 3067 /** @var int $carry2 */ 3068 $carry2 = $s2 >> 21; 3069 $s3 += $carry2; 3070 $s2 -= $carry2 << 21; 3071 /** @var int $carry3 */ 3072 $carry3 = $s3 >> 21; 3073 $s4 += $carry3; 3074 $s3 -= $carry3 << 21; 3075 /** @var int $carry4 */ 3076 $carry4 = $s4 >> 21; 3077 $s5 += $carry4; 3078 $s4 -= $carry4 << 21; 3079 /** @var int $carry5 */ 3080 $carry5 = $s5 >> 21; 3081 $s6 += $carry5; 3082 $s5 -= $carry5 << 21; 3083 /** @var int $carry6 */ 3084 $carry6 = $s6 >> 21; 3085 $s7 += $carry6; 3086 $s6 -= $carry6 << 21; 3087 /** @var int $carry7 */ 3088 $carry7 = $s7 >> 21; 3089 $s8 += $carry7; 3090 $s7 -= $carry7 << 21; 3091 /** @var int $carry8 */ 3092 $carry8 = $s8 >> 21; 3093 $s9 += $carry8; 3094 $s8 -= $carry8 << 21; 3095 /** @var int $carry9 */ 3096 $carry9 = $s9 >> 21; 3097 $s10 += $carry9; 3098 $s9 -= $carry9 << 21; 3099 /** @var int $carry10 */ 3100 $carry10 = $s10 >> 21; 3101 $s11 += $carry10; 3102 $s10 -= $carry10 << 21; 3103 3104 /** 3105 * @var array<int, int> 3106 */ 3107 $arr = array( 3108 (int) ($s0 >> 0), 3109 (int) ($s0 >> 8), 3110 (int) (($s0 >> 16) | $s1 << 5), 3111 (int) ($s1 >> 3), 3112 (int) ($s1 >> 11), 3113 (int) (($s1 >> 19) | $s2 << 2), 3114 (int) ($s2 >> 6), 3115 (int) (($s2 >> 14) | $s3 << 7), 3116 (int) ($s3 >> 1), 3117 (int) ($s3 >> 9), 3118 (int) (($s3 >> 17) | $s4 << 4), 3119 (int) ($s4 >> 4), 3120 (int) ($s4 >> 12), 3121 (int) (($s4 >> 20) | $s5 << 1), 3122 (int) ($s5 >> 7), 3123 (int) (($s5 >> 15) | $s6 << 6), 3124 (int) ($s6 >> 2), 3125 (int) ($s6 >> 10), 3126 (int) (($s6 >> 18) | $s7 << 3), 3127 (int) ($s7 >> 5), 3128 (int) ($s7 >> 13), 3129 (int) ($s8 >> 0), 3130 (int) ($s8 >> 8), 3131 (int) (($s8 >> 16) | $s9 << 5), 3132 (int) ($s9 >> 3), 3133 (int) ($s9 >> 11), 3134 (int) (($s9 >> 19) | $s10 << 2), 3135 (int) ($s10 >> 6), 3136 (int) (($s10 >> 14) | $s11 << 7), 3137 (int) ($s11 >> 1), 3138 (int) ($s11 >> 9), 3139 (int) $s11 >> 17 3140 ); 3141 return self::intArrayToString($arr); 3142 } 3143 3144 /** 3145 * multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493 3146 * 3147 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A 3148 * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 3149 */ 3150 public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A) 3151 { 3152 /** @var array<int, int> $aslide */ 3153 $aslide = array( 3154 13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 3155 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 3156 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 3157 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, 3158 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 3159 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0, 3160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 3166 ); 3167 3168 /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai size 8 */ 3169 $Ai = array(); 3170 3171 # ge_p3_to_cached(&Ai[0], A); 3172 $Ai[0] = self::ge_p3_to_cached($A); 3173 # ge_p3_dbl(&t, A); 3174 $t = self::ge_p3_dbl($A); 3175 # ge_p1p1_to_p3(&A2, &t); 3176 $A2 = self::ge_p1p1_to_p3($t); 3177 3178 for ($i = 1; $i < 8; ++$i) { 3179 # ge_add(&t, &A2, &Ai[0]); 3180 $t = self::ge_add($A2, $Ai[$i - 1]); 3181 # ge_p1p1_to_p3(&u, &t); 3182 $u = self::ge_p1p1_to_p3($t); 3183 # ge_p3_to_cached(&Ai[i], &u); 3184 $Ai[$i] = self::ge_p3_to_cached($u); 3185 } 3186 3187 $r = self::ge_p3_0(); 3188 for ($i = 252; $i >= 0; --$i) { 3189 $t = self::ge_p3_dbl($r); 3190 if ($aslide[$i] > 0) { 3191 # ge_p1p1_to_p3(&u, &t); 3192 $u = self::ge_p1p1_to_p3($t); 3193 # ge_add(&t, &u, &Ai[aslide[i] / 2]); 3194 $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]); 3195 } elseif ($aslide[$i] < 0) { 3196 # ge_p1p1_to_p3(&u, &t); 3197 $u = self::ge_p1p1_to_p3($t); 3198 # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); 3199 $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]); 3200 } 3201 } 3202 3203 # ge_p1p1_to_p3(r, &t); 3204 return self::ge_p1p1_to_p3($t); 3205 } 3206 3207 /** 3208 * @param string $a 3209 * @param string $b 3210 * @return string 3211 */ 3212 public static function sc25519_mul($a, $b) 3213 { 3214 // int64_t a0 = 2097151 & load_3(a); 3215 // int64_t a1 = 2097151 & (load_4(a + 2) >> 5); 3216 // int64_t a2 = 2097151 & (load_3(a + 5) >> 2); 3217 // int64_t a3 = 2097151 & (load_4(a + 7) >> 7); 3218 // int64_t a4 = 2097151 & (load_4(a + 10) >> 4); 3219 // int64_t a5 = 2097151 & (load_3(a + 13) >> 1); 3220 // int64_t a6 = 2097151 & (load_4(a + 15) >> 6); 3221 // int64_t a7 = 2097151 & (load_3(a + 18) >> 3); 3222 // int64_t a8 = 2097151 & load_3(a + 21); 3223 // int64_t a9 = 2097151 & (load_4(a + 23) >> 5); 3224 // int64_t a10 = 2097151 & (load_3(a + 26) >> 2); 3225 // int64_t a11 = (load_4(a + 28) >> 7); 3226 $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); 3227 $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); 3228 $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); 3229 $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); 3230 $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); 3231 $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); 3232 $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); 3233 $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); 3234 $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); 3235 $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); 3236 $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); 3237 $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); 3238 3239 // int64_t b0 = 2097151 & load_3(b); 3240 // int64_t b1 = 2097151 & (load_4(b + 2) >> 5); 3241 // int64_t b2 = 2097151 & (load_3(b + 5) >> 2); 3242 // int64_t b3 = 2097151 & (load_4(b + 7) >> 7); 3243 // int64_t b4 = 2097151 & (load_4(b + 10) >> 4); 3244 // int64_t b5 = 2097151 & (load_3(b + 13) >> 1); 3245 // int64_t b6 = 2097151 & (load_4(b + 15) >> 6); 3246 // int64_t b7 = 2097151 & (load_3(b + 18) >> 3); 3247 // int64_t b8 = 2097151 & load_3(b + 21); 3248 // int64_t b9 = 2097151 & (load_4(b + 23) >> 5); 3249 // int64_t b10 = 2097151 & (load_3(b + 26) >> 2); 3250 // int64_t b11 = (load_4(b + 28) >> 7); 3251 $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); 3252 $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); 3253 $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); 3254 $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); 3255 $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); 3256 $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); 3257 $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); 3258 $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); 3259 $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); 3260 $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); 3261 $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); 3262 $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); 3263 3264 // s0 = a0 * b0; 3265 // s1 = a0 * b1 + a1 * b0; 3266 // s2 = a0 * b2 + a1 * b1 + a2 * b0; 3267 // s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; 3268 // s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; 3269 // s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; 3270 // s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; 3271 // s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + 3272 // a6 * b1 + a7 * b0; 3273 // s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + 3274 // a6 * b2 + a7 * b1 + a8 * b0; 3275 // s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + 3276 // a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; 3277 // s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + 3278 // a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; 3279 // s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + 3280 // a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; 3281 // s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + 3282 // a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; 3283 // s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + 3284 // a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; 3285 // s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + 3286 // a9 * b5 + a10 * b4 + a11 * b3; 3287 // s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + 3288 // a10 * b5 + a11 * b4; 3289 // s16 = 3290 // a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; 3291 // s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; 3292 // s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; 3293 // s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; 3294 // s20 = a9 * b11 + a10 * b10 + a11 * b9; 3295 // s21 = a10 * b11 + a11 * b10; 3296 // s22 = a11 * b11; 3297 // s23 = 0; 3298 $s0 = self::mul($a0, $b0, 22); 3299 $s1 = self::mul($a0, $b1, 22) + self::mul($a1, $b0, 22); 3300 $s2 = self::mul($a0, $b2, 22) + self::mul($a1, $b1, 22) + self::mul($a2, $b0, 22); 3301 $s3 = self::mul($a0, $b3, 22) + self::mul($a1, $b2, 22) + self::mul($a2, $b1, 22) + self::mul($a3, $b0, 22); 3302 $s4 = self::mul($a0, $b4, 22) + self::mul($a1, $b3, 22) + self::mul($a2, $b2, 22) + self::mul($a3, $b1, 22) + 3303 self::mul($a4, $b0, 22); 3304 $s5 = self::mul($a0, $b5, 22) + self::mul($a1, $b4, 22) + self::mul($a2, $b3, 22) + self::mul($a3, $b2, 22) + 3305 self::mul($a4, $b1, 22) + self::mul($a5, $b0, 22); 3306 $s6 = self::mul($a0, $b6, 22) + self::mul($a1, $b5, 22) + self::mul($a2, $b4, 22) + self::mul($a3, $b3, 22) + 3307 self::mul($a4, $b2, 22) + self::mul($a5, $b1, 22) + self::mul($a6, $b0, 22); 3308 $s7 = self::mul($a0, $b7, 22) + self::mul($a1, $b6, 22) + self::mul($a2, $b5, 22) + self::mul($a3, $b4, 22) + 3309 self::mul($a4, $b3, 22) + self::mul($a5, $b2, 22) + self::mul($a6, $b1, 22) + self::mul($a7, $b0, 22); 3310 $s8 = self::mul($a0, $b8, 22) + self::mul($a1, $b7, 22) + self::mul($a2, $b6, 22) + self::mul($a3, $b5, 22) + 3311 self::mul($a4, $b4, 22) + self::mul($a5, $b3, 22) + self::mul($a6, $b2, 22) + self::mul($a7, $b1, 22) + 3312 self::mul($a8, $b0, 22); 3313 $s9 = self::mul($a0, $b9, 22) + self::mul($a1, $b8, 22) + self::mul($a2, $b7, 22) + self::mul($a3, $b6, 22) + 3314 self::mul($a4, $b5, 22) + self::mul($a5, $b4, 22) + self::mul($a6, $b3, 22) + self::mul($a7, $b2, 22) + 3315 self::mul($a8, $b1, 22) + self::mul($a9, $b0, 22); 3316 $s10 = self::mul($a0, $b10, 22) + self::mul($a1, $b9, 22) + self::mul($a2, $b8, 22) + self::mul($a3, $b7, 22) + 3317 self::mul($a4, $b6, 22) + self::mul($a5, $b5, 22) + self::mul($a6, $b4, 22) + self::mul($a7, $b3, 22) + 3318 self::mul($a8, $b2, 22) + self::mul($a9, $b1, 22) + self::mul($a10, $b0, 22); 3319 $s11 = self::mul($a0, $b11, 22) + self::mul($a1, $b10, 22) + self::mul($a2, $b9, 22) + self::mul($a3, $b8, 22) + 3320 self::mul($a4, $b7, 22) + self::mul($a5, $b6, 22) + self::mul($a6, $b5, 22) + self::mul($a7, $b4, 22) + 3321 self::mul($a8, $b3, 22) + self::mul($a9, $b2, 22) + self::mul($a10, $b1, 22) + self::mul($a11, $b0, 22); 3322 $s12 = self::mul($a1, $b11, 22) + self::mul($a2, $b10, 22) + self::mul($a3, $b9, 22) + self::mul($a4, $b8, 22) + 3323 self::mul($a5, $b7, 22) + self::mul($a6, $b6, 22) + self::mul($a7, $b5, 22) + self::mul($a8, $b4, 22) + 3324 self::mul($a9, $b3, 22) + self::mul($a10, $b2, 22) + self::mul($a11, $b1, 22); 3325 $s13 = self::mul($a2, $b11, 22) + self::mul($a3, $b10, 22) + self::mul($a4, $b9, 22) + self::mul($a5, $b8, 22) + 3326 self::mul($a6, $b7, 22) + self::mul($a7, $b6, 22) + self::mul($a8, $b5, 22) + self::mul($a9, $b4, 22) + 3327 self::mul($a10, $b3, 22) + self::mul($a11, $b2, 22); 3328 $s14 = self::mul($a3, $b11, 22) + self::mul($a4, $b10, 22) + self::mul($a5, $b9, 22) + self::mul($a6, $b8, 22) + 3329 self::mul($a7, $b7, 22) + self::mul($a8, $b6, 22) + self::mul($a9, $b5, 22) + self::mul($a10, $b4, 22) + 3330 self::mul($a11, $b3, 22); 3331 $s15 = self::mul($a4, $b11, 22) + self::mul($a5, $b10, 22) + self::mul($a6, $b9, 22) + self::mul($a7, $b8, 22) + 3332 self::mul($a8, $b7, 22) + self::mul($a9, $b6, 22) + self::mul($a10, $b5, 22) + self::mul($a11, $b4, 22); 3333 $s16 = 3334 self::mul($a5, $b11, 22) + self::mul($a6, $b10, 22) + self::mul($a7, $b9, 22) + self::mul($a8, $b8, 22) + 3335 self::mul($a9, $b7, 22) + self::mul($a10, $b6, 22) + self::mul($a11, $b5, 22); 3336 $s17 = self::mul($a6, $b11, 22) + self::mul($a7, $b10, 22) + self::mul($a8, $b9, 22) + self::mul($a9, $b8, 22) + 3337 self::mul($a10, $b7, 22) + self::mul($a11, $b6, 22); 3338 $s18 = self::mul($a7, $b11, 22) + self::mul($a8, $b10, 22) + self::mul($a9, $b9, 22) + self::mul($a10, $b8, 22) 3339 + self::mul($a11, $b7, 22); 3340 $s19 = self::mul($a8, $b11, 22) + self::mul($a9, $b10, 22) + self::mul($a10, $b9, 22) + 3341 self::mul($a11, $b8, 22); 3342 $s20 = self::mul($a9, $b11, 22) + self::mul($a10, $b10, 22) + self::mul($a11, $b9, 22); 3343 $s21 = self::mul($a10, $b11, 22) + self::mul($a11, $b10, 22); 3344 $s22 = self::mul($a11, $b11, 22); 3345 $s23 = 0; 3346 3347 // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; 3348 // s1 += carry0; 3349 // s0 -= carry0 * ((uint64_t) 1L << 21); 3350 $carry0 = ($s0 + (1 << 20)) >> 21; 3351 $s1 += $carry0; 3352 $s0 -= $carry0 << 21; 3353 // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; 3354 // s3 += carry2; 3355 // s2 -= carry2 * ((uint64_t) 1L << 21); 3356 $carry2 = ($s2 + (1 << 20)) >> 21; 3357 $s3 += $carry2; 3358 $s2 -= $carry2 << 21; 3359 // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; 3360 // s5 += carry4; 3361 // s4 -= carry4 * ((uint64_t) 1L << 21); 3362 $carry4 = ($s4 + (1 << 20)) >> 21; 3363 $s5 += $carry4; 3364 $s4 -= $carry4 << 21; 3365 // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; 3366 // s7 += carry6; 3367 // s6 -= carry6 * ((uint64_t) 1L << 21); 3368 $carry6 = ($s6 + (1 << 20)) >> 21; 3369 $s7 += $carry6; 3370 $s6 -= $carry6 << 21; 3371 // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; 3372 // s9 += carry8; 3373 // s8 -= carry8 * ((uint64_t) 1L << 21); 3374 $carry8 = ($s8 + (1 << 20)) >> 21; 3375 $s9 += $carry8; 3376 $s8 -= $carry8 << 21; 3377 // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; 3378 // s11 += carry10; 3379 // s10 -= carry10 * ((uint64_t) 1L << 21); 3380 $carry10 = ($s10 + (1 << 20)) >> 21; 3381 $s11 += $carry10; 3382 $s10 -= $carry10 << 21; 3383 // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; 3384 // s13 += carry12; 3385 // s12 -= carry12 * ((uint64_t) 1L << 21); 3386 $carry12 = ($s12 + (1 << 20)) >> 21; 3387 $s13 += $carry12; 3388 $s12 -= $carry12 << 21; 3389 // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; 3390 // s15 += carry14; 3391 // s14 -= carry14 * ((uint64_t) 1L << 21); 3392 $carry14 = ($s14 + (1 << 20)) >> 21; 3393 $s15 += $carry14; 3394 $s14 -= $carry14 << 21; 3395 // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; 3396 // s17 += carry16; 3397 // s16 -= carry16 * ((uint64_t) 1L << 21); 3398 $carry16 = ($s16 + (1 << 20)) >> 21; 3399 $s17 += $carry16; 3400 $s16 -= $carry16 << 21; 3401 // carry18 = (s18 + (int64_t) (1L << 20)) >> 21; 3402 // s19 += carry18; 3403 // s18 -= carry18 * ((uint64_t) 1L << 21); 3404 $carry18 = ($s18 + (1 << 20)) >> 21; 3405 $s19 += $carry18; 3406 $s18 -= $carry18 << 21; 3407 // carry20 = (s20 + (int64_t) (1L << 20)) >> 21; 3408 // s21 += carry20; 3409 // s20 -= carry20 * ((uint64_t) 1L << 21); 3410 $carry20 = ($s20 + (1 << 20)) >> 21; 3411 $s21 += $carry20; 3412 $s20 -= $carry20 << 21; 3413 // carry22 = (s22 + (int64_t) (1L << 20)) >> 21; 3414 // s23 += carry22; 3415 // s22 -= carry22 * ((uint64_t) 1L << 21); 3416 $carry22 = ($s22 + (1 << 20)) >> 21; 3417 $s23 += $carry22; 3418 $s22 -= $carry22 << 21; 3419 3420 // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; 3421 // s2 += carry1; 3422 // s1 -= carry1 * ((uint64_t) 1L << 21); 3423 $carry1 = ($s1 + (1 << 20)) >> 21; 3424 $s2 += $carry1; 3425 $s1 -= $carry1 << 21; 3426 // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; 3427 // s4 += carry3; 3428 // s3 -= carry3 * ((uint64_t) 1L << 21); 3429 $carry3 = ($s3 + (1 << 20)) >> 21; 3430 $s4 += $carry3; 3431 $s3 -= $carry3 << 21; 3432 // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; 3433 // s6 += carry5; 3434 // s5 -= carry5 * ((uint64_t) 1L << 21); 3435 $carry5 = ($s5 + (1 << 20)) >> 21; 3436 $s6 += $carry5; 3437 $s5 -= $carry5 << 21; 3438 // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; 3439 // s8 += carry7; 3440 // s7 -= carry7 * ((uint64_t) 1L << 21); 3441 $carry7 = ($s7 + (1 << 20)) >> 21; 3442 $s8 += $carry7; 3443 $s7 -= $carry7 << 21; 3444 // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; 3445 // s10 += carry9; 3446 // s9 -= carry9 * ((uint64_t) 1L << 21); 3447 $carry9 = ($s9 + (1 << 20)) >> 21; 3448 $s10 += $carry9; 3449 $s9 -= $carry9 << 21; 3450 // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; 3451 // s12 += carry11; 3452 // s11 -= carry11 * ((uint64_t) 1L << 21); 3453 $carry11 = ($s11 + (1 << 20)) >> 21; 3454 $s12 += $carry11; 3455 $s11 -= $carry11 << 21; 3456 // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; 3457 // s14 += carry13; 3458 // s13 -= carry13 * ((uint64_t) 1L << 21); 3459 $carry13 = ($s13 + (1 << 20)) >> 21; 3460 $s14 += $carry13; 3461 $s13 -= $carry13 << 21; 3462 // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; 3463 // s16 += carry15; 3464 // s15 -= carry15 * ((uint64_t) 1L << 21); 3465 $carry15 = ($s15 + (1 << 20)) >> 21; 3466 $s16 += $carry15; 3467 $s15 -= $carry15 << 21; 3468 // carry17 = (s17 + (int64_t) (1L << 20)) >> 21; 3469 // s18 += carry17; 3470 // s17 -= carry17 * ((uint64_t) 1L << 21); 3471 $carry17 = ($s17 + (1 << 20)) >> 21; 3472 $s18 += $carry17; 3473 $s17 -= $carry17 << 21; 3474 // carry19 = (s19 + (int64_t) (1L << 20)) >> 21; 3475 // s20 += carry19; 3476 // s19 -= carry19 * ((uint64_t) 1L << 21); 3477 $carry19 = ($s19 + (1 << 20)) >> 21; 3478 $s20 += $carry19; 3479 $s19 -= $carry19 << 21; 3480 // carry21 = (s21 + (int64_t) (1L << 20)) >> 21; 3481 // s22 += carry21; 3482 // s21 -= carry21 * ((uint64_t) 1L << 21); 3483 $carry21 = ($s21 + (1 << 20)) >> 21; 3484 $s22 += $carry21; 3485 $s21 -= $carry21 << 21; 3486 3487 // s11 += s23 * 666643; 3488 // s12 += s23 * 470296; 3489 // s13 += s23 * 654183; 3490 // s14 -= s23 * 997805; 3491 // s15 += s23 * 136657; 3492 // s16 -= s23 * 683901; 3493 $s11 += self::mul($s23, 666643, 20); 3494 $s12 += self::mul($s23, 470296, 19); 3495 $s13 += self::mul($s23, 654183, 20); 3496 $s14 -= self::mul($s23, 997805, 20); 3497 $s15 += self::mul($s23, 136657, 18); 3498 $s16 -= self::mul($s23, 683901, 20); 3499 3500 // s10 += s22 * 666643; 3501 // s11 += s22 * 470296; 3502 // s12 += s22 * 654183; 3503 // s13 -= s22 * 997805; 3504 // s14 += s22 * 136657; 3505 // s15 -= s22 * 683901; 3506 $s10 += self::mul($s22, 666643, 20); 3507 $s11 += self::mul($s22, 470296, 19); 3508 $s12 += self::mul($s22, 654183, 20); 3509 $s13 -= self::mul($s22, 997805, 20); 3510 $s14 += self::mul($s22, 136657, 18); 3511 $s15 -= self::mul($s22, 683901, 20); 3512 3513 // s9 += s21 * 666643; 3514 // s10 += s21 * 470296; 3515 // s11 += s21 * 654183; 3516 // s12 -= s21 * 997805; 3517 // s13 += s21 * 136657; 3518 // s14 -= s21 * 683901; 3519 $s9 += self::mul($s21, 666643, 20); 3520 $s10 += self::mul($s21, 470296, 19); 3521 $s11 += self::mul($s21, 654183, 20); 3522 $s12 -= self::mul($s21, 997805, 20); 3523 $s13 += self::mul($s21, 136657, 18); 3524 $s14 -= self::mul($s21, 683901, 20); 3525 3526 // s8 += s20 * 666643; 3527 // s9 += s20 * 470296; 3528 // s10 += s20 * 654183; 3529 // s11 -= s20 * 997805; 3530 // s12 += s20 * 136657; 3531 // s13 -= s20 * 683901; 3532 $s8 += self::mul($s20, 666643, 20); 3533 $s9 += self::mul($s20, 470296, 19); 3534 $s10 += self::mul($s20, 654183, 20); 3535 $s11 -= self::mul($s20, 997805, 20); 3536 $s12 += self::mul($s20, 136657, 18); 3537 $s13 -= self::mul($s20, 683901, 20); 3538 3539 // s7 += s19 * 666643; 3540 // s8 += s19 * 470296; 3541 // s9 += s19 * 654183; 3542 // s10 -= s19 * 997805; 3543 // s11 += s19 * 136657; 3544 // s12 -= s19 * 683901; 3545 $s7 += self::mul($s19, 666643, 20); 3546 $s8 += self::mul($s19, 470296, 19); 3547 $s9 += self::mul($s19, 654183, 20); 3548 $s10 -= self::mul($s19, 997805, 20); 3549 $s11 += self::mul($s19, 136657, 18); 3550 $s12 -= self::mul($s19, 683901, 20); 3551 3552 // s6 += s18 * 666643; 3553 // s7 += s18 * 470296; 3554 // s8 += s18 * 654183; 3555 // s9 -= s18 * 997805; 3556 // s10 += s18 * 136657; 3557 // s11 -= s18 * 683901; 3558 $s6 += self::mul($s18, 666643, 20); 3559 $s7 += self::mul($s18, 470296, 19); 3560 $s8 += self::mul($s18, 654183, 20); 3561 $s9 -= self::mul($s18, 997805, 20); 3562 $s10 += self::mul($s18, 136657, 18); 3563 $s11 -= self::mul($s18, 683901, 20); 3564 3565 // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; 3566 // s7 += carry6; 3567 // s6 -= carry6 * ((uint64_t) 1L << 21); 3568 $carry6 = ($s6 + (1 << 20)) >> 21; 3569 $s7 += $carry6; 3570 $s6 -= $carry6 << 21; 3571 // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; 3572 // s9 += carry8; 3573 // s8 -= carry8 * ((uint64_t) 1L << 21); 3574 $carry8 = ($s8 + (1 << 20)) >> 21; 3575 $s9 += $carry8; 3576 $s8 -= $carry8 << 21; 3577 // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; 3578 // s11 += carry10; 3579 // s10 -= carry10 * ((uint64_t) 1L << 21); 3580 $carry10 = ($s10 + (1 << 20)) >> 21; 3581 $s11 += $carry10; 3582 $s10 -= $carry10 << 21; 3583 // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; 3584 // s13 += carry12; 3585 // s12 -= carry12 * ((uint64_t) 1L << 21); 3586 $carry12 = ($s12 + (1 << 20)) >> 21; 3587 $s13 += $carry12; 3588 $s12 -= $carry12 << 21; 3589 // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; 3590 // s15 += carry14; 3591 // s14 -= carry14 * ((uint64_t) 1L << 21); 3592 $carry14 = ($s14 + (1 << 20)) >> 21; 3593 $s15 += $carry14; 3594 $s14 -= $carry14 << 21; 3595 // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; 3596 // s17 += carry16; 3597 // s16 -= carry16 * ((uint64_t) 1L << 21); 3598 $carry16 = ($s16 + (1 << 20)) >> 21; 3599 $s17 += $carry16; 3600 $s16 -= $carry16 << 21; 3601 3602 // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; 3603 // s8 += carry7; 3604 // s7 -= carry7 * ((uint64_t) 1L << 21); 3605 $carry7 = ($s7 + (1 << 20)) >> 21; 3606 $s8 += $carry7; 3607 $s7 -= $carry7 << 21; 3608 // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; 3609 // s10 += carry9; 3610 // s9 -= carry9 * ((uint64_t) 1L << 21); 3611 $carry9 = ($s9 + (1 << 20)) >> 21; 3612 $s10 += $carry9; 3613 $s9 -= $carry9 << 21; 3614 // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; 3615 // s12 += carry11; 3616 // s11 -= carry11 * ((uint64_t) 1L << 21); 3617 $carry11 = ($s11 + (1 << 20)) >> 21; 3618 $s12 += $carry11; 3619 $s11 -= $carry11 << 21; 3620 // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; 3621 // s14 += carry13; 3622 // s13 -= carry13 * ((uint64_t) 1L << 21); 3623 $carry13 = ($s13 + (1 << 20)) >> 21; 3624 $s14 += $carry13; 3625 $s13 -= $carry13 << 21; 3626 // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; 3627 // s16 += carry15; 3628 // s15 -= carry15 * ((uint64_t) 1L << 21); 3629 $carry15 = ($s15 + (1 << 20)) >> 21; 3630 $s16 += $carry15; 3631 $s15 -= $carry15 << 21; 3632 3633 // s5 += s17 * 666643; 3634 // s6 += s17 * 470296; 3635 // s7 += s17 * 654183; 3636 // s8 -= s17 * 997805; 3637 // s9 += s17 * 136657; 3638 // s10 -= s17 * 683901; 3639 $s5 += self::mul($s17, 666643, 20); 3640 $s6 += self::mul($s17, 470296, 19); 3641 $s7 += self::mul($s17, 654183, 20); 3642 $s8 -= self::mul($s17, 997805, 20); 3643 $s9 += self::mul($s17, 136657, 18); 3644 $s10 -= self::mul($s17, 683901, 20); 3645 3646 // s4 += s16 * 666643; 3647 // s5 += s16 * 470296; 3648 // s6 += s16 * 654183; 3649 // s7 -= s16 * 997805; 3650 // s8 += s16 * 136657; 3651 // s9 -= s16 * 683901; 3652 $s4 += self::mul($s16, 666643, 20); 3653 $s5 += self::mul($s16, 470296, 19); 3654 $s6 += self::mul($s16, 654183, 20); 3655 $s7 -= self::mul($s16, 997805, 20); 3656 $s8 += self::mul($s16, 136657, 18); 3657 $s9 -= self::mul($s16, 683901, 20); 3658 3659 // s3 += s15 * 666643; 3660 // s4 += s15 * 470296; 3661 // s5 += s15 * 654183; 3662 // s6 -= s15 * 997805; 3663 // s7 += s15 * 136657; 3664 // s8 -= s15 * 683901; 3665 $s3 += self::mul($s15, 666643, 20); 3666 $s4 += self::mul($s15, 470296, 19); 3667 $s5 += self::mul($s15, 654183, 20); 3668 $s6 -= self::mul($s15, 997805, 20); 3669 $s7 += self::mul($s15, 136657, 18); 3670 $s8 -= self::mul($s15, 683901, 20); 3671 3672 // s2 += s14 * 666643; 3673 // s3 += s14 * 470296; 3674 // s4 += s14 * 654183; 3675 // s5 -= s14 * 997805; 3676 // s6 += s14 * 136657; 3677 // s7 -= s14 * 683901; 3678 $s2 += self::mul($s14, 666643, 20); 3679 $s3 += self::mul($s14, 470296, 19); 3680 $s4 += self::mul($s14, 654183, 20); 3681 $s5 -= self::mul($s14, 997805, 20); 3682 $s6 += self::mul($s14, 136657, 18); 3683 $s7 -= self::mul($s14, 683901, 20); 3684 3685 // s1 += s13 * 666643; 3686 // s2 += s13 * 470296; 3687 // s3 += s13 * 654183; 3688 // s4 -= s13 * 997805; 3689 // s5 += s13 * 136657; 3690 // s6 -= s13 * 683901; 3691 $s1 += self::mul($s13, 666643, 20); 3692 $s2 += self::mul($s13, 470296, 19); 3693 $s3 += self::mul($s13, 654183, 20); 3694 $s4 -= self::mul($s13, 997805, 20); 3695 $s5 += self::mul($s13, 136657, 18); 3696 $s6 -= self::mul($s13, 683901, 20); 3697 3698 // s0 += s12 * 666643; 3699 // s1 += s12 * 470296; 3700 // s2 += s12 * 654183; 3701 // s3 -= s12 * 997805; 3702 // s4 += s12 * 136657; 3703 // s5 -= s12 * 683901; 3704 // s12 = 0; 3705 $s0 += self::mul($s12, 666643, 20); 3706 $s1 += self::mul($s12, 470296, 19); 3707 $s2 += self::mul($s12, 654183, 20); 3708 $s3 -= self::mul($s12, 997805, 20); 3709 $s4 += self::mul($s12, 136657, 18); 3710 $s5 -= self::mul($s12, 683901, 20); 3711 $s12 = 0; 3712 3713 // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; 3714 // s1 += carry0; 3715 // s0 -= carry0 * ((uint64_t) 1L << 21); 3716 $carry0 = ($s0 + (1 << 20)) >> 21; 3717 $s1 += $carry0; 3718 $s0 -= $carry0 << 21; 3719 // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; 3720 // s3 += carry2; 3721 // s2 -= carry2 * ((uint64_t) 1L << 21); 3722 $carry2 = ($s2 + (1 << 20)) >> 21; 3723 $s3 += $carry2; 3724 $s2 -= $carry2 << 21; 3725 // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; 3726 // s5 += carry4; 3727 // s4 -= carry4 * ((uint64_t) 1L << 21); 3728 $carry4 = ($s4 + (1 << 20)) >> 21; 3729 $s5 += $carry4; 3730 $s4 -= $carry4 << 21; 3731 // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; 3732 // s7 += carry6; 3733 // s6 -= carry6 * ((uint64_t) 1L << 21); 3734 $carry6 = ($s6 + (1 << 20)) >> 21; 3735 $s7 += $carry6; 3736 $s6 -= $carry6 << 21; 3737 // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; 3738 // s9 += carry8; 3739 // s8 -= carry8 * ((uint64_t) 1L << 21); 3740 $carry8 = ($s8 + (1 << 20)) >> 21; 3741 $s9 += $carry8; 3742 $s8 -= $carry8 << 21; 3743 // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; 3744 // s11 += carry10; 3745 // s10 -= carry10 * ((uint64_t) 1L << 21); 3746 $carry10 = ($s10 + (1 << 20)) >> 21; 3747 $s11 += $carry10; 3748 $s10 -= $carry10 << 21; 3749 3750 // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; 3751 // s2 += carry1; 3752 // s1 -= carry1 * ((uint64_t) 1L << 21); 3753 $carry1 = ($s1 + (1 << 20)) >> 21; 3754 $s2 += $carry1; 3755 $s1 -= $carry1 << 21; 3756 // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; 3757 // s4 += carry3; 3758 // s3 -= carry3 * ((uint64_t) 1L << 21); 3759 $carry3 = ($s3 + (1 << 20)) >> 21; 3760 $s4 += $carry3; 3761 $s3 -= $carry3 << 21; 3762 // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; 3763 // s6 += carry5; 3764 // s5 -= carry5 * ((uint64_t) 1L << 21); 3765 $carry5 = ($s5 + (1 << 20)) >> 21; 3766 $s6 += $carry5; 3767 $s5 -= $carry5 << 21; 3768 // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; 3769 // s8 += carry7; 3770 // s7 -= carry7 * ((uint64_t) 1L << 21); 3771 $carry7 = ($s7 + (1 << 20)) >> 21; 3772 $s8 += $carry7; 3773 $s7 -= $carry7 << 21; 3774 // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; 3775 // s10 += carry9; 3776 // s9 -= carry9 * ((uint64_t) 1L << 21); 3777 $carry9 = ($s9 + (1 << 20)) >> 21; 3778 $s10 += $carry9; 3779 $s9 -= $carry9 << 21; 3780 // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; 3781 // s12 += carry11; 3782 // s11 -= carry11 * ((uint64_t) 1L << 21); 3783 $carry11 = ($s11 + (1 << 20)) >> 21; 3784 $s12 += $carry11; 3785 $s11 -= $carry11 << 21; 3786 3787 // s0 += s12 * 666643; 3788 // s1 += s12 * 470296; 3789 // s2 += s12 * 654183; 3790 // s3 -= s12 * 997805; 3791 // s4 += s12 * 136657; 3792 // s5 -= s12 * 683901; 3793 // s12 = 0; 3794 $s0 += self::mul($s12, 666643, 20); 3795 $s1 += self::mul($s12, 470296, 19); 3796 $s2 += self::mul($s12, 654183, 20); 3797 $s3 -= self::mul($s12, 997805, 20); 3798 $s4 += self::mul($s12, 136657, 18); 3799 $s5 -= self::mul($s12, 683901, 20); 3800 $s12 = 0; 3801 3802 // carry0 = s0 >> 21; 3803 // s1 += carry0; 3804 // s0 -= carry0 * ((uint64_t) 1L << 21); 3805 $carry0 = $s0 >> 21; 3806 $s1 += $carry0; 3807 $s0 -= $carry0 << 21; 3808 // carry1 = s1 >> 21; 3809 // s2 += carry1; 3810 // s1 -= carry1 * ((uint64_t) 1L << 21); 3811 $carry1 = $s1 >> 21; 3812 $s2 += $carry1; 3813 $s1 -= $carry1 << 21; 3814 // carry2 = s2 >> 21; 3815 // s3 += carry2; 3816 // s2 -= carry2 * ((uint64_t) 1L << 21); 3817 $carry2 = $s2 >> 21; 3818 $s3 += $carry2; 3819 $s2 -= $carry2 << 21; 3820 // carry3 = s3 >> 21; 3821 // s4 += carry3; 3822 // s3 -= carry3 * ((uint64_t) 1L << 21); 3823 $carry3 = $s3 >> 21; 3824 $s4 += $carry3; 3825 $s3 -= $carry3 << 21; 3826 // carry4 = s4 >> 21; 3827 // s5 += carry4; 3828 // s4 -= carry4 * ((uint64_t) 1L << 21); 3829 $carry4 = $s4 >> 21; 3830 $s5 += $carry4; 3831 $s4 -= $carry4 << 21; 3832 // carry5 = s5 >> 21; 3833 // s6 += carry5; 3834 // s5 -= carry5 * ((uint64_t) 1L << 21); 3835 $carry5 = $s5 >> 21; 3836 $s6 += $carry5; 3837 $s5 -= $carry5 << 21; 3838 // carry6 = s6 >> 21; 3839 // s7 += carry6; 3840 // s6 -= carry6 * ((uint64_t) 1L << 21); 3841 $carry6 = $s6 >> 21; 3842 $s7 += $carry6; 3843 $s6 -= $carry6 << 21; 3844 // carry7 = s7 >> 21; 3845 // s8 += carry7; 3846 // s7 -= carry7 * ((uint64_t) 1L << 21); 3847 $carry7 = $s7 >> 21; 3848 $s8 += $carry7; 3849 $s7 -= $carry7 << 21; 3850 // carry8 = s8 >> 21; 3851 // s9 += carry8; 3852 // s8 -= carry8 * ((uint64_t) 1L << 21); 3853 $carry8 = $s8 >> 21; 3854 $s9 += $carry8; 3855 $s8 -= $carry8 << 21; 3856 // carry9 = s9 >> 21; 3857 // s10 += carry9; 3858 // s9 -= carry9 * ((uint64_t) 1L << 21); 3859 $carry9 = $s9 >> 21; 3860 $s10 += $carry9; 3861 $s9 -= $carry9 << 21; 3862 // carry10 = s10 >> 21; 3863 // s11 += carry10; 3864 // s10 -= carry10 * ((uint64_t) 1L << 21); 3865 $carry10 = $s10 >> 21; 3866 $s11 += $carry10; 3867 $s10 -= $carry10 << 21; 3868 // carry11 = s11 >> 21; 3869 // s12 += carry11; 3870 // s11 -= carry11 * ((uint64_t) 1L << 21); 3871 $carry11 = $s11 >> 21; 3872 $s12 += $carry11; 3873 $s11 -= $carry11 << 21; 3874 3875 // s0 += s12 * 666643; 3876 // s1 += s12 * 470296; 3877 // s2 += s12 * 654183; 3878 // s3 -= s12 * 997805; 3879 // s4 += s12 * 136657; 3880 // s5 -= s12 * 683901; 3881 $s0 += self::mul($s12, 666643, 20); 3882 $s1 += self::mul($s12, 470296, 19); 3883 $s2 += self::mul($s12, 654183, 20); 3884 $s3 -= self::mul($s12, 997805, 20); 3885 $s4 += self::mul($s12, 136657, 18); 3886 $s5 -= self::mul($s12, 683901, 20); 3887 3888 // carry0 = s0 >> 21; 3889 // s1 += carry0; 3890 // s0 -= carry0 * ((uint64_t) 1L << 21); 3891 $carry0 = $s0 >> 21; 3892 $s1 += $carry0; 3893 $s0 -= $carry0 << 21; 3894 // carry1 = s1 >> 21; 3895 // s2 += carry1; 3896 // s1 -= carry1 * ((uint64_t) 1L << 21); 3897 $carry1 = $s1 >> 21; 3898 $s2 += $carry1; 3899 $s1 -= $carry1 << 21; 3900 // carry2 = s2 >> 21; 3901 // s3 += carry2; 3902 // s2 -= carry2 * ((uint64_t) 1L << 21); 3903 $carry2 = $s2 >> 21; 3904 $s3 += $carry2; 3905 $s2 -= $carry2 << 21; 3906 // carry3 = s3 >> 21; 3907 // s4 += carry3; 3908 // s3 -= carry3 * ((uint64_t) 1L << 21); 3909 $carry3 = $s3 >> 21; 3910 $s4 += $carry3; 3911 $s3 -= $carry3 << 21; 3912 // carry4 = s4 >> 21; 3913 // s5 += carry4; 3914 // s4 -= carry4 * ((uint64_t) 1L << 21); 3915 $carry4 = $s4 >> 21; 3916 $s5 += $carry4; 3917 $s4 -= $carry4 << 21; 3918 // carry5 = s5 >> 21; 3919 // s6 += carry5; 3920 // s5 -= carry5 * ((uint64_t) 1L << 21); 3921 $carry5 = $s5 >> 21; 3922 $s6 += $carry5; 3923 $s5 -= $carry5 << 21; 3924 // carry6 = s6 >> 21; 3925 // s7 += carry6; 3926 // s6 -= carry6 * ((uint64_t) 1L << 21); 3927 $carry6 = $s6 >> 21; 3928 $s7 += $carry6; 3929 $s6 -= $carry6 << 21; 3930 // carry7 = s7 >> 21; 3931 // s8 += carry7; 3932 // s7 -= carry7 * ((uint64_t) 1L << 21); 3933 $carry7 = $s7 >> 21; 3934 $s8 += $carry7; 3935 $s7 -= $carry7 << 21; 3936 // carry8 = s8 >> 21; 3937 // s9 += carry8; 3938 // s8 -= carry8 * ((uint64_t) 1L << 21); 3939 $carry8 = $s8 >> 21; 3940 $s9 += $carry8; 3941 $s8 -= $carry8 << 21; 3942 // carry9 = s9 >> 21; 3943 // s10 += carry9; 3944 // s9 -= carry9 * ((uint64_t) 1L << 21); 3945 $carry9 = $s9 >> 21; 3946 $s10 += $carry9; 3947 $s9 -= $carry9 << 21; 3948 // carry10 = s10 >> 21; 3949 // s11 += carry10; 3950 // s10 -= carry10 * ((uint64_t) 1L << 21); 3951 $carry10 = $s10 >> 21; 3952 $s11 += $carry10; 3953 $s10 -= $carry10 << 21; 3954 3955 $s = array_fill(0, 32, 0); 3956 // s[0] = s0 >> 0; 3957 $s[0] = $s0 >> 0; 3958 // s[1] = s0 >> 8; 3959 $s[1] = $s0 >> 8; 3960 // s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5)); 3961 $s[2] = ($s0 >> 16) | ($s1 << 5); 3962 // s[3] = s1 >> 3; 3963 $s[3] = $s1 >> 3; 3964 // s[4] = s1 >> 11; 3965 $s[4] = $s1 >> 11; 3966 // s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2)); 3967 $s[5] = ($s1 >> 19) | ($s2 << 2); 3968 // s[6] = s2 >> 6; 3969 $s[6] = $s2 >> 6; 3970 // s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7)); 3971 $s[7] = ($s2 >> 14) | ($s3 << 7); 3972 // s[8] = s3 >> 1; 3973 $s[8] = $s3 >> 1; 3974 // s[9] = s3 >> 9; 3975 $s[9] = $s3 >> 9; 3976 // s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4)); 3977 $s[10] = ($s3 >> 17) | ($s4 << 4); 3978 // s[11] = s4 >> 4; 3979 $s[11] = $s4 >> 4; 3980 // s[12] = s4 >> 12; 3981 $s[12] = $s4 >> 12; 3982 // s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1)); 3983 $s[13] = ($s4 >> 20) | ($s5 << 1); 3984 // s[14] = s5 >> 7; 3985 $s[14] = $s5 >> 7; 3986 // s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6)); 3987 $s[15] = ($s5 >> 15) | ($s6 << 6); 3988 // s[16] = s6 >> 2; 3989 $s[16] = $s6 >> 2; 3990 // s[17] = s6 >> 10; 3991 $s[17] = $s6 >> 10; 3992 // s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3)); 3993 $s[18] = ($s6 >> 18) | ($s7 << 3); 3994 // s[19] = s7 >> 5; 3995 $s[19] = $s7 >> 5; 3996 // s[20] = s7 >> 13; 3997 $s[20] = $s7 >> 13; 3998 // s[21] = s8 >> 0; 3999 $s[21] = $s8 >> 0; 4000 // s[22] = s8 >> 8; 4001 $s[22] = $s8 >> 8; 4002 // s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5)); 4003 $s[23] = ($s8 >> 16) | ($s9 << 5); 4004 // s[24] = s9 >> 3; 4005 $s[24] = $s9 >> 3; 4006 // s[25] = s9 >> 11; 4007 $s[25] = $s9 >> 11; 4008 // s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2)); 4009 $s[26] = ($s9 >> 19) | ($s10 << 2); 4010 // s[27] = s10 >> 6; 4011 $s[27] = $s10 >> 6; 4012 // s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7)); 4013 $s[28] = ($s10 >> 14) | ($s11 << 7); 4014 // s[29] = s11 >> 1; 4015 $s[29] = $s11 >> 1; 4016 // s[30] = s11 >> 9; 4017 $s[30] = $s11 >> 9; 4018 // s[31] = s11 >> 17; 4019 $s[31] = $s11 >> 17; 4020 return self::intArrayToString($s); 4021 } 4022 4023 /** 4024 * @param string $s 4025 * @return string 4026 */ 4027 public static function sc25519_sq($s) 4028 { 4029 return self::sc25519_mul($s, $s); 4030 } 4031 4032 /** 4033 * @param string $s 4034 * @param int $n 4035 * @param string $a 4036 * @return string 4037 */ 4038 public static function sc25519_sqmul($s, $n, $a) 4039 { 4040 for ($i = 0; $i < $n; ++$i) { 4041 $s = self::sc25519_sq($s); 4042 } 4043 return self::sc25519_mul($s, $a); 4044 } 4045 4046 /** 4047 * @param string $s 4048 * @return string 4049 */ 4050 public static function sc25519_invert($s) 4051 { 4052 $_10 = self::sc25519_sq($s); 4053 $_11 = self::sc25519_mul($s, $_10); 4054 $_100 = self::sc25519_mul($s, $_11); 4055 $_1000 = self::sc25519_sq($_100); 4056 $_1010 = self::sc25519_mul($_10, $_1000); 4057 $_1011 = self::sc25519_mul($s, $_1010); 4058 $_10000 = self::sc25519_sq($_1000); 4059 $_10110 = self::sc25519_sq($_1011); 4060 $_100000 = self::sc25519_mul($_1010, $_10110); 4061 $_100110 = self::sc25519_mul($_10000, $_10110); 4062 $_1000000 = self::sc25519_sq($_100000); 4063 $_1010000 = self::sc25519_mul($_10000, $_1000000); 4064 $_1010011 = self::sc25519_mul($_11, $_1010000); 4065 $_1100011 = self::sc25519_mul($_10000, $_1010011); 4066 $_1100111 = self::sc25519_mul($_100, $_1100011); 4067 $_1101011 = self::sc25519_mul($_100, $_1100111); 4068 $_10010011 = self::sc25519_mul($_1000000, $_1010011); 4069 $_10010111 = self::sc25519_mul($_100, $_10010011); 4070 $_10111101 = self::sc25519_mul($_100110, $_10010111); 4071 $_11010011 = self::sc25519_mul($_10110, $_10111101); 4072 $_11100111 = self::sc25519_mul($_1010000, $_10010111); 4073 $_11101011 = self::sc25519_mul($_100, $_11100111); 4074 $_11110101 = self::sc25519_mul($_1010, $_11101011); 4075 4076 $recip = self::sc25519_mul($_1011, $_11110101); 4077 $recip = self::sc25519_sqmul($recip, 126, $_1010011); 4078 $recip = self::sc25519_sqmul($recip, 9, $_10); 4079 $recip = self::sc25519_mul($recip, $_11110101); 4080 $recip = self::sc25519_sqmul($recip, 7, $_1100111); 4081 $recip = self::sc25519_sqmul($recip, 9, $_11110101); 4082 $recip = self::sc25519_sqmul($recip, 11, $_10111101); 4083 $recip = self::sc25519_sqmul($recip, 8, $_11100111); 4084 $recip = self::sc25519_sqmul($recip, 9, $_1101011); 4085 $recip = self::sc25519_sqmul($recip, 6, $_1011); 4086 $recip = self::sc25519_sqmul($recip, 14, $_10010011); 4087 $recip = self::sc25519_sqmul($recip, 10, $_1100011); 4088 $recip = self::sc25519_sqmul($recip, 9, $_10010111); 4089 $recip = self::sc25519_sqmul($recip, 10, $_11110101); 4090 $recip = self::sc25519_sqmul($recip, 8, $_11010011); 4091 return self::sc25519_sqmul($recip, 8, $_11101011); 4092 } 4093 4094 /** 4095 * @param string $s 4096 * @return string 4097 */ 4098 public static function clamp($s) 4099 { 4100 $s_ = self::stringToIntArray($s); 4101 $s_[0] &= 248; 4102 $s_[31] |= 64; 4103 $s_[31] &= 128; 4104 return self::intArrayToString($s_); 4105 } 4106 }