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

randombit / botan / 12869303872

20 Jan 2025 01:40PM UTC coverage: 91.213% (+0.01%) from 91.202%
12869303872

push

github

web-flow
Merge pull request #4569 from randombit/jack/mod-inv-distinguish-cases

When computing modular inverses distingush which case we are in

93546 of 102558 relevant lines covered (91.21%)

11542300.02 hits per line

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

95.58
/src/cli/math.cpp
1
/*
2
* (C) 2009,2010,2015 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "cli.h"
8

9
#if defined(BOTAN_HAS_NUMBERTHEORY)
10

11
   #include <botan/numthry.h>
12
   #include <botan/internal/mod_inv.h>
13
   #include <botan/internal/monty.h>
14
   #include <iterator>
15

16
namespace Botan_CLI {
17

18
class Modular_Inverse final : public Command {
19
   public:
20
      Modular_Inverse() : Command("mod_inverse n mod") {}
6✔
21

22
      std::string group() const override { return "numtheory"; }
1✔
23

24
      std::string description() const override { return "Calculates a modular inverse"; }
1✔
25

26
      void go() override {
2✔
27
         const Botan::BigInt n(get_arg("n"));
4✔
28
         const Botan::BigInt mod(get_arg("mod"));
4✔
29

30
         if(auto inv = Botan::inverse_mod_general(n, mod)) {
2✔
31
            output() << *inv << "\n";
1✔
32
         } else {
33
            output() << "No modular inverse exists\n";
1✔
34
         }
2✔
35
      }
4✔
36
};
37

38
BOTAN_REGISTER_COMMAND("mod_inverse", Modular_Inverse);
3✔
39

40
class Gen_Prime final : public Command {
41
   public:
42
      Gen_Prime() : Command("gen_prime --hex --count=1 bits") {}
6✔
43

44
      std::string group() const override { return "numtheory"; }
1✔
45

46
      std::string description() const override { return "Samples one or more primes"; }
1✔
47

48
      void go() override {
2✔
49
         const size_t bits = get_arg_sz("bits");
2✔
50
         const size_t cnt = get_arg_sz("count");
2✔
51
         const bool hex = flag_set("hex");
2✔
52

53
         for(size_t i = 0; i != cnt; ++i) {
4✔
54
            const Botan::BigInt p = Botan::random_prime(rng(), bits);
2✔
55

56
            if(hex) {
2✔
57
               output() << "0x" << std::hex << p << "\n";
×
58
            } else {
59
               output() << p << "\n";
2✔
60
            }
61
         }
2✔
62
      }
2✔
63
};
64

65
BOTAN_REGISTER_COMMAND("gen_prime", Gen_Prime);
3✔
66

67
class Is_Prime final : public Command {
68
   public:
69
      Is_Prime() : Command("is_prime --prob=56 n") {}
8✔
70

71
      std::string group() const override { return "numtheory"; }
1✔
72

73
      std::string description() const override { return "Test if the integer n is composite or prime"; }
1✔
74

75
      void go() override {
3✔
76
         Botan::BigInt n(get_arg("n"));
6✔
77
         const size_t prob = get_arg_sz("prob");
3✔
78
         const bool prime = Botan::is_prime(n, rng(), prob);
3✔
79

80
         output() << n << " is " << (prime ? "probably prime" : "composite") << "\n";
4✔
81
      }
3✔
82
};
83

84
BOTAN_REGISTER_COMMAND("is_prime", Is_Prime);
4✔
85

86
/*
87
* Factor integers using a combination of trial division by small
88
* primes, and Pollard's Rho algorithm
89
*/
90
class Factor final : public Command {
91
   public:
92
      Factor() : Command("factor n") {}
8✔
93

94
      std::string group() const override { return "numtheory"; }
1✔
95

96
      std::string description() const override { return "Factor a given integer"; }
1✔
97

98
      void go() override {
3✔
99
         Botan::BigInt n(get_arg("n"));
6✔
100

101
         std::vector<Botan::BigInt> factors = factorize(n, rng());
3✔
102
         std::sort(factors.begin(), factors.end());
3✔
103

104
         output() << n << ":";
3✔
105
         for(const auto& factor : factors) {
8✔
106
            output() << " " << factor;
5✔
107
         }
108
         output() << "\n";
3✔
109
      }
6✔
110

111
   private:
112
      std::vector<Botan::BigInt> factorize(const Botan::BigInt& n_in, Botan::RandomNumberGenerator& rng) {
4✔
113
         Botan::BigInt n = n_in;
4✔
114
         std::vector<Botan::BigInt> factors = remove_small_factors(n);
4✔
115

116
         while(n != 1) {
5✔
117
            if(Botan::is_prime(n, rng)) {
4✔
118
               factors.push_back(n);
3✔
119
               break;
3✔
120
            }
121

122
            Botan::BigInt a_factor = 0;
1✔
123
            while(a_factor == 0) {
2✔
124
               a_factor = rho(n, rng);
1✔
125
            }
126

127
            const auto rho_factored = factorize(a_factor, rng);
1✔
128
            for(const auto& factor : rho_factored) {
2✔
129
               factors.push_back(factor);
1✔
130
            }
131

132
            n /= a_factor;
1✔
133
         }
2✔
134

135
         return factors;
4✔
136
      }
4✔
137

138
      /*
139
      * Pollard's Rho algorithm, as described in the MIT algorithms book.
140
      * Uses Brent's cycle finding
141
      */
142
      static Botan::BigInt rho(const Botan::BigInt& n, Botan::RandomNumberGenerator& rng) {
1✔
143
         auto monty_n = std::make_shared<Botan::Montgomery_Params>(n);
1✔
144

145
         const Botan::Montgomery_Int one(monty_n, monty_n->R1(), false);
1✔
146

147
         Botan::Montgomery_Int x(monty_n, Botan::BigInt::random_integer(rng, 2, n - 3), false);
5✔
148
         Botan::Montgomery_Int y = x;
1✔
149
         Botan::Montgomery_Int z = one;
1✔
150
         Botan::Montgomery_Int t(monty_n);
1✔
151
         Botan::BigInt d;
1✔
152

153
         Botan::secure_vector<Botan::word> ws;
1✔
154

155
         size_t i = 1, k = 2;
1✔
156

157
         while(true) {
147,199✔
158
            i++;
147,199✔
159

160
            if(i >= 0xFFFF0000)  // bad seed? too slow? bail out
147,199✔
161
            {
162
               break;
163
            }
164

165
            x.square_this(ws);  // x = x^2
147,199✔
166
            x.add(one, ws);
147,199✔
167

168
            t = y;
147,199✔
169
            t.sub(x, ws);
147,199✔
170

171
            z.mul_by(t, ws);
147,199✔
172

173
            if(i == k || i % 128 == 0) {
147,199✔
174
               d = Botan::gcd(z.value(), n);
2,311✔
175
               z = one;
1,156✔
176

177
               if(d == n) {
1,156✔
178
                  // TODO Should rewind here
179
                  break;
180
               }
181

182
               if(d != 1) {
1,156✔
183
                  return d;
1✔
184
               }
185
            }
186

187
            if(i == k) {
147,198✔
188
               y = x;
17✔
189
               k = 2 * k;
17✔
190
            }
191
         }
192

193
         // failed
194
         return 0;
×
195
      }
2✔
196

197
      // Remove (and return) any small (< 2^16) factors
198
      static std::vector<Botan::BigInt> remove_small_factors(Botan::BigInt& n) {
4✔
199
         std::vector<Botan::BigInt> factors;
4✔
200

201
         while(n.is_even()) {
8✔
202
            factors.push_back(2);
×
203
            n /= 2;
×
204
         }
205

206
         for(size_t j = 0; j != Botan::PRIME_TABLE_SIZE; j++) {
19,651✔
207
            uint16_t prime = Botan::PRIMES[j];
19,648✔
208
            if(n < prime) {
19,648✔
209
               break;
210
            }
211

212
            Botan::BigInt x = Botan::gcd(n, prime);
19,647✔
213

214
            if(x != 1) {
19,647✔
215
               n /= x;
2✔
216

217
               while(x != 1) {
4✔
218
                  x /= prime;
2✔
219
                  factors.push_back(prime);
4✔
220
               }
221
            }
222
         }
19,647✔
223

224
         return factors;
4✔
225
      }
×
226
};
227

228
BOTAN_REGISTER_COMMAND("factor", Factor);
4✔
229

230
}  // namespace Botan_CLI
231

232
#endif
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

© 2026 Coveralls, Inc