Botan 3.0.0-alpha0
Crypto and TLS for C&
big_code.cpp
Go to the documentation of this file.
1/*
2* BigInt Encoding/Decoding
3* (C) 1999-2010,2012,2019,2021 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/bigint.h>
9#include <botan/internal/divide.h>
10#include <botan/hex.h>
11
12namespace Botan {
13
14std::string BigInt::to_dec_string() const
15 {
16 // Use the largest power of 10 that fits in a word
17#if (BOTAN_MP_WORD_BITS == 64)
18 const word conversion_radix = 10000000000000000000U;
19 const word radix_digits = 19;
20#else
21 const word conversion_radix = 1000000000U;
22 const word radix_digits = 9;
23#endif
24
25 // (over-)estimate of the number of digits needed; log2(10) ~ 3.3219
26 const size_t digit_estimate = static_cast<size_t>(1 + (this->bits() / 3.32));
27
28 // (over-)estimate of db such that conversion_radix^db > *this
29 const size_t digit_blocks = (digit_estimate + radix_digits - 1) / radix_digits;
30
31 BigInt value = *this;
32 value.set_sign(Positive);
33
34 // Extract groups of digits into words
35 std::vector<word> digit_groups(digit_blocks);
36
37 for(size_t i = 0; i != digit_blocks; ++i)
38 {
39 word remainder = 0;
40 ct_divide_word(value, conversion_radix, value, remainder);
41 digit_groups[i] = remainder;
42 }
43
45
46 // Extract digits from the groups
47 std::vector<uint8_t> digits(digit_blocks * radix_digits);
48
49 for(size_t i = 0; i != digit_blocks; ++i)
50 {
51 word remainder = digit_groups[i];
52 for(size_t j = 0; j != radix_digits; ++j)
53 {
54 // Compiler should convert div/mod by 10 into mul by magic constant
55 const word digit = remainder % 10;
56 remainder /= 10;
57 digits[radix_digits*i + j] = static_cast<uint8_t>(digit);
58 }
59 }
60
61 // remove leading zeros
62 while(!digits.empty() && digits.back() == 0)
63 {
64 digits.pop_back();
65 }
66
67 BOTAN_ASSERT_NOMSG(digit_estimate >= digits.size());
68
69 // Reverse the digits to big-endian and format to text
70 std::string s;
71 s.reserve(1 + digits.size());
72
73 if(is_negative())
74 s += "-";
75
76 // Reverse and convert to textual digits
77 for(auto i = digits.rbegin(); i != digits.rend(); ++i)
78 {
79 s.push_back(*i + '0'); // assumes ASCII
80 }
81
82 if(s.empty())
83 s += "0";
84
85 return s;
86 }
87
88std::string BigInt::to_hex_string() const
89 {
90 std::vector<uint8_t> bits = BigInt::encode(*this);
91
92 if(bits.empty())
93 bits.push_back(0);
94
95 std::string hrep;
96 if(is_negative())
97 hrep += "-";
98 hrep += "0x";
99 hrep += hex_encode(bits);
100 return hrep;
101 }
102
103/*
104* Encode a BigInt, with leading 0s if needed
105*/
107 {
108 if(n.bytes() > bytes)
109 throw Encoding_Error("encode_1363: n is too large to encode properly");
110
112 n.binary_encode(output.data(), output.size());
113 return output;
114 }
115
116//static
117void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n)
118 {
119 if(n.bytes() > bytes)
120 throw Encoding_Error("encode_1363: n is too large to encode properly");
121
122 n.binary_encode(output, bytes);
123 }
124
125/*
126* Encode two BigInt, with leading 0s if needed, and concatenate
127*/
129 {
130 if(n1.is_negative() || n2.is_negative())
131 throw Encoding_Error("encode_fixed_length_int_pair: values must be positive");
132 if(n1.bytes() > bytes || n2.bytes() > bytes)
133 throw Encoding_Error("encode_fixed_length_int_pair: values too large to encode properly");
134 secure_vector<uint8_t> output(2 * bytes);
135 n1.binary_encode(output.data() , bytes);
136 n2.binary_encode(output.data() + bytes, bytes);
137 return output;
138 }
139
140/*
141* Decode a BigInt
142*/
143BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base)
144 {
145 BigInt r;
146 if(base == Binary)
147 {
148 r.binary_decode(buf, length);
149 }
150 else if(base == Hexadecimal)
151 {
153
154 if(length % 2)
155 {
156 // Handle lack of leading 0
157 const char buf0_with_leading_0[2] =
158 { '0', static_cast<char>(buf[0]) };
159
160 binary = hex_decode_locked(buf0_with_leading_0, 2);
161
162 binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]),
163 length - 1,
164 false);
165 }
166 else
168 length, false);
169
170 r.binary_decode(binary.data(), binary.size());
171 }
172 else if(base == Decimal)
173 {
174 // This could be made faster using the same trick as to_dec_string
175 for(size_t i = 0; i != length; ++i)
176 {
177 const char c = buf[i];
178
179 if(c < '0' || c > '9')
180 throw Invalid_Argument("BigInt::decode: invalid decimal char");
181
182 const uint8_t x = c - '0';
183 BOTAN_ASSERT_NOMSG(x < 10);
184
185 r *= 10;
186 r += x;
187 }
188 }
189 else
190 throw Invalid_Argument("Unknown BigInt decoding method");
191 return r;
192 }
193
194}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
void binary_decode(const uint8_t buf[], size_t length)
Definition: bigint.cpp:428
static BigInt decode(const uint8_t buf[], size_t length)
Definition: bigint.h:790
@ Hexadecimal
Definition: bigint.h:30
std::string to_dec_string() const
Definition: big_code.cpp:14
void binary_encode(uint8_t buf[]) const
Definition: bigint.cpp:395
std::string to_hex_string() const
Definition: big_code.cpp:88
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:128
size_t bits() const
Definition: bigint.cpp:309
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:765
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:106
bool is_zero() const
Definition: bigint.h:430
bool is_negative() const
Definition: bigint.h:541
size_t bytes() const
Definition: bigint.cpp:294
void set_sign(Sign sign)
Definition: bigint.h:577
Definition: alg_id.cpp:13
secure_vector< uint8_t > hex_decode_locked(const char input[], size_t input_length, bool ignore_ws)
Definition: hex.cpp:168
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:31
void ct_divide_word(const BigInt &x, word y, BigInt &q_out, word &r_out)
Definition: divide.cpp:84
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:188
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65