8#include <botan/internal/primality.h>
10#include <botan/exceptn.h>
11#include <botan/numthry.h>
13#include <botan/internal/barrett.h>
14#include <botan/internal/bit_ops.h>
15#include <botan/internal/ct_utils.h>
16#include <botan/internal/divide.h>
17#include <botan/internal/loadstor.h>
18#include <botan/internal/monty.h>
25class Prime_Sieve final {
27 Prime_Sieve(
const BigInt& init_value,
size_t sieve_size,
word step,
bool check_2p1) :
28 m_sieve(std::min(sieve_size,
PRIME_TABLE_SIZE)), m_step(step), m_check_2p1(check_2p1) {
29 for(
size_t i = 0; i != m_sieve.size(); ++i) {
34 size_t sieve_size()
const {
return m_sieve.size(); }
36 bool check_2p1()
const {
return m_check_2p1; }
40 for(
size_t i = 0; i != m_sieve.size(); ++i) {
41 m_sieve[i] = sieve_step_incr(m_sieve[i], m_step,
PRIMES[i]);
46 if(this->check_2p1()) {
56 passes &= ~CT::Mask<word>::is_equal(m_sieve[i], (
PRIMES[i] - 1) / 2);
60 return passes.as_bool();
70 const word stepmod = (step >= mod) ? (step % mod) : step;
73 const word next = (v + stepmod);
77 std::vector<word> m_sieve;
79 const bool m_check_2p1;
82#if defined(BOTAN_ENABLE_DEBUG_ASSERTS)
84bool no_small_multiples(
const BigInt& v,
const Prime_Sieve& sieve) {
85 const size_t sieve_size = sieve.sieve_size();
86 const bool check_2p1 = sieve.check_2p1();
91 const BigInt v_x2_p1 = 2 * v + 1;
93 for(
size_t i = 0; i != sieve_size; ++i) {
98 if(v_x2_p1 %
PRIMES[i] == 0)
114 bool sieve_check_2p1) {
115 const size_t MAX_ATTEMPTS = 32 * 1024;
120 if(std::gcd(equiv, modulo) != 1) {
121 throw Invalid_Argument(
"random_prime equiv and modulo must be relatively prime");
133 p += (modulo - (p % modulo)) + equiv;
135 Prime_Sieve sieve(p, bits, modulo, sieve_check_2p1);
137 for(
size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
167 if(
gcd(p - 1, coprime) > 1) {
172 if(p.bits() > bits) {
197 throw Invalid_Argument(
"random_prime: Can't make a prime of " + std::to_string(bits) +
" bits");
203 if(modulo == 0 || modulo >= 100000) {
217 if(equiv != 1 || modulo != 2 || coprime != 0) {
218 throw Not_Implemented(
"random_prime equiv/modulo/coprime options not usable for small primes");
223 }
else if(bits == 3) {
225 }
else if(bits == 4) {
233 const uint16_t small_prime =
PRIMES[idx];
245 return random_prime_with_sieve(rng, bits, coprime, equiv, modulo, prob,
false);
262 if(coprime <= 1 || coprime.
is_even() || coprime.
bits() > 64) {
263 throw Invalid_Argument(
"generate_rsa_prime coprime must be small odd positive integer");
266 const size_t MAX_ATTEMPTS = 32 * 1024;
271 BigInt p(keygen_rng, bits);
290 Prime_Sieve sieve(p, bits, step,
false);
292 for(
size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
316 if(
gcd(p - 1, coprime) > 1) {
320 if(p.
bits() > bits) {
336 throw Invalid_Argument(
"random_safe_prime: Can't make a prime of " + std::to_string(bits) +
" bits");
339 const size_t error_bound = 128;
348 q = random_prime_with_sieve(rng, bits - 1,
BigInt::zero(), 2, 3, error_bound,
true);
351 if(
is_prime(p, rng, error_bound,
true)) {
#define BOTAN_DEBUG_ASSERT(expr)
static Barrett_Reduction for_secret_modulus(const BigInt &m)
static BigInt from_word(word n)
static constexpr Mask< T > is_gte(T x, T y)
static constexpr Mask< T > set()
static constexpr Mask< T > expand(T v)
void randomize(std::span< uint8_t > output)
constexpr auto scoped_poison(const Ts &... xs)
word ct_mod_word(const BigInt &x, word y)
bool is_miller_rabin_probable_prime(const BigInt &n, const Barrett_Reduction &mod_n, const Montgomery_Params &monty_n, RandomNumberGenerator &rng, size_t test_iterations)
BigInt random_prime(RandomNumberGenerator &rng, size_t bits, const BigInt &coprime, size_t equiv, size_t modulo, size_t prob)
bool is_lucas_probable_prime(const BigInt &C, const Barrett_Reduction &mod_C)
const size_t PRIME_TABLE_SIZE
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
BigInt generate_rsa_prime(RandomNumberGenerator &keygen_rng, RandomNumberGenerator &prime_test_rng, size_t bits, const BigInt &coprime, size_t prob)
BOTAN_FORCE_INLINE constexpr size_t high_bit(T n)
BigInt gcd(const BigInt &a, const BigInt &b)
constexpr auto load_le(ParamTs &&... params)
size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random)
BigInt random_safe_prime(RandomNumberGenerator &rng, size_t bits)
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
The native machine word, used as the limb type for multiprecision integers.