From 7badac9c6a32dbb0fe64fc909b7124c044ee1a1d Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 2 May 2018 20:10:44 -0400 Subject: Improve performance of Pollard rho implementation Using Montgomery is somewhat faster and allows avoiding mallocs. Test GCD only on intervals since gcd is 90+% of the runtime cost. --- src/cli/math.cpp | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'src/cli/math.cpp') diff --git a/src/cli/math.cpp b/src/cli/math.cpp index 2f3339898..0ddc9c48c 100644 --- a/src/cli/math.cpp +++ b/src/cli/math.cpp @@ -10,6 +10,7 @@ #include #include +#include #include namespace Botan_CLI { @@ -163,34 +164,55 @@ class Factor final : public Command } /* - * Pollard's Rho algorithm, as described in the MIT algorithms book. We - * use (x^2+x) mod n instead of (x*2-1) mod n as the random function, - * it _seems_ to lead to faster factorization for the values I tried. + * Pollard's Rho algorithm, as described in the MIT algorithms book. + * Uses Brent's cycle finding */ Botan::BigInt rho(const Botan::BigInt& n, Botan::RandomNumberGenerator& rng) { - Botan::BigInt x = Botan::BigInt::random_integer(rng, 0, n - 1); - Botan::BigInt y = x; - Botan::BigInt d = 0; + auto monty_n = std::make_shared(n); - Botan::Modular_Reducer mod_n(n); + const Botan::Montgomery_Int one(monty_n, monty_n->R1(), false); + + Botan::Montgomery_Int x(monty_n, Botan::BigInt::random_integer(rng, 2, n - 3), false); + Botan::Montgomery_Int y = x; + Botan::Montgomery_Int z = one; + Botan::BigInt d; + Botan::Montgomery_Int t(monty_n); + + Botan::secure_vector ws; size_t i = 1, k = 2; + while(true) { i++; - if(i == 0) // overflow, bail out + if(i >= 0xFFFF0000) // bad seed? too slow? bail out { break; } - x = mod_n.multiply((x + 1), x); + x.square_this(ws); // x = x^2 + x.add(one, ws); + + t = y; + t -= x; + + z.mul_by(t, ws); - d = Botan::gcd(y - x, n); - if(d != 1 && d != n) + if(i == k || i % 128 == 0) { - return d; + d = Botan::gcd(z.value(), n); + z = one; + + if(d == n) + { + // TODO Should rewind here + break; + } + + if(d != 1) + return d; } if(i == k) @@ -199,6 +221,8 @@ class Factor final : public Command k = 2 * k; } } + + // failed return 0; } -- cgit v1.2.3