summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/cli/math.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/cli/math.cpp')
-rw-r--r--comm/third_party/botan/src/cli/math.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/cli/math.cpp b/comm/third_party/botan/src/cli/math.cpp
new file mode 100644
index 0000000000..1268cd3e53
--- /dev/null
+++ b/comm/third_party/botan/src/cli/math.cpp
@@ -0,0 +1,269 @@
+/*
+* (C) 2009,2010,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "cli.h"
+
+#if defined(BOTAN_HAS_NUMBERTHEORY)
+
+#include <botan/numthry.h>
+#include <botan/monty.h>
+#include <iterator>
+
+namespace Botan_CLI {
+
+class Modular_Inverse final : public Command
+ {
+ public:
+ Modular_Inverse() : Command("mod_inverse n mod") {}
+
+ std::string group() const override
+ {
+ return "numtheory";
+ }
+
+ std::string description() const override
+ {
+ return "Calculates a modular inverse";
+ }
+
+ void go() override
+ {
+ const Botan::BigInt n(get_arg("n"));
+ const Botan::BigInt mod(get_arg("mod"));
+
+ output() << Botan::inverse_mod(n, mod) << "\n";
+ }
+ };
+
+BOTAN_REGISTER_COMMAND("mod_inverse", Modular_Inverse);
+
+class Gen_Prime final : public Command
+ {
+ public:
+ Gen_Prime() : Command("gen_prime --count=1 bits") {}
+
+ std::string group() const override
+ {
+ return "numtheory";
+ }
+
+ std::string description() const override
+ {
+ return "Samples one or more primes";
+ }
+
+ void go() override
+ {
+ const size_t bits = get_arg_sz("bits");
+ const size_t cnt = get_arg_sz("count");
+
+ for(size_t i = 0; i != cnt; ++i)
+ {
+ const Botan::BigInt p = Botan::random_prime(rng(), bits);
+ output() << p << "\n";
+ }
+ }
+ };
+
+BOTAN_REGISTER_COMMAND("gen_prime", Gen_Prime);
+
+class Is_Prime final : public Command
+ {
+ public:
+ Is_Prime() : Command("is_prime --prob=56 n") {}
+
+ std::string group() const override
+ {
+ return "numtheory";
+ }
+
+ std::string description() const override
+ {
+ return "Test if the integer n is composite or prime";
+ }
+
+ void go() override
+ {
+ Botan::BigInt n(get_arg("n"));
+ const size_t prob = get_arg_sz("prob");
+ const bool prime = Botan::is_prime(n, rng(), prob);
+
+ output() << n << " is " << (prime ? "probably prime" : "composite") << "\n";
+ }
+ };
+
+BOTAN_REGISTER_COMMAND("is_prime", Is_Prime);
+
+/*
+* Factor integers using a combination of trial division by small
+* primes, and Pollard's Rho algorithm
+*/
+class Factor final : public Command
+ {
+ public:
+ Factor() : Command("factor n") {}
+
+ std::string group() const override
+ {
+ return "numtheory";
+ }
+
+ std::string description() const override
+ {
+ return "Factor a given integer";
+ }
+
+ void go() override
+ {
+ Botan::BigInt n(get_arg("n"));
+
+ std::vector<Botan::BigInt> factors = factorize(n, rng());
+ std::sort(factors.begin(), factors.end());
+
+ output() << n << ": ";
+ std::copy(factors.begin(), factors.end(), std::ostream_iterator<Botan::BigInt>(output(), " "));
+ output() << std::endl;
+ }
+
+ private:
+
+ std::vector<Botan::BigInt> factorize(const Botan::BigInt& n_in,
+ Botan::RandomNumberGenerator& rng)
+ {
+ Botan::BigInt n = n_in;
+ std::vector<Botan::BigInt> factors = remove_small_factors(n);
+
+ while(n != 1)
+ {
+ if(Botan::is_prime(n, rng))
+ {
+ factors.push_back(n);
+ break;
+ }
+
+ Botan::BigInt a_factor = 0;
+ while(a_factor == 0)
+ {
+ a_factor = rho(n, rng);
+ }
+
+ std::vector<Botan::BigInt> rho_factored = factorize(a_factor, rng);
+ for(size_t j = 0; j != rho_factored.size(); j++)
+ {
+ factors.push_back(rho_factored[j]);
+ }
+
+ n /= a_factor;
+ }
+
+ return factors;
+ }
+
+ /*
+ * 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)
+ {
+ auto monty_n = std::make_shared<Botan::Montgomery_Params>(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::Montgomery_Int t(monty_n);
+ Botan::BigInt d;
+
+ Botan::secure_vector<Botan::word> ws;
+
+ size_t i = 1, k = 2;
+
+ while(true)
+ {
+ i++;
+
+ if(i >= 0xFFFF0000) // bad seed? too slow? bail out
+ {
+ break;
+ }
+
+ x.square_this(ws); // x = x^2
+ x.add(one, ws);
+
+ t = y;
+ t.sub(x, ws);
+
+ z.mul_by(t, ws);
+
+ if(i == k || i % 128 == 0)
+ {
+ d = Botan::gcd(z.value(), n);
+ z = one;
+
+ if(d == n)
+ {
+ // TODO Should rewind here
+ break;
+ }
+
+ if(d != 1)
+ return d;
+ }
+
+ if(i == k)
+ {
+ y = x;
+ k = 2 * k;
+ }
+ }
+
+ // failed
+ return 0;
+ }
+
+ // Remove (and return) any small (< 2^16) factors
+ std::vector<Botan::BigInt> remove_small_factors(Botan::BigInt& n)
+ {
+ std::vector<Botan::BigInt> factors;
+
+ while(n.is_even())
+ {
+ factors.push_back(2);
+ n /= 2;
+ }
+
+ for(size_t j = 0; j != Botan::PRIME_TABLE_SIZE; j++)
+ {
+ uint16_t prime = Botan::PRIMES[j];
+ if(n < prime)
+ {
+ break;
+ }
+
+ Botan::BigInt x = Botan::gcd(n, prime);
+
+ if(x != 1)
+ {
+ n /= x;
+
+ while(x != 1)
+ {
+ x /= prime;
+ factors.push_back(prime);
+ }
+ }
+ }
+
+ return factors;
+ }
+ };
+
+BOTAN_REGISTER_COMMAND("factor", Factor);
+
+}
+
+#endif