1 /** 2 * Number Theory Functions 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.math.numbertheory.numthry; 12 13 import botan.constants; 14 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO): 15 16 public import botan.math.bigint.bigint; 17 public import botan.math.numbertheory.pow_mod; 18 public import botan.math.numbertheory.primes; 19 public import botan.utils.types; 20 import botan.rng.rng; 21 import botan.hash.hash; 22 import botan.utils.parsing; 23 import std.algorithm; 24 import botan.math.numbertheory.reducer; 25 import botan.utils.bit_ops; 26 import botan.math.mp.mp_core; 27 import botan.utils.rounding; 28 import botan.algo_factory.algo_factory : AlgorithmFactory; 29 import botan.constants; 30 import std.conv : to; 31 32 /** 33 * Fused multiply-add 34 * Params: 35 * a = an integer 36 * b = an integer 37 * c = an integer 38 * Returns: (a*b)+c 39 */ 40 /* 41 * Multiply-Add Operation 42 */ 43 BigInt mulAdd()(auto const ref BigInt a, auto const ref BigInt b, auto const ref BigInt c) 44 { 45 if (c.isNegative() || c.isZero()) 46 throw new InvalidArgument("mulAdd: Third argument must be > 0"); 47 48 BigInt.Sign sign = BigInt.Positive; 49 if (a.sign() != b.sign()) 50 sign = BigInt.Negative; 51 52 const size_t a_sw = a.sigWords(); 53 const size_t b_sw = b.sigWords(); 54 const size_t c_sw = c.sigWords(); 55 56 BigInt r = BigInt(sign, std.algorithm.max(a.length + b.length, c_sw) + 1); 57 SecureVector!word workspace = SecureVector!word(r.length); 58 59 bigint_mul(r.mutablePtr(), r.length, workspace.ptr, a.ptr, a.length, a_sw, b.ptr, b.length, b_sw); 60 61 const size_t r_size = std.algorithm.max(r.sigWords(), c_sw); 62 bigint_add2(r.mutablePtr(), r_size, c.ptr, c_sw); 63 return r; 64 } 65 66 67 /** 68 * Fused subtract-multiply 69 * Params: 70 * a = an integer 71 * b = an integer 72 * c = an integer 73 * Returns: (a-b)*c 74 */ 75 BigInt subMul()(auto const ref BigInt a, auto const ref BigInt b, auto const ref BigInt c) 76 { 77 if (a.isNegative() || b.isNegative()) 78 throw new InvalidArgument("subMul: First two arguments must be >= 0"); 79 80 BigInt r = a.dup; 81 r -= b; 82 r *= c; 83 return r.move(); 84 } 85 86 /** 87 * Return the absolute value 88 * Params: 89 * n = an integer 90 * Returns: absolute value of n 91 */ 92 BigInt abs()(auto const ref BigInt n) { return n.abs(); } 93 94 /** 95 * Compute the greatest common divisor 96 * Params: 97 * a = positive integer x 98 * b = positive integer y 99 * Returns: gcd(x,y) 100 */ 101 BigInt gcd()(auto const ref BigInt a, auto const ref BigInt b) 102 { 103 if (a.isZero() || b.isZero()) return BigInt(0); 104 if (a == 1 || b == 1) return BigInt(1); 105 106 BigInt x = a.dup, y = b.dup; 107 x.setSign(BigInt.Positive); 108 y.setSign(BigInt.Positive); 109 size_t shift = std.algorithm.min(lowZeroBits(x), lowZeroBits(y)); 110 111 x >>= shift; 112 y >>= shift; 113 114 while (x.isNonzero()) 115 { 116 x >>= lowZeroBits(x); 117 y >>= lowZeroBits(y); 118 if (x >= y) { x -= y; x >>= 1; } 119 else { y -= x; y >>= 1; } 120 } 121 122 return (y << shift); 123 } 124 125 /** 126 * Least common multiple 127 * Params: 128 * a = a positive integer x 129 * b = a positive integer y 130 * Returns: z, smallest integer such that z % x == 0 and z % y == 0 131 */ 132 BigInt lcm()(auto const ref BigInt a, auto const ref BigInt b) 133 { 134 auto a_b = (a * b); 135 auto gcd_a_b = gcd(a, b); 136 return a_b/gcd_a_b; 137 } 138 139 140 /** 141 * Params: 142 * x = an integer 143 * Returns: (x*x) 144 */ 145 BigInt square()(auto const ref BigInt x) 146 { 147 const size_t x_sw = x.sigWords(); 148 149 BigInt z = BigInt(BigInt.Positive, roundUp!size_t(2*x_sw, 16)); 150 SecureVector!word workspace = SecureVector!word(z.length); 151 152 bigint_sqr(z.mutablePtr(), z.length, workspace.ptr, x.ptr, x.length, x_sw); 153 return z; 154 } 155 156 /** 157 * Modular inversion 158 * Params: 159 * n = a positive integer x 160 * mod = a positive integer modulus 161 * Returns: y st (x*y) % modulus == 1 162 */ 163 BigInt inverseMod()(auto const ref BigInt n, auto const ref BigInt mod) 164 { 165 if (mod.isZero()) 166 throw new BigInt.DivideByZero(); 167 if (mod.isNegative() || n.isNegative()) 168 throw new InvalidArgument("inverseMod: arguments must be non-negative"); 169 170 if (n.isZero() || (n.isEven() && mod.isEven())) 171 return BigInt(0); // fast fail checks 172 173 if (mod.isOdd()) 174 return inverseModOddModulus(n, mod); 175 176 BigInt u = mod.dup, v = n.dup; 177 BigInt A = BigInt(1); 178 BigInt B = BigInt(0); 179 BigInt C = BigInt(0); 180 BigInt D = BigInt(1); 181 182 while (u.isNonzero()) 183 { 184 const size_t u_zero_bits = lowZeroBits(u); 185 u >>= u_zero_bits; 186 foreach (size_t i; 0 .. u_zero_bits) 187 { 188 if (A.isOdd() || B.isOdd()) 189 { A += n; B -= mod; } 190 A >>= 1; B >>= 1; 191 } 192 193 const size_t v_zero_bits = lowZeroBits(v); 194 v >>= v_zero_bits; 195 foreach (size_t i; 0 .. v_zero_bits) 196 { 197 if (C.isOdd() || D.isOdd()) 198 { C += n; D -= mod; } 199 C >>= 1; D >>= 1; 200 } 201 202 if (u >= v) { u -= v; A -= C; B -= D; } 203 else { v -= u; C -= A; D -= B; } 204 } 205 206 if (v != 1) 207 return BigInt(0); // no modular inverse 208 209 while (D.isNegative()) D += mod; 210 while (D >= mod) D -= mod; 211 212 return D.move(); 213 } 214 215 216 /** 217 * Compute the Jacobi symbol. If n is prime, this is equivalent 218 * to the Legendre symbol. 219 * @see http://mathworld.wolfram.com/JacobiSymbol.html 220 * 221 * Params: 222 * a = is a non-negative integer 223 * n = is an odd integer > 1 224 * Returns: (n / m) 225 */ 226 int jacobi()(auto const ref BigInt a, auto const ref BigInt n) 227 { 228 if (a.isNegative()) 229 throw new InvalidArgument("jacobi: first argument must be non-negative"); 230 if (n.isEven() || n < 2) 231 throw new InvalidArgument("jacobi: second argument must be odd and > 1"); 232 233 BigInt x = a.dup, y = n.dup; 234 int J = 1; 235 236 while (y > 1) 237 { 238 x %= y; 239 if (x > y / 2) 240 { 241 x = y - x; 242 if (y % 4 == 3) 243 J = -J; 244 } 245 if (x.isZero()) 246 return 0; 247 248 size_t shifts = lowZeroBits(x); 249 x >>= shifts; 250 if (shifts % 2) 251 { 252 word y_mod_8 = y % 8; 253 if (y_mod_8 == 3 || y_mod_8 == 5) 254 J = -J; 255 } 256 257 if (x % 4 == 3 && y % 4 == 3) 258 J = -J; 259 std.algorithm.swap(x, y); 260 } 261 return J; 262 } 263 264 /** 265 * Modular exponentation 266 * Params: 267 * base = an integer base b 268 * exp = a positive exponent x 269 * mod = a positive modulus m 270 * Returns: (b^x) % m 271 */ 272 BigInt powerMod()(auto const ref BigInt base, auto const ref BigInt exp, auto const ref BigInt mod) 273 { 274 auto pow_mod = scoped!PowerMod(mod); 275 276 /* 277 * Calling setBase before setExponent means we end up using a 278 * minimal window. This makes sense given that here we know that any 279 * precomputation is wasted. 280 */ 281 pow_mod.setBase(base); 282 pow_mod.setExponent(exp); 283 return pow_mod.execute(); 284 } 285 286 287 /** 288 * Compute the square root of x modulo a prime using the 289 * Shanks-Tonnelli algorithm 290 * 291 * Params: 292 * a = the input x 293 * p = the prime p 294 * Returns: y such that (y*y)%p == x, or -1 if no such integer 295 */ 296 297 /* 298 * Shanks-Tonnelli algorithm 299 */ 300 BigInt ressol()(auto const ref BigInt a, auto const ref BigInt p) 301 { 302 303 if (a == 0) 304 return BigInt(0); 305 else if (a < 0) 306 throw new InvalidArgument("ressol(): a to solve for must be positive"); 307 308 if (p == 2) 309 return a.dup; 310 else if (p <= 1) 311 throw new InvalidArgument("ressol(): prime must be > 1"); 312 else if(p.isEven()) 313 throw new InvalidArgument("ressol(): invalid prime"); 314 if (jacobi(a, p) != 1) { // not a quadratic residue 315 auto bi = -BigInt(1); 316 return bi.move(); 317 } 318 319 if (p % 4 == 3) 320 return powerMod(a, ((p+1) >> 2), p); 321 322 size_t s = lowZeroBits(p - 1); 323 BigInt q = p >> s; 324 325 q -= 1; 326 q >>= 1; 327 328 ModularReducer mod_p = ModularReducer(p); 329 330 BigInt r = powerMod(a, q, p); 331 BigInt n = mod_p.multiply(a, mod_p.square(r)); 332 r = mod_p.multiply(r, a); 333 334 if (n == 1) 335 return r.move(); 336 337 // find random non quadratic residue z 338 BigInt z = 2; 339 while (jacobi(z, p) == 1) // while z quadratic residue 340 ++z; 341 342 BigInt c = powerMod(z, (q << 1) + 1, p); 343 344 while (n > 1) 345 { 346 q = n.dup(); 347 348 size_t i = 0; 349 while (q != 1) 350 { 351 q = mod_p.square(q); 352 ++i; 353 if (i >= s) { 354 auto bi = -BigInt(1); 355 return bi.move(); 356 } 357 } 358 359 c = powerMod(c, BigInt.powerOf2(s-i-1), p); 360 r = mod_p.multiply(r, c); 361 c = mod_p.square(c); 362 n = mod_p.multiply(n, c); 363 s = i; 364 } 365 366 return r.move(); 367 } 368 369 /* 370 * Compute -input^-1 mod 2^MP_WORD_BITS. Returns zero if input 371 * is even. If input is odd, input and 2^n are relatively prime 372 * and an inverse exists. 373 */ 374 word montyInverse(word input) 375 { 376 word b = input; 377 word x2 = 1, x1 = 0, y2 = 0, y1 = 1; 378 379 // First iteration, a = n+1 380 word q = bigint_divop(1, 0, b); 381 word r = (MP_WORD_MAX - q*b) + 1; 382 word x = x2 - q*x1; 383 word y = y2 - q*y1; 384 385 word a = b; 386 b = r; 387 x2 = x1; 388 x1 = x; 389 y2 = y1; 390 y1 = y; 391 392 while (b > 0) 393 { 394 q = a / b; 395 r = a - q*b; 396 x = x2 - q*x1; 397 y = y2 - q*y1; 398 399 a = b; 400 b = r; 401 x2 = x1; 402 x1 = x; 403 y2 = y1; 404 y1 = y; 405 } 406 407 // Now invert in addition space 408 y2 = (MP_WORD_MAX - y2) + 1; 409 410 return y2; 411 } 412 413 /** 414 * Params: 415 * n = a positive integer x 416 * Returns: count of the zero bits in x, or, equivalently, the largest 417 * value of n such that 2^n divides x evenly. Returns zero if 418 * n is less than or equal to zero. 419 */ 420 size_t lowZeroBits()(auto const ref BigInt n) 421 { 422 size_t low_zero = 0; 423 424 if (n.isPositive() && n.isNonzero()) 425 { 426 for (size_t i = 0; i != n.length; ++i) 427 { 428 const word x = n.wordAt(i); 429 430 if (x) 431 { 432 low_zero += ctz(x); 433 break; 434 } 435 else 436 low_zero += BOTAN_MP_WORD_BITS; 437 } 438 } 439 440 return low_zero; 441 } 442 443 /** 444 * Check for primality using Miller-Rabin 445 * Params: 446 * n = a positive integer to test for primality 447 * rng = a random number generator 448 * prob = chance of false positive is bounded by 1/2**prob 449 * is_random = true if n was randomly chosen by us 450 * Returns: true if all primality tests passed, otherwise false 451 */ 452 bool isPrime()(auto const ref BigInt n, RandomNumberGenerator rng, size_t prob = 56, bool is_random = false) 453 { 454 import std.range : assumeSorted, SortedRange, empty; 455 if (n == 2) 456 return true; 457 if (n <= 1 || n.isEven()) 458 return false; 459 460 // Fast path testing for small numbers (<= 65521) 461 if (n <= PRIMES[PRIME_TABLE_SIZE-1]) 462 { 463 const ushort num = cast(ushort) n.wordAt(0); 464 auto r = assumeSorted(PRIMES[0..$]); 465 return !r.equalRange(num).empty; 466 } 467 468 const size_t test_iterations = mrTestIterations(n.bits(), prob, is_random); 469 const BigInt n_minus_1 = n - 1; 470 const size_t s = lowZeroBits(n_minus_1); 471 FixedExponentPowerModImpl pow_mod = ThreadMem.alloc!FixedExponentPowerModImpl(n_minus_1 >> s, n); 472 scope(exit) ThreadMem.free(pow_mod); 473 ModularReducer reducer = ModularReducer(n); 474 475 foreach (size_t i; 0 .. test_iterations) 476 { 477 auto bi = BigInt(2); 478 const BigInt a = BigInt.randomInteger(rng, bi, n_minus_1); 479 BigInt y = pow_mod(a); 480 if (mrWitness(y, reducer, n_minus_1, s)) 481 return false; 482 } 483 484 return true; 485 } 486 487 bool quickCheckPrime(const ref BigInt n, RandomNumberGenerator rng) 488 { return isPrime(n, rng, 32); } 489 490 bool checkPrime(const ref BigInt n, RandomNumberGenerator rng) 491 { return isPrime(n, rng, 56); } 492 493 bool verifyPrime(const ref BigInt n, RandomNumberGenerator rng) 494 { return isPrime(n, rng, 80); } 495 496 /** 497 * Randomly generate a prime 498 * Params: 499 * rng = a random number generator 500 * bits = how large the resulting prime should be in bits 501 * coprime = a positive integer the result should be coprime to 502 * equiv = a non-negative number that the result should be 503 equivalent to modulo equiv_mod 504 * modulo = the modulus equiv should be checked against 505 * Returns: random prime with the specified criteria 506 */ 507 BigInt randomPrime()(RandomNumberGenerator rng, 508 size_t bits, const ref BigInt coprime, 509 size_t equiv = 1, size_t modulo = 2) 510 { 511 if (bits <= 1) 512 throw new InvalidArgument("randomPrime: Can't make a prime of " ~ to!string(bits) ~ " bits"); 513 else if (bits == 2) 514 return ((rng.nextByte() % 2) ? BigInt(2) : BigInt(3)); 515 else if (bits == 3) 516 return ((rng.nextByte() % 2) ? BigInt(5) : BigInt(7)); 517 else if (bits == 4) 518 return ((rng.nextByte() % 2) ? BigInt(11) : BigInt(13)); 519 520 if (coprime <= 0) 521 throw new InvalidArgument("randomPrime: coprime must be > 0"); 522 if (modulo % 2 == 1 || modulo == 0) 523 throw new InvalidArgument("randomPrime: Invalid modulo value"); 524 if (equiv >= modulo || equiv % 2 == 0) 525 throw new InvalidArgument("randomPrime: equiv must be < modulo, and odd"); 526 527 while (true) 528 { 529 BigInt p = BigInt(rng, bits); 530 531 // Force lowest and two top bits on 532 p.setBit(bits - 1); 533 p.setBit(bits - 2); 534 p.setBit(0); 535 536 if (p % modulo != equiv) 537 p += (modulo - p % modulo) + equiv; 538 539 const size_t sieve_size = std.algorithm.min(bits / 2, PRIME_TABLE_SIZE); 540 SecureVector!ushort sieve = SecureVector!ushort(sieve_size); 541 542 for (size_t j = 0; j != sieve.length; ++j) 543 sieve[j] = cast(ushort)( p % PRIMES[j]); 544 545 size_t counter = 0; 546 while (true) 547 { 548 if (counter == 4096 || p.bits() > bits) 549 break; 550 551 bool passes_sieve = true; 552 ++counter; 553 p += modulo; 554 555 if (p.bits() > bits) 556 break; 557 558 for (size_t j = 0; j != sieve.length; ++j) 559 { 560 sieve[j] = cast(ushort)((sieve[j] + modulo) % PRIMES[j]); 561 if (sieve[j] == 0) 562 passes_sieve = false; 563 } 564 auto one = BigInt(1); 565 auto p_1 = p - one; 566 auto gcd_coprime = gcd(p_1, coprime); 567 if (!passes_sieve || gcd_coprime != one) 568 continue; 569 if (isPrime(p, rng, 64, true)) 570 return p.move; 571 } 572 } 573 } 574 575 /// ditto 576 BigInt randomPrime()(RandomNumberGenerator rng, 577 size_t bits, const BigInt coprime = BigInt(1), 578 size_t equiv = 1, size_t modulo = 2) 579 { 580 return randomPrime(rng, bits, coprime, equiv, modulo); 581 } 582 583 /** 584 * Return a random 'safe' prime, of the form p=2*q+1 with q prime 585 * Params: 586 * rng = a random number generator 587 * bits = is how long the resulting prime should be 588 * Returns: prime randomly chosen from safe primes of length bits 589 */ 590 BigInt randomSafePrime(RandomNumberGenerator rng, size_t bits) 591 { 592 if (bits <= 64) 593 throw new InvalidArgument("randomSafePrime: Can't make a prime of " ~ to!string(bits) ~ " bits"); 594 595 BigInt p; 596 do 597 p = (randomPrime(rng, bits - 1) << 1) + 1; 598 while (!isPrime(p, rng, 64, true)); 599 return p; 600 } 601 602 /** 603 * Generate DSA parameters using the FIPS 186 kosherizer 604 * Params: 605 * rng = a random number generator 606 * af = an algorithm factory 607 * p_out = where the prime p will be stored 608 * q_out = where the prime q will be stored 609 * pbits = how long p will be in bits 610 * qbits = how long q will be in bits 611 * Returns: random seed used to generate this parameter set 612 */ 613 Vector!ubyte generateDsaPrimes(RandomNumberGenerator rng, 614 AlgorithmFactory af, 615 ref BigInt p_out, ref BigInt q_out, 616 size_t pbits, size_t qbits) 617 { 618 while (true) 619 { 620 Vector!ubyte seed = Vector!ubyte(qbits / 8); 621 rng.randomize(seed.ptr, seed.length); 622 623 if (generateDsaPrimes(rng, af, p_out, q_out, pbits, qbits, seed)) 624 return seed; 625 } 626 } 627 628 629 /** 630 * Generate DSA parameters using the FIPS 186 kosherizer 631 * Params: 632 * rng = a random number generator 633 * af = an algorithm factory 634 * p_out = where the prime p will be stored 635 * q_out = where the prime q will be stored 636 * pbits = how long p will be in bits 637 * qbits = how long q will be in bits 638 * seed_c = the seed used to generate the parameters 639 * Returns: true if seed generated a valid DSA parameter set, otherwise 640 false. p_out and q_out are only valid if true was returned. 641 */ 642 bool generateDsaPrimes()(RandomNumberGenerator rng, 643 AlgorithmFactory af, 644 ref BigInt p_out, ref BigInt q_out, 645 size_t pbits, size_t qbits, 646 auto const ref Vector!ubyte seed_c) 647 { 648 if (!fips1863ValidSize(pbits, qbits)) 649 throw new InvalidArgument( 650 "FIPS 186-3 does not allow DSA domain parameters of " ~ to!string(pbits) ~ "/" ~ to!string(qbits) ~ " bits long"); 651 652 if (seed_c.length * 8 < qbits) 653 throw new InvalidArgument("Generating a DSA parameter set with a " ~ to!string(qbits) ~ 654 "long q requires a seed at least as many bits long"); 655 656 Unique!HashFunction hash = af.makeHashFunction("SHA-" ~ to!string(qbits)); 657 658 const size_t HASH_SIZE = hash.outputLength; 659 660 struct Seed 661 { 662 public: 663 this()(auto const ref Vector!ubyte s) { m_seed = s.dup(); } 664 665 ref T opCast(T : Vector!ubyte)() { return m_seed; } 666 667 alias m_seed this; 668 669 ref Seed opUnary(string op)() 670 if (op == "++") 671 { 672 for (size_t j = m_seed.length; j > 0; --j) 673 if (++m_seed[j-1]) 674 break; 675 return this; 676 } 677 private: 678 Vector!ubyte m_seed; 679 } 680 681 Seed seed = Seed(seed_c); 682 683 q_out.binaryDecode(hash.process(seed)); 684 q_out.setBit(qbits-1); 685 q_out.setBit(0); 686 687 if (!isPrime(q_out, rng)) 688 return false; 689 690 const size_t n = (pbits-1) / (HASH_SIZE * 8), b = (pbits-1) % (HASH_SIZE * 8); 691 692 BigInt X; 693 Vector!ubyte V = Vector!ubyte(HASH_SIZE * (n+1)); 694 695 foreach (size_t j; 0 .. 4096) 696 { 697 for (size_t k = 0; k <= n; ++k) 698 { 699 ++seed; 700 hash.update(seed); 701 hash.flushInto(&V[HASH_SIZE * (n-k)]); 702 } 703 704 X.binaryDecode(&V[HASH_SIZE - 1 - b/8], V.length - (HASH_SIZE - 1 - b/8)); 705 X.setBit(pbits-1); 706 707 p_out = X - (X % (q_out*2) - 1); 708 709 if (p_out.bits() == pbits && isPrime(p_out, rng)) 710 return true; 711 } 712 return false; 713 } 714 715 /* 716 * Check if this size is allowed by FIPS 186-3 717 */ 718 bool fips1863ValidSize(size_t pbits, size_t qbits) 719 { 720 if (qbits == 160) 721 return (pbits == 512 || pbits == 768 || pbits == 1024); 722 723 if (qbits == 224) 724 return (pbits == 2048); 725 726 if (qbits == 256) 727 return (pbits == 2048 || pbits == 3072); 728 729 return false; 730 } 731 732 /* 733 * If the modulus is odd, then we can avoid computing A and C. This is 734 * a critical path algorithm in some instances and an odd modulus is 735 * the common case for crypto, so worth special casing. See note 14.64 736 * in Handbook of Applied Cryptography for more details. 737 */ 738 BigInt inverseModOddModulus(const ref BigInt n, const ref BigInt mod) 739 { 740 BigInt u = mod.dup; 741 BigInt v = n.dup; 742 BigInt B = BigInt(0); 743 BigInt D = BigInt(1); 744 745 while (u.isNonzero()) 746 { 747 const size_t u_zero_bits = lowZeroBits(u); 748 u >>= u_zero_bits; 749 foreach (size_t i; 0 .. u_zero_bits) 750 { 751 if (B.isOdd()) 752 { B -= mod; } 753 B >>= 1; 754 } 755 756 const size_t v_zero_bits = lowZeroBits(v); 757 v >>= v_zero_bits; 758 foreach (size_t i; 0 .. v_zero_bits) 759 { 760 if (D.isOdd()) 761 { D -= mod; } 762 D >>= 1; 763 } 764 765 if (u >= v) { u -= v; B -= D; } 766 else { v -= u; D -= B; } 767 } 768 769 if (v != 1) 770 return BigInt(0); // no modular inverse 771 772 while (D.isNegative()) D += mod; 773 while (D >= mod) D -= mod; 774 775 return D.move(); 776 } 777 778 bool mrWitness(T : ModularReducer)(ref BigInt y, 779 auto ref T reducer_n, 780 const ref BigInt n_minus_1, size_t s) 781 { 782 if (y == 1 || y == n_minus_1) 783 return false; 784 785 foreach (size_t i; 1 .. s) 786 { 787 y = reducer_n.square(y); 788 789 if (y == 1) // found a non-trivial square root 790 return true; 791 if (y == n_minus_1) // -1, trivial square root, so give up 792 return false; 793 } 794 795 return true; // fails Fermat test 796 } 797 798 size_t mrTestIterations(size_t n_bits, size_t prob, bool random) 799 { 800 const size_t base = (prob + 2) / 2; // worst case 4^-t error rate 801 802 /* 803 * For randomly chosen numbers we can use the estimates from 804 * http://www.math.dartmouth.edu/~carlp/PDF/paper88.pdf 805 * 806 * These values are derived from the inequality for p(k,t) given on 807 * the second page. 808 */ 809 if (random && prob <= 80) 810 { 811 if (n_bits >= 1536) 812 return 2; // < 2^-89 813 if (n_bits >= 1024) 814 return 4; // < 2^-89 815 if (n_bits >= 512) 816 return 5; // < 2^-80 817 if (n_bits >= 256) 818 return 11; // < 2^-80 819 } 820 821 return base; 822 }