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