• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.81
/src/tests/test_bigint.cpp
1
/*
2
* (C) 2009,2015,2016 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#if defined(BOTAN_HAS_NUMBERTHEORY)
10
   #include "test_rng.h"
11
   #include <botan/bigint.h>
12
   #include <botan/numthry.h>
13
   #include <botan/reducer.h>
14
   #include <botan/internal/divide.h>
15
   #include <botan/internal/parsing.h>
16
   #include <botan/internal/primality.h>
17
#endif
18

19
namespace Botan_Tests {
20

21
namespace {
22

23
#if defined(BOTAN_HAS_NUMBERTHEORY)
24

25
using Botan::BigInt;
26

27
class BigInt_Unit_Tests final : public Test {
×
28
   public:
29
      std::vector<Test::Result> run() override {
1✔
30
         std::vector<Test::Result> results;
1✔
31

32
         results.push_back(test_bigint_sizes());
2✔
33
         results.push_back(test_random_prime());
2✔
34
         results.push_back(test_encode());
2✔
35
         results.push_back(test_bigint_io());
2✔
36
         results.push_back(test_get_substring());
2✔
37

38
         return results;
1✔
39
      }
×
40

41
   private:
42
      static Test::Result test_bigint_sizes() {
1✔
43
         Test::Result result("BigInt size functions");
1✔
44

45
         for(size_t bit : {1, 8, 16, 31, 32, 64, 97, 128, 179, 192, 512, 521}) {
13✔
46
            BigInt a;
12✔
47

48
            a.set_bit(bit);
12✔
49

50
            // Test 2^n and 2^n-1
51
            for(size_t i = 0; i != 2; ++i) {
36✔
52
               const size_t exp_bits = bit + 1 - i;
24✔
53
               result.test_eq("BigInt::bits", a.bits(), exp_bits);
24✔
54
               result.test_eq(
24✔
55
                  "BigInt::bytes", a.bytes(), (exp_bits % 8 == 0) ? (exp_bits / 8) : (exp_bits + 8 - exp_bits % 8) / 8);
24✔
56

57
               if(bit == 1 && i == 1) {
24✔
58
                  result.test_is_eq("BigInt::to_u32bit zero", a.to_u32bit(), static_cast<uint32_t>(1));
2✔
59
               } else if(bit <= 31 || (bit == 32 && i == 1)) {
23✔
60
                  result.test_is_eq(
8✔
61
                     "BigInt::to_u32bit", a.to_u32bit(), static_cast<uint32_t>((uint64_t(1) << bit) - i));
16✔
62
               } else {
63
                  try {
15✔
64
                     a.to_u32bit();
15✔
65
                     result.test_failure("BigInt::to_u32bit roundtripped out of range value");
×
66
                  } catch(std::exception&) { result.test_success("BigInt::to_u32bit rejected out of range"); }
30✔
67
               }
68

69
               a--;
48✔
70
            }
71
         }
12✔
72

73
         return result;
1✔
74
      }
×
75

76
      static Test::Result test_random_prime() {
1✔
77
         Test::Result result("BigInt prime generation");
1✔
78

79
         result.test_throws("Invalid bit size", "random_prime: Can't make a prime of 0 bits", []() {
4✔
80
            Botan::random_prime(Test::rng(), 0);
1✔
81
         });
×
82
         result.test_throws("Invalid bit size", "random_prime: Can't make a prime of 1 bits", []() {
3✔
83
            Botan::random_prime(Test::rng(), 1);
1✔
84
         });
×
85
         result.test_throws("Invalid arg", "random_prime Invalid value for equiv/modulo", []() {
3✔
86
            Botan::random_prime(Test::rng(), 2, 1, 0, 2);
1✔
87
         });
×
88

89
         BigInt p = Botan::random_prime(Test::rng(), 2);
1✔
90
         result.confirm("Only two 2-bit primes", p == 2 || p == 3);
2✔
91

92
         p = Botan::random_prime(Test::rng(), 3);
2✔
93
         result.confirm("Only two 3-bit primes", p == 5 || p == 7);
4✔
94

95
         p = Botan::random_prime(Test::rng(), 4);
2✔
96
         result.confirm("Only two 4-bit primes", p == 11 || p == 13);
2✔
97

98
         for(size_t bits = 5; bits <= 32; ++bits) {
29✔
99
            p = Botan::random_prime(Test::rng(), bits);
56✔
100
            result.test_eq("Expected bit size", p.bits(), bits);
28✔
101
            result.test_eq("P is prime", Botan::is_prime(p, Test::rng()), true);
56✔
102
         }
103

104
         const size_t safe_prime_bits = 65;
1✔
105
         const BigInt safe_prime = Botan::random_safe_prime(Test::rng(), safe_prime_bits);
1✔
106
         result.test_eq("Safe prime size", safe_prime.bits(), safe_prime_bits);
1✔
107
         result.confirm("P is prime", Botan::is_prime(safe_prime, Test::rng()));
2✔
108
         result.confirm("(P-1)/2 is prime", Botan::is_prime((safe_prime - 1) / 2, Test::rng()));
4✔
109

110
         return result;
1✔
111
      }
2✔
112

113
      static Test::Result test_encode() {
1✔
114
         Test::Result result("BigInt encoding functions");
1✔
115

116
         const BigInt n1(0xffff);
1✔
117
         const BigInt n2(1023);
1✔
118

119
         Botan::secure_vector<uint8_t> encoded_n1 = BigInt::encode_1363(n1, 256);
1✔
120
         Botan::secure_vector<uint8_t> encoded_n2 = BigInt::encode_1363(n2, 256);
1✔
121
         Botan::secure_vector<uint8_t> expected = encoded_n1;
1✔
122
         expected += encoded_n2;
1✔
123

124
         Botan::secure_vector<uint8_t> encoded_n1_n2 = BigInt::encode_fixed_length_int_pair(n1, n2, 256);
1✔
125
         result.test_eq("encode_fixed_length_int_pair", encoded_n1_n2, expected);
1✔
126

127
         for(size_t i = 0; i < 256 - n1.bytes(); ++i) {
255✔
128
            if(encoded_n1[i] != 0) {
254✔
129
               result.test_failure("encode_1363", "no zero byte");
×
130
            }
131
         }
132

133
         return result;
1✔
134
      }
6✔
135

136
      static Test::Result test_get_substring() {
1✔
137
         Test::Result result("BigInt get_substring");
1✔
138

139
         const size_t rbits = 1024;
1✔
140

141
         const Botan::BigInt r(Test::rng(), rbits);
1✔
142

143
         for(size_t wlen = 1; wlen <= 32; ++wlen) {
33✔
144
            for(size_t offset = 0; offset != rbits + 64; ++offset) {
34,848✔
145
               const uint32_t val = r.get_substring(offset, wlen);
34,816✔
146

147
               Botan::BigInt t = r >> offset;
34,816✔
148
               t.mask_bits(wlen);
34,816✔
149

150
               const uint32_t cmp = t.to_u32bit();
34,816✔
151

152
               result.test_eq("Same value", size_t(val), size_t(cmp));
69,632✔
153
            }
34,816✔
154
         }
155

156
         return result;
1✔
157
      }
1✔
158

159
      static Test::Result test_bigint_io() {
1✔
160
         Test::Result result("BigInt IO operators");
1✔
161

162
         const std::map<std::string, Botan::BigInt> str_to_val = {{"-13", -Botan::BigInt(13)},
2✔
163
                                                                  {"0", Botan::BigInt(0)},
2✔
164
                                                                  {"0x13", Botan::BigInt(0x13)},
2✔
165
                                                                  {"1", Botan::BigInt(1)},
2✔
166
                                                                  {"4294967297", Botan::BigInt(2147483648) * 2 + 1}};
13✔
167

168
         for(const auto& vec : str_to_val) {
6✔
169
            Botan::BigInt n;
5✔
170
            std::istringstream iss;
5✔
171

172
            iss.str(vec.first);
5✔
173
            iss >> n;
5✔
174
            result.test_eq("input '" + vec.first + "'", n, vec.second);
5✔
175
         }
10✔
176

177
         auto check_bigint_formatting = [&](const Botan::BigInt& n,
6✔
178
                                            const std::string& dec,
179
                                            const std::string& hex,
180
                                            const std::string& neg_dec,
181
                                            const std::string& neg_hex) {
182
            std::ostringstream oss;
5✔
183
            oss << n;
5✔
184
            result.test_eq("output decimal", oss.str(), dec);
10✔
185

186
            oss.str("");
10✔
187
            oss << (-n);
5✔
188
            result.test_eq("output negative decimal", oss.str(), neg_dec);
10✔
189

190
            oss.str("");
10✔
191
            oss << std::hex << n;
5✔
192
            result.test_eq("output hex", oss.str(), hex);
10✔
193

194
            oss.str("");
10✔
195
            oss << std::hex << (-n);
5✔
196
            result.test_eq("output negative hex", oss.str(), neg_hex);
10✔
197
         };
5✔
198

199
         check_bigint_formatting(Botan::BigInt(33), "33", "0x21", "-33", "-0x21");
2✔
200
         check_bigint_formatting(Botan::BigInt::from_s32(-33), "-33", "-0x21", "33", "0x21");
2✔
201
         check_bigint_formatting(Botan::BigInt(255), "255", "0xFF", "-255", "-0xFF");
2✔
202
         check_bigint_formatting(Botan::BigInt(0), "0", "0x00", "0", "0x00");
2✔
203
         check_bigint_formatting(Botan::BigInt(5), "5", "0x05", "-5", "-0x05");
2✔
204

205
         result.test_throws("octal output not supported", [&]() {
2✔
206
            Botan::BigInt n(5);
1✔
207
            std::ostringstream oss;
1✔
208
            oss << std::oct << n;
1✔
209
         });
1✔
210

211
         return result;
1✔
212
      }
1✔
213
};
214

215
BOTAN_REGISTER_TEST("math", "bigint_unit", BigInt_Unit_Tests);
216

217
class BigInt_Cmp_Test final : public Text_Based_Test {
×
218
   public:
219
      BigInt_Cmp_Test() : Text_Based_Test("bn/cmp.vec", "X,Y,R") {}
2✔
220

221
      Test::Result run_one_test(const std::string& op, const VarMap& vars) override {
19✔
222
         Test::Result result("BigInt Comparison " + op);
19✔
223

224
         const BigInt x = vars.get_req_bn("X");
19✔
225
         const BigInt y = vars.get_req_bn("Y");
19✔
226
         const bool expected = vars.get_req_bool("R");
19✔
227

228
         if(op == "EQ") {
19✔
229
            result.confirm("Values equal", x == y, expected);
12✔
230
         } else if(op == "LT") {
13✔
231
            result.confirm("Values LT", x < y, expected);
12✔
232

233
            if(expected) {
6✔
234
               result.confirm("If LT then reverse is GT", y >= x);
6✔
235
            } else {
236
               result.confirm("If not LT then GTE", x >= y);
12✔
237
            }
238
         } else if(op == "LTE") {
7✔
239
            result.confirm("Values LTE", x <= y, expected);
14✔
240

241
            if(expected) {
7✔
242
               result.confirm("If LTE then either LT or EQ", x < y || x == y);
14✔
243
            } else {
244
               result.confirm("If not LTE then GT", x > y);
9✔
245
            }
246
         } else {
247
            throw Test_Error("Unknown BigInt comparison type " + op);
×
248
         }
249

250
         return result;
19✔
251
      }
38✔
252
};
253

254
BOTAN_REGISTER_TEST("math", "bn_cmp", BigInt_Cmp_Test);
255

256
class BigInt_Add_Test final : public Text_Based_Test {
×
257
   public:
258
      BigInt_Add_Test() : Text_Based_Test("bn/add.vec", "In1,In2,Output") {}
2✔
259

260
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
78✔
261
         Test::Result result("BigInt Addition");
78✔
262

263
         using Botan::BigInt;
78✔
264

265
         const BigInt a = vars.get_req_bn("In1");
78✔
266
         const BigInt b = vars.get_req_bn("In2");
78✔
267
         const BigInt c = vars.get_req_bn("Output");
78✔
268

269
         result.test_eq("a + b", a + b, c);
156✔
270
         result.test_eq("b + a", b + a, c);
156✔
271

272
         BigInt e = a;
78✔
273
         e += b;
78✔
274
         result.test_eq("a += b", e, c);
78✔
275

276
         e = b;
78✔
277
         e += a;
78✔
278
         result.test_eq("b += a", e, c);
78✔
279

280
         return result;
78✔
281
      }
312✔
282
};
283

284
BOTAN_REGISTER_TEST("math", "bn_add", BigInt_Add_Test);
285

286
class BigInt_Sub_Test final : public Text_Based_Test {
×
287
   public:
288
      BigInt_Sub_Test() : Text_Based_Test("bn/sub.vec", "In1,In2,Output") {}
2✔
289

290
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
77✔
291
         Test::Result result("BigInt Subtraction");
77✔
292

293
         const BigInt a = vars.get_req_bn("In1");
77✔
294
         const BigInt b = vars.get_req_bn("In2");
77✔
295
         const BigInt c = vars.get_req_bn("Output");
77✔
296

297
         result.test_eq("a - b", a - b, c);
154✔
298

299
         BigInt e = a;
77✔
300
         e -= b;
77✔
301
         result.test_eq("a -= b", e, c);
77✔
302

303
         return result;
77✔
304
      }
308✔
305
};
306

307
BOTAN_REGISTER_TEST("math", "bn_sub", BigInt_Sub_Test);
308

309
class BigInt_Mul_Test final : public Text_Based_Test {
×
310
   public:
311
      BigInt_Mul_Test() : Text_Based_Test("bn/mul.vec", "In1,In2,Output") {}
2✔
312

313
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
104✔
314
         Test::Result result("BigInt Multiply");
104✔
315

316
         const BigInt a = vars.get_req_bn("In1");
104✔
317
         const BigInt b = vars.get_req_bn("In2");
104✔
318
         const BigInt c = vars.get_req_bn("Output");
104✔
319

320
         result.test_eq("a * b", a * b, c);
208✔
321
         result.test_eq("b * a", b * a, c);
208✔
322

323
         BigInt e = a;
104✔
324
         e *= b;
104✔
325
         result.test_eq("a *= b", e, c);
104✔
326

327
         e = b;
104✔
328
         e *= a;
104✔
329
         result.test_eq("b *= a", e, c);
104✔
330

331
         return result;
104✔
332
      }
416✔
333
};
334

335
BOTAN_REGISTER_TEST("math", "bn_mul", BigInt_Mul_Test);
336

337
class BigInt_Sqr_Test final : public Text_Based_Test {
×
338
   public:
339
      BigInt_Sqr_Test() : Text_Based_Test("bn/sqr.vec", "Input,Output") {}
2✔
340

341
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
21✔
342
         Test::Result result("BigInt Square");
21✔
343

344
         const BigInt input = vars.get_req_bn("Input");
21✔
345
         const BigInt output = vars.get_req_bn("Output");
21✔
346

347
         result.test_eq("a * a", input * input, output);
42✔
348
         result.test_eq("sqr(a)", square(input), output);
42✔
349

350
         return result;
21✔
351
      }
42✔
352
};
353

354
BOTAN_REGISTER_TEST("math", "bn_sqr", BigInt_Sqr_Test);
355

356
class BigInt_Div_Test final : public Text_Based_Test {
×
357
   public:
358
      BigInt_Div_Test() : Text_Based_Test("bn/divide.vec", "In1,In2,Output") {}
2✔
359

360
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
783✔
361
         Test::Result result("BigInt Divide");
783✔
362

363
         const BigInt a = vars.get_req_bn("In1");
783✔
364
         const BigInt b = vars.get_req_bn("In2");
783✔
365
         const BigInt c = vars.get_req_bn("Output");
783✔
366

367
         result.test_eq("a / b", a / b, c);
1,566✔
368

369
         BigInt e = a;
783✔
370
         e /= b;
783✔
371
         result.test_eq("a /= b", e, c);
783✔
372

373
         if(b.sig_words() == 1) {
783✔
374
            const Botan::word bw = b.word_at(0);
404✔
375
            result.test_eq("bw ok", Botan::BigInt::from_word(bw), b);
808✔
376

377
            Botan::BigInt ct_q;
404✔
378
            Botan::word ct_r;
404✔
379
            Botan::ct_divide_word(a, bw, ct_q, ct_r);
404✔
380
            result.test_eq("ct_divide_word q", ct_q, c);
404✔
381
            result.test_eq("ct_divide_word r", ct_q * b + ct_r, a);
2,020✔
382
         }
404✔
383

384
         Botan::BigInt ct_q, ct_r;
783✔
385
         Botan::ct_divide(a, b, ct_q, ct_r);
783✔
386
         result.test_eq("ct_divide q", ct_q, c);
783✔
387
         result.test_eq("ct_divide r", ct_q * b + ct_r, a);
2,349✔
388

389
         return result;
783✔
390
      }
4,696✔
391
};
392

393
BOTAN_REGISTER_TEST("math", "bn_div", BigInt_Div_Test);
394

395
class BigInt_Mod_Test final : public Text_Based_Test {
×
396
   public:
397
      BigInt_Mod_Test() : Text_Based_Test("bn/mod.vec", "In1,In2,Output") {}
2✔
398

399
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
76✔
400
         Test::Result result("BigInt Mod");
76✔
401

402
         const BigInt a = vars.get_req_bn("In1");
76✔
403
         const BigInt b = vars.get_req_bn("In2");
76✔
404
         const BigInt expected = vars.get_req_bn("Output");
76✔
405

406
         result.test_eq("a % b", a % b, expected);
152✔
407

408
         BigInt e = a;
76✔
409
         e %= b;
76✔
410
         result.test_eq("a %= b", e, expected);
76✔
411

412
         const Botan::Modular_Reducer mod_b(b);
76✔
413
         result.test_eq("Barrett", mod_b.reduce(a), expected);
152✔
414

415
         // if b fits into a Botan::word test %= operator for words
416
         if(b.sig_words() == 1) {
76✔
417
            const Botan::word b_word = b.word_at(0);
30✔
418

419
            e = a;
30✔
420
            e %= b_word;
30✔
421
            result.test_eq("a %= b (as word)", e, expected);
30✔
422

423
            result.test_eq("a % b (as word)", a % b_word, expected);
60✔
424

425
            Botan::BigInt ct_q;
30✔
426
            Botan::word ct_r;
30✔
427
            Botan::ct_divide_word(a, b.word_at(0), ct_q, ct_r);
60✔
428
            result.test_eq("ct_divide_u8 r", ct_r, expected);
82✔
429
         }
30✔
430

431
         Botan::BigInt ct_q, ct_r;
76✔
432
         Botan::ct_divide(a, b, ct_q, ct_r);
76✔
433
         result.test_eq("ct_divide r", ct_r, expected);
76✔
434

435
         return result;
76✔
436
      }
453✔
437
};
438

439
BOTAN_REGISTER_TEST("math", "bn_mod", BigInt_Mod_Test);
440

441
class BigInt_GCD_Test final : public Text_Based_Test {
×
442
   public:
443
      BigInt_GCD_Test() : Text_Based_Test("bn/gcd.vec", "X,Y,GCD") {}
2✔
444

445
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
181✔
446
         Test::Result result("BigInt GCD");
181✔
447

448
         const BigInt x = vars.get_req_bn("X");
181✔
449
         const BigInt y = vars.get_req_bn("Y");
181✔
450
         const BigInt expected = vars.get_req_bn("GCD");
181✔
451

452
         const BigInt g1 = Botan::gcd(x, y);
181✔
453
         result.test_eq("gcd", g1, expected);
181✔
454

455
         const BigInt g2 = Botan::gcd(y, x);
181✔
456
         result.test_eq("gcd", g2, expected);
181✔
457

458
         return result;
181✔
459
      }
905✔
460
};
461

462
BOTAN_REGISTER_TEST("math", "bn_gcd", BigInt_GCD_Test);
463

464
class BigInt_Jacobi_Test final : public Text_Based_Test {
×
465
   public:
466
      BigInt_Jacobi_Test() : Text_Based_Test("bn/jacobi.vec", "A,N,J") {}
2✔
467

468
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
698✔
469
         Test::Result result("BigInt Jacobi");
698✔
470

471
         const BigInt a = vars.get_req_bn("A");
698✔
472
         const BigInt n = vars.get_req_bn("N");
698✔
473
         const std::string expected = vars.get_req_str("J");
698✔
474

475
         const int32_t j = Botan::jacobi(a, n);
698✔
476

477
         if(j == 0) {
698✔
478
            result.test_eq("jacobi", expected, "0");
314✔
479
         } else if(j == -1) {
541✔
480
            result.test_eq("jacobi", expected, "-1");
614✔
481
         } else {
482
            result.test_eq("jacobi", expected, "1");
468✔
483
         }
484

485
         return result;
698✔
486
      }
2,094✔
487
};
488

489
BOTAN_REGISTER_TEST("math", "bn_jacobi", BigInt_Jacobi_Test);
490

491
class BigInt_Lshift_Test final : public Text_Based_Test {
×
492
   public:
493
      BigInt_Lshift_Test() : Text_Based_Test("bn/lshift.vec", "Value,Shift,Output") {}
3✔
494

495
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
50✔
496
         Test::Result result("BigInt Lshift");
50✔
497

498
         const BigInt value = vars.get_req_bn("Value");
50✔
499
         const size_t shift = vars.get_req_bn("Shift").to_u32bit();
100✔
500
         const BigInt output = vars.get_req_bn("Output");
50✔
501

502
         result.test_eq("a << s", value << shift, output);
100✔
503

504
         BigInt e = value;
50✔
505
         e <<= shift;
50✔
506
         result.test_eq("a <<= s", e, output);
50✔
507

508
         return result;
50✔
509
      }
150✔
510
};
511

512
BOTAN_REGISTER_TEST("math", "bn_lshift", BigInt_Lshift_Test);
513

514
class BigInt_Rshift_Test final : public Text_Based_Test {
×
515
   public:
516
      BigInt_Rshift_Test() : Text_Based_Test("bn/rshift.vec", "Value,Shift,Output") {}
3✔
517

518
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
53✔
519
         Test::Result result("BigInt Rshift");
53✔
520

521
         const BigInt value = vars.get_req_bn("Value");
53✔
522
         const size_t shift = vars.get_req_bn("Shift").to_u32bit();
106✔
523
         const BigInt output = vars.get_req_bn("Output");
53✔
524

525
         result.test_eq("a >> s", value >> shift, output);
106✔
526

527
         BigInt e = value;
53✔
528
         e >>= shift;
53✔
529
         result.test_eq("a >>= s", e, output);
53✔
530

531
         return result;
53✔
532
      }
159✔
533
};
534

535
BOTAN_REGISTER_TEST("math", "bn_rshift", BigInt_Rshift_Test);
536

537
class BigInt_Powmod_Test final : public Text_Based_Test {
×
538
   public:
539
      BigInt_Powmod_Test() : Text_Based_Test("bn/powmod.vec", "Base,Exponent,Modulus,Output") {}
3✔
540

541
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
47✔
542
         Test::Result result("BigInt Powmod");
47✔
543

544
         const BigInt base = vars.get_req_bn("Base");
47✔
545
         const BigInt exponent = vars.get_req_bn("Exponent");
47✔
546
         const BigInt modulus = vars.get_req_bn("Modulus");
47✔
547
         const BigInt expected = vars.get_req_bn("Output");
47✔
548

549
         result.test_eq("power_mod", Botan::power_mod(base, exponent, modulus), expected);
94✔
550
         return result;
47✔
551
      }
188✔
552
};
553

554
BOTAN_REGISTER_TEST("math", "bn_powmod", BigInt_Powmod_Test);
555

556
class BigInt_IsPrime_Test final : public Text_Based_Test {
×
557
   public:
558
      BigInt_IsPrime_Test() : Text_Based_Test("bn/isprime.vec", "X") {}
2✔
559

560
      Test::Result run_one_test(const std::string& header, const VarMap& vars) override {
132✔
561
         if(header != "Prime" && header != "NonPrime") {
132✔
562
            throw Test_Error("Bad header for prime test " + header);
×
563
         }
564

565
         const BigInt value = vars.get_req_bn("X");
132✔
566
         const bool is_prime = (header == "Prime");
132✔
567

568
         Test::Result result("BigInt Test " + header);
132✔
569
         result.test_eq("is_prime", Botan::is_prime(value, Test::rng()), is_prime);
132✔
570

571
         return result;
132✔
572
      }
132✔
573
};
574

575
BOTAN_REGISTER_TEST("math", "bn_isprime", BigInt_IsPrime_Test);
576

577
class BigInt_IsSquare_Test final : public Text_Based_Test {
×
578
   public:
579
      BigInt_IsSquare_Test() : Text_Based_Test("bn/perfect_square.vec", "X,R") {}
2✔
580

581
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
7✔
582
         const BigInt value = vars.get_req_bn("X");
7✔
583
         const BigInt expected = vars.get_req_bn("R");
7✔
584
         const BigInt computed = Botan::is_perfect_square(value);
7✔
585

586
         Test::Result result("BigInt IsSquare");
7✔
587
         result.test_eq("is_perfect_square", computed, expected);
7✔
588
         return result;
7✔
589
      }
21✔
590
};
591

592
BOTAN_REGISTER_TEST("math", "bn_issquare", BigInt_IsSquare_Test);
593

594
class BigInt_Sqrt_Modulo_Prime_Test final : public Text_Based_Test {
×
595
   public:
596
      BigInt_Sqrt_Modulo_Prime_Test() : Text_Based_Test("bn/sqrt_modulo_prime.vec", "Input,Modulus,Output") {}
3✔
597

598
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
17✔
599
         Test::Result result("BigInt Sqrt Modulo Prime");
17✔
600

601
         const Botan::BigInt a = vars.get_req_bn("Input");
17✔
602
         const Botan::BigInt p = vars.get_req_bn("Modulus");
17✔
603
         const Botan::BigInt exp = vars.get_req_bn("Output");
17✔
604

605
         const Botan::BigInt a_sqrt = Botan::sqrt_modulo_prime(a, p);
17✔
606

607
         result.test_eq("sqrt_modulo_prime", a_sqrt, exp);
17✔
608

609
         if(a_sqrt > 1) {
17✔
610
            const Botan::BigInt a_sqrt2 = (a_sqrt * a_sqrt) % p;
8✔
611
            result.test_eq("square correct", a_sqrt2, a);
16✔
612
         }
8✔
613

614
         return result;
17✔
615
      }
68✔
616
};
617

618
BOTAN_REGISTER_TEST("math", "bn_sqrt_modulo_prime", BigInt_Sqrt_Modulo_Prime_Test);
619

620
class BigInt_InvMod_Test final : public Text_Based_Test {
×
621
   public:
622
      BigInt_InvMod_Test() : Text_Based_Test("bn/invmod.vec", "Input,Modulus,Output") {}
3✔
623

624
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
138✔
625
         Test::Result result("BigInt InvMod");
138✔
626

627
         const Botan::BigInt a = vars.get_req_bn("Input");
138✔
628
         const Botan::BigInt mod = vars.get_req_bn("Modulus");
138✔
629
         const Botan::BigInt expected = vars.get_req_bn("Output");
138✔
630

631
         const Botan::BigInt a_inv = Botan::inverse_mod(a, mod);
138✔
632

633
         result.test_eq("inverse_mod", a_inv, expected);
138✔
634

635
         if(a_inv > 1) {
138✔
636
            result.test_eq("inverse ok", (a * a_inv) % mod, 1);
415✔
637
         }
638
         /*
639
         else if((a % mod) > 0)
640
            {
641
            result.confirm("no inverse with gcd > 1", gcd(a, mod) > 1);
642
            }
643
         */
