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