8#include <botan/internal/primality.h>
10#include <botan/numthry.h>
11#include <botan/reducer.h>
13#include <botan/internal/bit_ops.h>
14#include <botan/internal/ct_utils.h>
15#include <botan/internal/loadstor.h>
22class Prime_Sieve
final {
24 Prime_Sieve(
const BigInt& init_value,
size_t sieve_size, word step,
bool check_2p1) :
25 m_sieve(std::min(sieve_size,
PRIME_TABLE_SIZE)), m_step(step), m_check_2p1(check_2p1) {
26 for(
size_t i = 0; i != m_sieve.size(); ++i) {
27 m_sieve[i] = init_value %
PRIMES[i];
31 size_t sieve_size()
const {
return m_sieve.size(); }
33 bool check_2p1()
const {
return m_check_2p1; }
37 for(
size_t i = 0; i != m_sieve.size(); ++i) {
38 m_sieve[i] = (m_sieve[i] + m_step) %
PRIMES[i];
43 if(this->check_2p1()) {
53 passes &= ~CT::Mask<word>::is_equal(m_sieve[i], (
PRIMES[i] - 1) / 2);
57 return passes.as_bool();
61 std::vector<word> m_sieve;
63 const bool m_check_2p1;
66#if defined(BOTAN_ENABLE_DEBUG_ASSERTS)
68bool no_small_multiples(
const BigInt& v,
const Prime_Sieve& sieve) {
69 const size_t sieve_size = sieve.sieve_size();
70 const bool check_2p1 = sieve.check_2p1();
75 const BigInt v_x2_p1 = 2 * v + 1;
77 for(
size_t i = 0; i != sieve_size; ++i) {
82 if(v_x2_p1 %
PRIMES[i] == 0)
100 throw Invalid_Argument(
"random_prime: Can't make a prime of " + std::to_string(bits) +
" bits");
105 if(modulo == 0 || modulo >= 100000) {
118 if(equiv != 1 || modulo != 2 || coprime != 0) {
119 throw Not_Implemented(
"random_prime equiv/modulo/coprime options not usable for small primes");
124 }
else if(bits == 3) {
126 }
else if(bits == 4) {
134 const uint16_t small_prime =
PRIMES[idx];
143 const size_t MAX_ATTEMPTS = 32 * 1024;
156 p += (modulo - (p % modulo)) + equiv;
158 Prime_Sieve sieve(p, bits, modulo,
true);
160 for(
size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
189 if(
gcd(p - 1, coprime) > 1) {
194 if(p.
bits() > bits) {
225 if(coprime <= 1 || coprime.
is_even() || coprime.
bits() > 64) {
226 throw Invalid_Argument(
"generate_rsa_prime coprime must be small odd positive integer");
229 const size_t MAX_ATTEMPTS = 32 * 1024;
234 BigInt p(keygen_rng, bits);
251 Prime_Sieve sieve(p, bits, step,
false);
253 for(
size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
276 if(
gcd(p - 1, coprime) > 1) {
280 if(p.
bits() > bits) {
296 throw Invalid_Argument(
"random_safe_prime: Can't make a prime of " + std::to_string(bits) +
" bits");
299 const size_t error_bound = 128;
310 if(
is_prime(p, rng, error_bound,
true)) {
#define BOTAN_DEBUG_ASSERT(expr)
static BigInt from_word(word n)
static constexpr Mask< T > set()
static constexpr Mask< T > expand(T v)
void randomize(std::span< uint8_t > output)
int(* final)(unsigned char *, CTX *)
BigInt random_prime(RandomNumberGenerator &rng, size_t bits, const BigInt &coprime, size_t equiv, size_t modulo, size_t prob)
constexpr size_t high_bit(T n)
const size_t PRIME_TABLE_SIZE
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
bool is_miller_rabin_probable_prime(const BigInt &n, const Modular_Reducer &mod_n, RandomNumberGenerator &rng, size_t test_iterations)
BigInt generate_rsa_prime(RandomNumberGenerator &keygen_rng, RandomNumberGenerator &prime_test_rng, size_t bits, const BigInt &coprime, size_t prob)
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)
bool is_lucas_probable_prime(const BigInt &C, const Modular_Reducer &mod_C)