Coverage Report

Created: 2026-04-01 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/math/numbertheory/primality.cpp
Line
Count
Source
1
/*
2
* (C) 2016,2018 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#include <botan/internal/primality.h>
8
9
#include <botan/bigint.h>
10
#include <botan/numthry.h>
11
#include <botan/rng.h>
12
#include <botan/internal/barrett.h>
13
#include <botan/internal/monty.h>
14
#include <botan/internal/monty_exp.h>
15
#include <algorithm>
16
17
namespace Botan {
18
19
0
bool is_lucas_probable_prime(const BigInt& C, const Barrett_Reduction& mod_C) {
20
0
   BOTAN_ARG_CHECK(C.is_positive(), "Argument should be a positive integer");
21
22
0
   if(C == 2 || C == 3 || C == 5 || C == 7 || C == 11 || C == 13) {
23
0
      return true;
24
0
   }
25
26
0
   if(C <= 1 || C.is_even()) {
27
0
      return false;
28
0
   }
29
30
0
   BigInt D = BigInt::from_word(5);
31
32
0
   for(;;) {
33
0
      int32_t j = jacobi(D, C);
34
0
      if(j == 0) {
35
0
         return false;
36
0
      }
37
38
0
      if(j == -1) {
39
0
         break;
40
0
      }
41
42
      // Check 5, -7, 9, -11, 13, -15, 17, ...
43
0
      if(D.is_negative()) {
44
0
         D.flip_sign();
45
0
         D += 2;
46
0
      } else {
47
0
         D += 2;
48
0
         D.flip_sign();
49
0
      }
50
51
0
      if(D == 17 && is_perfect_square(C).is_nonzero()) {
52
0
         return false;
53
0
      }
54
0
   }
55
56
0
   if(D.is_negative()) {
57
0
      D += C;
58
0
   }
59
60
0
   const BigInt K = C + 1;
61
0
   const size_t K_bits = K.bits() - 1;
62
63
0
   BigInt U = BigInt::one();
64
0
   BigInt V = BigInt::one();
65
66
0
   BigInt Ut, Vt, U2, V2;
67
68
0
   for(size_t i = 0; i != K_bits; ++i) {
69
0
      const bool k_bit = K.get_bit(K_bits - 1 - i);
70
71
0
      Ut = mod_C.multiply(U, V);
72
73
0
      Vt = mod_C.reduce(mod_C.square(V) + mod_C.multiply(D, mod_C.square(U)));
74
0
      Vt.ct_cond_add(Vt.is_odd(), C);
75
0
      Vt >>= 1;
76
0
      Vt = mod_C.reduce(Vt);
77
78
0
      U = Ut;
79
0
      V = Vt;
80
81
0
      U2 = mod_C.reduce(Ut + Vt);
82
0
      U2.ct_cond_add(U2.is_odd(), C);
83
0
      U2 >>= 1;
84
85
0
      V2 = mod_C.reduce(Vt + mod_C.multiply(Ut, D));
86
0
      V2.ct_cond_add(V2.is_odd(), C);
87
0
      V2 >>= 1;
88
89
0
      U.ct_cond_assign(k_bit, U2);
90
0
      V.ct_cond_assign(k_bit, V2);
91
0
   }
92
93
0
   return (U == 0);
94
0
}
95
96
0
bool is_bailie_psw_probable_prime(const BigInt& n, const Barrett_Reduction& mod_n) {
97
0
   if(n == 2) {
98
0
      return true;
99
0
   } else if(n <= 1 || n.is_even()) {
100
0
      return false;
101
0
   }
102
103
0
   auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
104
0
   const auto base = BigInt::from_word(2);
105
0
   return passes_miller_rabin_test(n, mod_n, monty_n, base) && is_lucas_probable_prime(n, mod_n);
106
0
}
107
108
bool passes_miller_rabin_test(const BigInt& n,
109
                              const Barrett_Reduction& mod_n,
110
                              const std::shared_ptr<Montgomery_Params>& monty_n,
111
0
                              const BigInt& a) {
112
0
   if(n < 3 || n.is_even()) {
113
0
      return false;
114
0
   }
115
116
0
   BOTAN_ASSERT_NOMSG(n > 1);
117
118
0
   const BigInt n_minus_1 = n - 1;
119
0
   const size_t s = low_zero_bits(n_minus_1);
120
0
   const BigInt nm1_s = n_minus_1 >> s;
121
0
   const size_t n_bits = n.bits();
122
123
0
   const size_t powm_window = 4;
124
125
0
   auto powm_a_n = monty_precompute(monty_n, a, powm_window);
126
127
0
   BigInt y = monty_execute(*powm_a_n, nm1_s, n_bits).value();
128
129
0
   if(y == 1 || y == n_minus_1) {
130
0
      return true;
131
0
   }
132
133
0
   for(size_t i = 1; i != s; ++i) {
134
0
      y = mod_n.square(y);
135
136
0
      if(y == 1) {  // found a non-trivial square root
137
0
         return false;
138
0
      }
139
140
      /*
141
      -1 is the trivial square root of unity, so ``a`` is not a
142
      witness for this number - give up
143
      */
144
0
      if(y == n_minus_1) {
145
0
         return true;
146
0
      }
147
0
   }
148
149
0
   return false;
150
0
}
151
152
bool is_miller_rabin_probable_prime(const BigInt& n,
153
                                    const Barrett_Reduction& mod_n,
154
                                    RandomNumberGenerator& rng,
155
0
                                    size_t test_iterations) {
156
0
   if(n < 3 || n.is_even()) {
157
0
      return false;
158
0
   }
159
160
0
   auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
161
162
0
   for(size_t i = 0; i != test_iterations; ++i) {
163
0
      const BigInt a = BigInt::random_integer(rng, BigInt::from_word(2), n);
164
165
0
      if(!passes_miller_rabin_test(n, mod_n, monty_n, a)) {
166
0
         return false;
167
0
      }
168
0
   }
169
170
   // Failed to find a counterexample
171
0
   return true;
172
0
}
173
174
0
size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random) {
175
0
   const size_t base = (prob + 2) / 2;  // worst case 4^-t error rate
176
177
   /*
178
   * If the candidate prime was maliciously constructed, we can't rely
179
   * on arguments based on p being random.
180
   */
181
0
   if(random == false) {
182
0
      return base;
183
0
   }
184
185
   /*
186
   * For randomly chosen numbers we can use the estimates from
187
   * http://www.math.dartmouth.edu/~carlp/PDF/paper88.pdf
188
   *
189
   * These values are derived from the inequality for p(k,t) given on
190
   * the second page.
191
   */
192
0
   if(prob <= 128) {
193
0
      if(n_bits >= 1536) {
194
0
         return 4;  // < 2^-133
195
0
      }
196
0
      if(n_bits >= 1024) {
197
0
         return 6;  // < 2^-133
198
0
      }
199
0
      if(n_bits >= 512) {
200
0
         return 12;  // < 2^-129
201
0
      }
202
0
      if(n_bits >= 256) {
203
0
         return 29;  // < 2^-128
204
0
      }
205
0
   }
206
207
   /*
208
   If the user desires a smaller error probability than we have
209
   precomputed error estimates for, just fall back to using the worst
210
   case error rate.
211
   */
212
0
   return base;
213
0
}
214
215
}  // namespace Botan