644

645
         return result;
138✔
646
      }
552✔
647
};
648

649
BOTAN_REGISTER_TEST("math", "bn_invmod", BigInt_InvMod_Test);
650

651
class BigInt_Rand_Test final : public Text_Based_Test {
×
652
   public:
653
      BigInt_Rand_Test() : Text_Based_Test("bn/random.vec", "Seed,Min,Max,Output") {}
3✔
654

655
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
3✔
656
         Test::Result result("BigInt Random");
3✔
657

658
         const std::vector<uint8_t> seed = vars.get_req_bin("Seed");
3✔
659
         const Botan::BigInt min = vars.get_req_bn("Min");
3✔
660
         const Botan::BigInt max = vars.get_req_bn("Max");
3✔
661
         const Botan::BigInt expected = vars.get_req_bn("Output");
3✔
662

663
         Fixed_Output_RNG rng(seed);
3✔
664
         Botan::BigInt generated = BigInt::random_integer(rng, min, max);
3✔
665

666
         result.test_eq("random_integer KAT", generated, expected);
3✔
667

668
         return result;
3✔
669
      }
15✔
670
};
671

672
BOTAN_REGISTER_TEST("math", "bn_rand", BigInt_Rand_Test);
673

674
class Lucas_Primality_Test final : public Test {
×
675
   public:
676
      std::vector<Test::Result> run() override {
1✔
677
         const uint32_t lucas_max = (Test::run_long_tests() ? 100000 : 6000);
1✔
678

679
         // OEIS A217120
680
         std::set<uint32_t> lucas_pp{
1✔
681
            323,   377,   1159,  1829,  3827,  5459,  5777,  9071,  9179,  10877, 11419, 11663, 13919, 14839, 16109,
682
            16211, 18407, 18971, 19043, 22499, 23407, 24569, 25199, 25877, 26069, 27323, 32759, 34943, 35207, 39059,
683
            39203, 39689, 40309, 44099, 46979, 47879, 50183, 51983, 53663, 56279, 58519, 60377, 63881, 69509, 72389,
684
            73919, 75077, 77219, 79547, 79799, 82983, 84419, 86063, 90287, 94667, 97019, 97439,
685
         };
1✔
686

687
         Test::Result result("Lucas primality test");
1✔
688

689
         for(uint32_t i = 3; i <= lucas_max; i += 2) {
50,000✔
690
            Botan::Modular_Reducer mod_i(i);
49,999✔
691
            const bool passes_lucas = Botan::is_lucas_probable_prime(i, mod_i);
49,999✔
692
            const bool is_prime = Botan::is_prime(i, Test::rng());
49,999✔
693

694
            const bool is_lucas_pp = (is_prime == false && passes_lucas == true);
49,999✔
695

696
            if(is_lucas_pp) {
49,999✔
697
               result.confirm("Lucas pseudoprime is in list", lucas_pp.count(i) == 1);
228✔
698
            } else {
699
               result.confirm("Lucas non-pseudoprime is not in list", !lucas_pp.contains(i));
199,768✔
700
            }
701
         }
49,999✔
702

703
         return {result};
2✔
704
      }
1✔
705
};
706

