summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/math/numbertheory/primality.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/math/numbertheory/primality.cpp')
-rw-r--r--comm/third_party/botan/src/lib/math/numbertheory/primality.cpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/math/numbertheory/primality.cpp b/comm/third_party/botan/src/lib/math/numbertheory/primality.cpp
new file mode 100644
index 0000000000..eb2be42b13
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/numbertheory/primality.cpp
@@ -0,0 +1,203 @@
+/*
+* (C) 2016,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/primality.h>
+#include <botan/internal/monty_exp.h>
+#include <botan/bigint.h>
+#include <botan/monty.h>
+#include <botan/reducer.h>
+#include <botan/rng.h>
+#include <algorithm>
+
+namespace Botan {
+
+bool is_lucas_probable_prime(const BigInt& C, const Modular_Reducer& mod_C)
+ {
+ if(C <= 1)
+ return false;
+ else if(C == 2)
+ return true;
+ else if(C.is_even())
+ return false;
+ else if(C == 3 || C == 5 || C == 7 || C == 11 || C == 13)
+ return true;
+
+ BigInt D = 5;
+
+ for(;;)
+ {
+ int32_t j = jacobi(D, C);
+ if(j == 0)
+ return false;
+
+ if(j == -1)
+ break;
+
+ // Check 5, -7, 9, -11, 13, -15, 17, ...
+ if(D.is_negative())
+ {
+ D.flip_sign();
+ D += 2;
+ }
+ else
+ {
+ D += 2;
+ D.flip_sign();
+ }
+
+ if(D == 17 && is_perfect_square(C).is_nonzero())
+ return false;
+ }
+
+ const BigInt K = C + 1;
+ const size_t K_bits = K.bits() - 1;
+
+ BigInt U = 1;
+ BigInt V = 1;
+
+ BigInt Ut, Vt, U2, V2;
+
+ for(size_t i = 0; i != K_bits; ++i)
+ {
+ const bool k_bit = K.get_bit(K_bits - 1 - i);
+
+ Ut = mod_C.multiply(U, V);
+
+ Vt = mod_C.reduce(mod_C.square(V) + mod_C.multiply(D, mod_C.square(U)));
+ Vt.ct_cond_add(Vt.is_odd(), C);
+ Vt >>= 1;
+ Vt = mod_C.reduce(Vt);
+
+ U = Ut;
+ V = Vt;
+
+ U2 = mod_C.reduce(Ut + Vt);
+ U2.ct_cond_add(U2.is_odd(), C);
+ U2 >>= 1;
+
+ V2 = mod_C.reduce(Vt + Ut*D);
+ V2.ct_cond_add(V2.is_odd(), C);
+ V2 >>= 1;
+
+ U.ct_cond_assign(k_bit, U2);
+ V.ct_cond_assign(k_bit, V2);
+ }
+
+ return (U == 0);
+ }
+
+bool is_bailie_psw_probable_prime(const BigInt& n, const Modular_Reducer& mod_n)
+ {
+ auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
+ return passes_miller_rabin_test(n, mod_n, monty_n, 2) && is_lucas_probable_prime(n, mod_n);
+ }
+
+bool is_bailie_psw_probable_prime(const BigInt& n)
+ {
+ Modular_Reducer mod_n(n);
+ return is_bailie_psw_probable_prime(n, mod_n);
+ }
+
+bool passes_miller_rabin_test(const BigInt& n,
+ const Modular_Reducer& mod_n,
+ const std::shared_ptr<Montgomery_Params>& monty_n,
+ const BigInt& a)
+ {
+ BOTAN_ASSERT_NOMSG(n > 1);
+
+ const BigInt n_minus_1 = n - 1;
+ const size_t s = low_zero_bits(n_minus_1);
+ const BigInt nm1_s = n_minus_1 >> s;
+ const size_t n_bits = n.bits();
+
+ const size_t powm_window = 4;
+
+ auto powm_a_n = monty_precompute(monty_n, a, powm_window);
+
+ BigInt y = monty_execute(*powm_a_n, nm1_s, n_bits);
+
+ if(y == 1 || y == n_minus_1)
+ return true;
+
+ for(size_t i = 1; i != s; ++i)
+ {
+ y = mod_n.square(y);
+
+ if(y == 1) // found a non-trivial square root
+ return false;
+
+ /*
+ -1 is the trivial square root of unity, so ``a`` is not a
+ witness for this number - give up
+ */
+ if(y == n_minus_1)
+ return true;
+ }
+
+ return false;
+ }
+
+bool is_miller_rabin_probable_prime(const BigInt& n,
+ const Modular_Reducer& mod_n,
+ RandomNumberGenerator& rng,
+ size_t test_iterations)
+ {
+ BOTAN_ASSERT_NOMSG(n > 1);
+
+ auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
+
+ for(size_t i = 0; i != test_iterations; ++i)
+ {
+ const BigInt a = BigInt::random_integer(rng, 2, n);
+
+ if(!passes_miller_rabin_test(n, mod_n, monty_n, a))
+ return false;
+ }
+
+ // Failed to find a counterexample
+ return true;
+ }
+
+
+size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random)
+ {
+ const size_t base = (prob + 2) / 2; // worst case 4^-t error rate
+
+ /*
+ * If the candidate prime was maliciously constructed, we can't rely
+ * on arguments based on p being random.
+ */
+ if(random == false)
+ return base;
+
+ /*
+ * For randomly chosen numbers we can use the estimates from
+ * http://www.math.dartmouth.edu/~carlp/PDF/paper88.pdf
+ *
+ * These values are derived from the inequality for p(k,t) given on
+ * the second page.
+ */
+ if(prob <= 128)
+ {
+ if(n_bits >= 1536)
+ return 4; // < 2^-133
+ if(n_bits >= 1024)
+ return 6; // < 2^-133
+ if(n_bits >= 512)
+ return 12; // < 2^-129
+ if(n_bits >= 256)
+ return 29; // < 2^-128
+ }
+
+ /*
+ If the user desires a smaller error probability than we have
+ precomputed error estimates for, just fall back to using the worst
+ case error rate.
+ */
+ return base;
+ }
+
+}