/src/botan/src/lib/math/bigint/big_code.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * BigInt Encoding/Decoding |
3 | | * (C) 1999-2010,2012,2019 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/divide.h> |
10 | | #include <botan/charset.h> |
11 | | #include <botan/hex.h> |
12 | | |
13 | | namespace Botan { |
14 | | |
15 | | std::string BigInt::to_dec_string() const |
16 | 0 | { |
17 | 0 | BigInt copy = *this; |
18 | 0 | copy.set_sign(Positive); |
19 | 0 |
|
20 | 0 | uint8_t remainder; |
21 | 0 | std::vector<uint8_t> digits; |
22 | 0 |
|
23 | 0 | while(copy > 0) |
24 | 0 | { |
25 | 0 | ct_divide_u8(copy, 10, copy, remainder); |
26 | 0 | digits.push_back(remainder); |
27 | 0 | } |
28 | 0 |
|
29 | 0 | std::string s; |
30 | 0 |
|
31 | 0 | for(auto i = digits.rbegin(); i != digits.rend(); ++i) |
32 | 0 | { |
33 | 0 | s.push_back(Charset::digit2char(*i)); |
34 | 0 | } |
35 | 0 |
|
36 | 0 | if(s.empty()) |
37 | 0 | s += "0"; |
38 | 0 |
|
39 | 0 | return s; |
40 | 0 | } |
41 | | |
42 | | std::string BigInt::to_hex_string() const |
43 | 0 | { |
44 | 0 | const std::vector<uint8_t> bits = BigInt::encode(*this); |
45 | 0 | if(bits.empty()) |
46 | 0 | return "00"; |
47 | 0 | else |
48 | 0 | return hex_encode(bits); |
49 | 0 | } |
50 | | |
51 | | /* |
52 | | * Encode a BigInt |
53 | | */ |
54 | | void BigInt::encode(uint8_t output[], const BigInt& n, Base base) |
55 | 0 | { |
56 | 0 | secure_vector<uint8_t> enc = n.encode_locked(base); |
57 | 0 | copy_mem(output, enc.data(), enc.size()); |
58 | 0 | } |
59 | | |
60 | | namespace { |
61 | | |
62 | | std::vector<uint8_t> str_to_vector(const std::string& s) |
63 | 0 | { |
64 | 0 | std::vector<uint8_t> v(s.size()); |
65 | 0 | std::memcpy(v.data(), s.data(), s.size()); |
66 | 0 | return v; |
67 | 0 | } |
68 | | |
69 | | secure_vector<uint8_t> str_to_lvector(const std::string& s) |
70 | 0 | { |
71 | 0 | secure_vector<uint8_t> v(s.size()); |
72 | 0 | std::memcpy(v.data(), s.data(), s.size()); |
73 | 0 | return v; |
74 | 0 | } |
75 | | |
76 | | } |
77 | | |
78 | | /* |
79 | | * Encode a BigInt |
80 | | */ |
81 | | std::vector<uint8_t> BigInt::encode(const BigInt& n, Base base) |
82 | 0 | { |
83 | 0 | if(base == Binary) |
84 | 0 | return BigInt::encode(n); |
85 | 0 | else if(base == Hexadecimal) |
86 | 0 | return str_to_vector(n.to_hex_string()); |
87 | 0 | else if(base == Decimal) |
88 | 0 | return str_to_vector(n.to_dec_string()); |
89 | 0 | else |
90 | 0 | throw Invalid_Argument("Unknown BigInt encoding base"); |
91 | 0 | } |
92 | | |
93 | | /* |
94 | | * Encode a BigInt |
95 | | */ |
96 | | secure_vector<uint8_t> BigInt::encode_locked(const BigInt& n, Base base) |
97 | 0 | { |
98 | 0 | if(base == Binary) |
99 | 0 | return BigInt::encode_locked(n); |
100 | 0 | else if(base == Hexadecimal) |
101 | 0 | return str_to_lvector(n.to_hex_string()); |
102 | 0 | else if(base == Decimal) |
103 | 0 | return str_to_lvector(n.to_dec_string()); |
104 | 0 | else |
105 | 0 | throw Invalid_Argument("Unknown BigInt encoding base"); |
106 | 0 | } |
107 | | |
108 | | /* |
109 | | * Encode a BigInt, with leading 0s if needed |
110 | | */ |
111 | | secure_vector<uint8_t> BigInt::encode_1363(const BigInt& n, size_t bytes) |
112 | 19.8k | { |
113 | 19.8k | if(n.bytes() > bytes) |
114 | 24 | throw Encoding_Error("encode_1363: n is too large to encode properly"); |
115 | 19.7k | |
116 | 19.7k | secure_vector<uint8_t> output(bytes); |
117 | 19.7k | n.binary_encode(output.data(), output.size()); |
118 | 19.7k | return output; |
119 | 19.7k | } |
120 | | |
121 | | //static |
122 | | void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n) |
123 | 40.4k | { |
124 | 40.4k | if(n.bytes() > bytes) |
125 | 0 | throw Encoding_Error("encode_1363: n is too large to encode properly"); |
126 | 40.4k | |
127 | 40.4k | n.binary_encode(output, bytes); |
128 | 40.4k | } |
129 | | |
130 | | /* |
131 | | * Encode two BigInt, with leading 0s if needed, and concatenate |
132 | | */ |
133 | | secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes) |
134 | 0 | { |
135 | 0 | if(n1.bytes() > bytes || n2.bytes() > bytes) |
136 | 0 | throw Encoding_Error("encode_fixed_length_int_pair: values too large to encode properly"); |
137 | 0 | secure_vector<uint8_t> output(2 * bytes); |
138 | 0 | n1.binary_encode(output.data() , bytes); |
139 | 0 | n2.binary_encode(output.data() + bytes, bytes); |
140 | 0 | return output; |
141 | 0 | } |
142 | | |
143 | | /* |
144 | | * Decode a BigInt |
145 | | */ |
146 | | BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base) |
147 | 17.8k | { |
148 | 17.8k | BigInt r; |
149 | 17.8k | if(base == Binary) |
150 | 0 | { |
151 | 0 | r.binary_decode(buf, length); |
152 | 0 | } |
153 | 17.8k | else if(base == Hexadecimal) |
154 | 17.8k | { |
155 | 17.8k | secure_vector<uint8_t> binary; |
156 | 17.8k | |
157 | 17.8k | if(length % 2) |
158 | 7.45k | { |
159 | 7.45k | // Handle lack of leading 0 |
160 | 7.45k | const char buf0_with_leading_0[2] = |
161 | 7.45k | { '0', static_cast<char>(buf[0]) }; |
162 | 7.45k | |
163 | 7.45k | binary = hex_decode_locked(buf0_with_leading_0, 2); |
164 | 7.45k | |
165 | 7.45k | binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]), |
166 | 7.45k | length - 1, |
167 | 7.45k | false); |
168 | 7.45k | } |
169 | 10.4k | else |
170 | 10.4k | binary = hex_decode_locked(cast_uint8_ptr_to_char(buf), |
171 | 10.4k | length, false); |
172 | 17.8k | |
173 | 17.8k | r.binary_decode(binary.data(), binary.size()); |
174 | 17.8k | } |
175 | 0 | else if(base == Decimal) |
176 | 0 | { |
177 | 0 | for(size_t i = 0; i != length; ++i) |
178 | 0 | { |
179 | 0 | if(Charset::is_space(buf[i])) |
180 | 0 | continue; |
181 | 0 | |
182 | 0 | if(!Charset::is_digit(buf[i])) |
183 | 0 | throw Invalid_Argument("BigInt::decode: " |
184 | 0 | "Invalid character in decimal input"); |
185 | 0 | |
186 | 0 | const uint8_t x = Charset::char2digit(buf[i]); |
187 | 0 |
|
188 | 0 | if(x >= 10) |
189 | 0 | throw Invalid_Argument("BigInt: Invalid decimal string"); |
190 | 0 | |
191 | 0 | r *= 10; |
192 | 0 | r += x; |
193 | 0 | } |
194 | 0 | } |
195 | 0 | else |
196 | 0 | throw Invalid_Argument("Unknown BigInt decoding method"); |
197 | 17.8k | return r; |
198 | 17.8k | } |
199 | | |
200 | | } |