707
BOTAN_REGISTER_TEST("math", "bn_lucas", Lucas_Primality_Test);
708

709
class DSA_ParamGen_Test final : public Text_Based_Test {
×
710
   public:
711
      DSA_ParamGen_Test() : Text_Based_Test("bn/dsa_gen.vec", "P,Q,Counter,Seed") {}
3✔
712

713
      Test::Result run_one_test(const std::string& header, const VarMap& vars) override {
20✔
714
         const std::vector<uint8_t> seed = vars.get_req_bin("Seed");
20✔
715
         const size_t offset = vars.get_req_sz("Counter");
20✔
716

717
         const Botan::BigInt exp_P = vars.get_req_bn("P");
20✔
718
         const Botan::BigInt exp_Q = vars.get_req_bn("Q");
20✔
719

720
         const std::vector<std::string> header_parts = Botan::split_on(header, ',');
20✔
721

722
         if(header_parts.size() != 2) {
20✔
723
            throw Test_Error("Unexpected header '" + header + "' in DSA param gen test");
×
724
         }
725

726
         const size_t p_bits = Botan::to_u32bit(header_parts[1]);
20✔
727
         const size_t q_bits = Botan::to_u32bit(header_parts[0]);
20✔
728

729
         Test::Result result("DSA Parameter Generation");
20✔
730

731
         try {
20✔
732
            Botan::BigInt gen_P, gen_Q;
20✔
733
            if(Botan::generate_dsa_primes(Test::rng(), gen_P, gen_Q, p_bits, q_bits, seed, offset)) {
20✔
734
               result.test_eq("P", gen_P, exp_P);
20✔
735
               result.test_eq("Q", gen_Q, exp_Q);
40✔
736
            } else {
737
               result.test_failure("Seed did not generate a DSA parameter");
×
738
            }
739
         } catch(Botan::Lookup_Error&) {}
40✔
740

741
         return result;
40✔
742
      }
80✔
743
};
744

745
BOTAN_REGISTER_TEST("math", "dsa_param", DSA_ParamGen_Test);
746

747
#endif
748

749
}  // namespace
750

751
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc