Botan: src/math/bigint/bigint.cpp Source File

Botan 1.10.17

bigint.cpp
Go to the documentation of this file.
1 /*
2 * BigInt Base
3 * (C) 1999-2011 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7
8 #include <botan/bigint.h>
9 #include <botan/internal/mp_core.h>
10 #include <botan/get_byte.h>
11 #include <botan/parsing.h>
12 #include <botan/internal/rounding.h>
13 #include <botan/internal/ct_utils.h>
14
15 namespace Botan {
16
17 /*
18 * Construct a BigInt from a regular number
19 */
20 BigInt::BigInt(u64bit n)
21 {
22 set_sign(Positive);
23
24 if(n == 0)
25 return;
26
27 const size_t limbs_needed = sizeof(u64bit) / sizeof(word);
28
29 reg.resize(4*limbs_needed);
30 for(size_t i = 0; i != limbs_needed; ++i)
31 reg[i] = ((n >> (i*MP_WORD_BITS)) & MP_WORD_MASK);
32 }
33
34 /*
35 * Construct a BigInt of the specified size
36 */
37 BigInt::BigInt(Sign s, size_t size)
38 {
39 reg.resize(round_up<size_t>(size, 8));
40 signedness = s;
41 }
42
43 /*
44 * Construct a BigInt from a "raw" BigInt
45 */
46 BigInt::BigInt(const BigInt& b)
47 {
48 const size_t b_words = b.sig_words();
49
50 if(b_words)
51 {
52 reg.resize(round_up<size_t>(b_words, 8));
53 reg.copy(b.data(), b_words);
54 set_sign(b.sign());
55 }
56 else
57 {
58 reg.resize(2);
59 set_sign(Positive);
60 }
61 }
62
63 /*
64 * Construct a BigInt from a string
65 */
66 BigInt::BigInt(const std::string& str)
67 {
68 Base base = Decimal;
69 size_t markers = 0;
70 bool negative = false;
71 if(str.length() > 0 && str[0] == '-') { markers += 1; negative = true; }
72
73 if(str.length() > markers + 2 && str[markers ] == '0' &&
74 str[markers + 1] == 'x')
75 { markers += 2; base = Hexadecimal; }
76 else if(str.length() > markers + 1 && str[markers] == '0')
77 { markers += 1; base = Octal; }
78
79 *this = decode(reinterpret_cast<const byte*>(str.data()) + markers,
80 str.length() - markers, base);
81
82 if(negative) set_sign(Negative);
83 else set_sign(Positive);
84 }
85
86 /*
87 * Construct a BigInt from an encoded BigInt
88 */
89 BigInt::BigInt(const byte input[], size_t length, Base base)
90 {
91 set_sign(Positive);
92 *this = decode(input, length, base);
93 }
94
95 /*
96 * Construct a BigInt from an encoded BigInt
97 */
98 BigInt::BigInt(RandomNumberGenerator& rng, size_t bits)
99 {
100 set_sign(Positive);
101 randomize(rng, bits);
102 }
103
104 /*
105 * Swap this BigInt with another
106 */
107 void BigInt::swap(BigInt& other)
108 {
109 reg.swap(other.reg);
110 std::swap(signedness, other.signedness);
111 }
112
113 /*
114 * Grow the internal storage
115 */
116 void BigInt::grow_reg(size_t n)
117 {
118 reg.resize(round_up<size_t>(size() + n, 8));
119 }
120
121 /*
122 * Grow the internal storage
123 */
124 void BigInt::grow_to(size_t n)
125 {
126 if(n > size())
127 reg.resize(round_up<size_t>(n, 8));
128 }
129
130 /*
131 * Comparison Function
132 */
133 s32bit BigInt::cmp(const BigInt& n, bool check_signs) const
134 {
135 if(check_signs)
136 {
137 if(n.is_positive() && this->is_negative()) return -1;
138 if(n.is_negative() && this->is_positive()) return 1;
139 if(n.is_negative() && this->is_negative())
140 return (-bigint_cmp(data(), sig_words(), n.data(), n.sig_words()));
141 }
142 return bigint_cmp(data(), sig_words(), n.data(), n.sig_words());
143 }
144
145 /*
146 * Return byte n of this number
147 */
148 byte BigInt::byte_at(size_t n) const
149 {
150 const size_t WORD_BYTES = sizeof(word);
151 size_t word_num = n / WORD_BYTES, byte_num = n % WORD_BYTES;
152 if(word_num >= size())
153 return 0;
154 else
155 return get_byte(WORD_BYTES - byte_num - 1, reg[word_num]);
156 }
157
158 /*
159 * Return bit n of this number
160 */
161 bool BigInt::get_bit(size_t n) const
162 {
163 return ((word_at(n / MP_WORD_BITS) >> (n % MP_WORD_BITS)) & 1);
164 }
165
166 /*
167 * Return bits {offset...offset+length}
168 */
169 u32bit BigInt::get_substring(size_t offset, size_t length) const
170 {
171 if(length > 32)
172 throw Invalid_Argument("BigInt::get_substring: Substring size too big");
173
174 u64bit piece = 0;
175 for(size_t i = 0; i != 8; ++i)
176 {
177 const byte part = byte_at((offset / 8) + (7-i));
178 piece = (piece << 8) | part;
179 }
180
181 const u64bit mask = (static_cast<u64bit>(1) << length) - 1;
182 const size_t shift = (offset % 8);
183
184 return static_cast<u32bit>((piece >> shift) & mask);
185 }
186
187 /*
188 * Convert this number to a u32bit, if possible
189 */
190 u32bit BigInt::to_u32bit() const
191 {
192 if(is_negative())
193 throw Encoding_Error("BigInt::to_u32bit: Number is negative");
194 if(bits() > 32)
195 throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");
196
197 u32bit out = 0;
198 for(u32bit j = 0; j != 4; ++j)
199 out = (out << 8) | byte_at(3-j);
200 return out;
201 }
202
203 /*
204 * Set bit number n
205 */
206 void BigInt::set_bit(size_t n)
207 {
208 const size_t which = n / MP_WORD_BITS;
209 const word mask = static_cast<word>(1) << (n % MP_WORD_BITS);
210 if(which >= size()) grow_to(which + 1);
211 reg[which] |= mask;
212 }
213
214 /*
215 * Clear bit number n
216 */
217 void BigInt::clear_bit(size_t n)
218 {
219 const size_t which = n / MP_WORD_BITS;
220 const word mask = static_cast<word>(1) << (n % MP_WORD_BITS);
221 if(which < size())
222 reg[which] &= ~mask;
223 }
224
225 /*
226 * Clear all but the lowest n bits
227 */
228 void BigInt::mask_bits(size_t n)
229 {
230 if(n == 0) { clear(); return; }
231 if(n >= bits()) return;
232
233 const size_t top_word = n / MP_WORD_BITS;
234 const word mask = (static_cast<word>(1) << (n % MP_WORD_BITS)) - 1;
235
236 if(top_word < size())
237 for(size_t i = top_word + 1; i != size(); ++i)
238 reg[i] = 0;
239
240 reg[top_word] &= mask;
241 }
242
243 /*
244 * Count how many bytes are being used
245 */
246 size_t BigInt::bytes() const
247 {
248 return (bits() + 7) / 8;
249 }
250
251 /*
252 * Count how many bits are being used
253 */
254 size_t BigInt::bits() const
255 {
256 const size_t words = sig_words();
257
258 if(words == 0)
259 return 0;
260
261 size_t full_words = words - 1, top_bits = MP_WORD_BITS;
262 word top_word = word_at(full_words), mask = MP_WORD_TOP_BIT;
263
264 while(top_bits && ((top_word & mask) == 0))
265 { mask >>= 1; top_bits--; }
266
267 return (full_words * MP_WORD_BITS + top_bits);
268 }
269
270 /*
271 * Calcluate the size in a certain base
272 */
273 size_t BigInt::encoded_size(Base base) const
274 {
275 static const double LOG_2_BASE_10 = 0.30102999566;
276
277 if(base == Binary)
278 return bytes();
279 else if(base == Hexadecimal)
280 return 2*bytes();
281 else if(base == Octal)
282 return ((bits() + 2) / 3);
283 else if(base == Decimal)
284 return static_cast<size_t>((bits() * LOG_2_BASE_10) + 1);
285 else
286 throw Invalid_Argument("Unknown base for BigInt encoding");
287 }
288
289 /*
290 * Set the sign
291 */
292 void BigInt::set_sign(Sign s)
293 {
294 if(is_zero())
295 signedness = Positive;
296 else
297 signedness = s;
298 }
299
300 /*
301 * Reverse the value of the sign flag
302 */
303 void BigInt::flip_sign()
304 {
305 set_sign(reverse_sign());
306 }
307
308 /*
309 * Return the opposite value of the current sign
310 */
311 BigInt::Sign BigInt::reverse_sign() const
312 {
313 if(sign() == Positive)
314 return Negative;
315 return Positive;
316 }
317
318 /*
319 * Return the negation of this number
320 */
321 BigInt BigInt::operator-() const
322 {
323 BigInt x = (*this);
324 x.flip_sign();
325 return x;
326 }
327
328 /*
329 * Return the absolute value of this number
330 */
331 BigInt BigInt::abs() const
332 {
333 BigInt x = (*this);
334 x.set_sign(Positive);
335 return x;
336 }
337
338 /*
339 * Encode this number into bytes
340 */
341 void BigInt::binary_encode(byte output[]) const
342 {
343 const size_t sig_bytes = bytes();
344 for(size_t i = 0; i != sig_bytes; ++i)
345 output[sig_bytes-i-1] = byte_at(i);
346 }
347
348 /*
349 * Set this number to the value in buf
350 */
351 void BigInt::binary_decode(const byte buf[], size_t length)
352 {
353 const size_t WORD_BYTES = sizeof(word);
354
355 clear();
356 reg.resize(round_up<size_t>((length / WORD_BYTES) + 1, 8));
357
358 for(size_t i = 0; i != length / WORD_BYTES; ++i)
359 {
360 const size_t top = length - WORD_BYTES*i;
361 for(size_t j = WORD_BYTES; j > 0; --j)
362 reg[i] = (reg[i] << 8) | buf[top - j];
363 }
364
365 for(size_t i = 0; i != length % WORD_BYTES; ++i)
366 reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) | buf[i];
367 }
368
369 /*
370 * Set this number to the value in buf
371 */
372 void BigInt::binary_decode(const MemoryRegion<byte>& buf)
373 {
374 binary_decode(buf, buf.size());
375 }
376
377 void BigInt::shrink_to_fit()
378 {
379 reg.resize(sig_words());
380 }
381
382 void BigInt::const_time_lookup(SecureVector<word>& output,
383 const std::vector<BigInt>& vec,
384 size_t idx)
385 {
386 const size_t words = output.size();
387
388 clear_mem(output.data(), output.size());
389
390 for(size_t i = 0; i != vec.size(); ++i)
391 {
392 for(size_t w = 0; w != words; ++w)
393 output[w] |= CT::select<word>(CT::is_equal(i, idx), vec[i].word_at(w), 0);
394 }
395 }
396
397
398 }
Botan::BigInt::get_bit
bool get_bit(size_t n) const
Definition: bigint.cpp:161
Botan::BigInt::reverse_sign
Sign reverse_sign() const
Definition: bigint.cpp:311
Botan::MemoryRegion::resize
void resize(size_t n)
Definition: secmem.h:217
Botan::BigInt::is_negative
bool is_negative() const
Definition: bigint.h:245
Botan::BigInt::Hexadecimal
Definition: bigint.h:28
Botan::BigInt
Definition: bigint.h:22
Botan::BigInt::Positive
Definition: bigint.h:33
Botan::BigInt::cmp
s32bit cmp(const BigInt &n, bool check_signs=true) const
Definition: bigint.cpp:133
Botan::BigInt::Decimal
Definition: bigint.h:28
Botan::RandomNumberGenerator
Definition: rng.h:20
Botan::BigInt::bits
size_t bits() const
Definition: bigint.cpp:254
Botan::BigInt::binary_decode
void binary_decode(const byte buf[], size_t length)
Definition: bigint.cpp:351
Botan::BigInt::get_substring
u32bit get_substring(size_t offset, size_t length) const
Definition: bigint.cpp:169
Botan::clear_mem
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:32
Botan::MemoryRegion::data
T * data()
Definition: secmem.h:53
Botan::BigInt::set_bit
void set_bit(size_t n)
Definition: bigint.cpp:206
Botan::BigInt::sign
Sign sign() const
Definition: bigint.h:257
Botan::BigInt::is_zero
bool is_zero() const
Definition: bigint.h:176
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::BigInt::swap
void swap(BigInt &other)
Definition: bigint.cpp:107
Botan::get_byte
byte get_byte(size_t byte_num, T input)
Definition: get_byte.h:21
Botan::BigInt::word_at
word word_at(size_t n) const
Definition: bigint.h:238
Botan::BigInt::mask_bits
void mask_bits(size_t n)
Definition: bigint.cpp:228
Botan::BigInt::operator-
BigInt operator-() const
Definition: bigint.cpp:321
Botan::CT::is_equal
T is_equal(T x, T y)
Definition: ct_utils.h:63
Botan::MemoryRegion::copy
void copy(const T in[], size_t n)
Definition: secmem.h:126
Botan::BigInt::data
const word * data() const
Definition: bigint.h:317
Botan::s32bit
signed int s32bit
Definition: types.h:37
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::BigInt::Negative
Definition: bigint.h:33
Botan::u64bit
unsigned long long u64bit
Definition: types.h:49
Botan::BigInt::grow_reg
void grow_reg(size_t n)
Definition: bigint.cpp:116
Botan::BigInt::randomize
void randomize(RandomNumberGenerator &rng, size_t bitsize=0)
Definition: big_rand.cpp:29
Botan::BigInt::binary_encode
void binary_encode(byte buf[]) const
Definition: bigint.cpp:341
Botan::BigInt::Octal
Definition: bigint.h:28
Botan::BigInt::Sign
Sign
Definition: bigint.h:33
Botan::BigInt::size
size_t size() const
Definition: bigint.h:284
Botan::MemoryRegion< byte >
Botan
Definition: algo_base.h:14
Botan::BigInt::sig_words
size_t sig_words() const
Definition: bigint.h:290
Botan::BigInt::bytes
size_t bytes() const
Definition: bigint.cpp:246
Botan::BigInt::Binary
Definition: bigint.h:28
Botan::BigInt::byte_at
byte byte_at(size_t n) const
Definition: bigint.cpp:148
Botan::BigInt::clear
void clear()
Definition: bigint.h:143
Botan::MP_WORD_MASK
const word MP_WORD_MASK
Definition: mp_types.h:27
Botan::BigInt::Base
Base
Definition: bigint.h:28
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::MemoryRegion::swap
void swap(MemoryRegion< T > &other)
Definition: secmem.h:260
Botan::BigInt::grow_to
void grow_to(size_t n)
Definition: bigint.cpp:124
Botan::BigInt::encoded_size
size_t encoded_size(Base base=Binary) const
Definition: bigint.cpp:273
Botan::BigInt::abs
BigInt abs() const
Definition: bigint.cpp:331
Botan::BigInt::decode
static BigInt decode(const byte buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:102
Botan::BigInt::BigInt
BigInt()
Definition: bigint.h:446
Botan::SecureVector< word >
Botan::BigInt::const_time_lookup
static void const_time_lookup(SecureVector< word > &output, const std::vector< BigInt > &vec, size_t idx)
Definition: bigint.cpp:382
std::swap
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
Definition: secmem.h:438
Botan::BigInt::shrink_to_fit
void shrink_to_fit()
Definition: bigint.cpp:377
Botan::BigInt::flip_sign
void flip_sign()
Definition: bigint.cpp:303
Botan::BigInt::clear_bit
void clear_bit(size_t n)
Definition: bigint.cpp:217
Botan::BigInt::set_sign
void set_sign(Sign sign)
Definition: bigint.cpp:292
Botan::MP_WORD_TOP_BIT
const word MP_WORD_TOP_BIT
Definition: mp_types.h:28
Botan::Encoding_Error
Definition: exceptn.h:129
Botan::bigint_cmp
s32bit bigint_cmp(const word x[], size_t x_size, const word y[], size_t y_size)
Definition: mp_misc.cpp:41
Botan::BigInt::is_positive
bool is_positive() const
Definition: bigint.h:251
Botan::u32bit
unsigned int u32bit
Definition: types.h:32
Botan::MP_WORD_BITS
const size_t MP_WORD_BITS
Definition: mp_core.h:18
Botan::BigInt::to_u32bit
u32bit to_u32bit() const
Definition: bigint.cpp:190