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
15namespace Botan {
16
17/*
18* Construct a BigInt from a regular number
19*/
21 {
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*/
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*/
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);
60 }
61 }
62
63/*
64* Construct a BigInt from a string
65*/
66BigInt::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*/
89BigInt::BigInt(const byte input[], size_t length, Base base)
90 {
92 *this = decode(input, length, base);
93 }
94
95/*
96* Construct a BigInt from an encoded BigInt
97*/
99 {
101 randomize(rng, bits);
102 }
103
104/*
105* Swap this BigInt with another
106*/
108 {
109 reg.swap(other.reg);
110 std::swap(signedness, other.signedness);
111 }
112
113/*
114* Grow the internal storage
115*/
116void 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*/
124void 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*/
133s32bit 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*/
148byte 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*/
161bool 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*/
169u32bit 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*/
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*/
206void 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*/
217void 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*/
228void 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*/
246size_t BigInt::bytes() const
247 {
248 return (bits() + 7) / 8;
249 }
250
251/*
252* Count how many bits are being used
253*/
254size_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*/
273size_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*/
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*/
304 {
306 }
307
308/*
309* Return the opposite value of the current sign
310*/
312 {
313 if(sign() == Positive)
314 return Negative;
315 return Positive;
316 }
317
318/*
319* Return the negation of this number
320*/
322 {
323 BigInt x = (*this);
324 x.flip_sign();
325 return x;
326 }
327
328/*
329* Return the absolute value of this number
330*/
332 {
333 BigInt x = (*this);
335 return x;
336 }
337
338/*
339* Encode this number into bytes
340*/
341void 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*/
351void 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*/
373 {
374 binary_decode(buf, buf.size());
375 }
376
378 {
379 reg.resize(sig_words());
380 }
381
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}
void swap(BigInt &other)
Definition bigint.cpp:107
u32bit to_u32bit() const
Definition bigint.cpp:190
size_t sig_words() const
Definition bigint.h:290
static BigInt decode(const byte buf[], size_t length, Base base=Binary)
Definition big_code.cpp:102
void shrink_to_fit()
Definition bigint.cpp:377
void binary_encode(byte buf[]) const
Definition bigint.cpp:341
size_t size() const
Definition bigint.h:284
void flip_sign()
Definition bigint.cpp:303
const word * data() const
Definition bigint.h:317
word word_at(size_t n) const
Definition bigint.h:238
void set_bit(size_t n)
Definition bigint.cpp:206
void mask_bits(size_t n)
Definition bigint.cpp:228
s32bit cmp(const BigInt &n, bool check_signs=true) const
Definition bigint.cpp:133
size_t bits() const
Definition bigint.cpp:254
BigInt operator-() const
Definition bigint.cpp:321
void clear()
Definition bigint.h:143
void clear_bit(size_t n)
Definition bigint.cpp:217
void randomize(RandomNumberGenerator &rng, size_t bitsize=0)
Definition big_rand.cpp:29
Sign sign() const
Definition bigint.h:257
byte byte_at(size_t n) const
Definition bigint.cpp:148
BigInt abs() const
Definition bigint.cpp:331
size_t encoded_size(Base base=Binary) const
Definition bigint.cpp:273
void binary_decode(const byte buf[], size_t length)
Definition bigint.cpp:351
static void const_time_lookup(SecureVector< word > &output, const std::vector< BigInt > &vec, size_t idx)
Definition bigint.cpp:382
bool is_zero() const
Definition bigint.h:176
u32bit get_substring(size_t offset, size_t length) const
Definition bigint.cpp:169
bool is_negative() const
Definition bigint.h:245
size_t bytes() const
Definition bigint.cpp:246
void grow_reg(size_t n)
Definition bigint.cpp:116
bool is_positive() const
Definition bigint.h:251
bool get_bit(size_t n) const
Definition bigint.cpp:161
void grow_to(size_t n)
Definition bigint.cpp:124
Sign reverse_sign() const
Definition bigint.cpp:311
void set_sign(Sign sign)
Definition bigint.cpp:292
size_t size() const
Definition secmem.h:29
T is_equal(T x, T y)
Definition ct_utils.h:63
T select(T mask, T from0, T from1)
Definition ct_utils.h:45
const word MP_WORD_MASK
Definition mp_types.h:27
signed int s32bit
Definition types.h:37
T round_up(T n, T align_to)
Definition rounding.h:22
s32bit bigint_cmp(const word x[], size_t x_size, const word y[], size_t y_size)
Definition mp_misc.cpp:41
byte get_byte(size_t byte_num, T input)
Definition get_byte.h:21
const word MP_WORD_TOP_BIT
Definition mp_types.h:28
unsigned long long u64bit
Definition types.h:49
const size_t MP_WORD_BITS
Definition mp_core.h:18
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
unsigned int u32bit
Definition types.h:32
void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:32
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
Definition secmem.h:438
Encoding_Error(const std::string &name)
Definition exceptn.h:131