Coverage Report

Created: 2025-04-11 06:34

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