Botan  2.9.0
Crypto and TLS for C++11
big_code.cpp
Go to the documentation of this file.
1 /*
2 * BigInt Encoding/Decoding
3 * (C) 1999-2010,2012 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  {
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 
42 std::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 */
54 void BigInt::encode(uint8_t output[], const BigInt& n, Base base)
55  {
56  if(base == Binary)
57  {
58  n.binary_encode(output);
59  }
60  else if(base == Hexadecimal)
61  {
63  n.binary_encode(binary.data());
64 
66  binary.data(), binary.size());
67  }
68  else if(base == Decimal)
69  {
70  BigInt copy = n;
71  uint8_t remainder;
72  copy.set_sign(Positive);
73  const size_t output_size = n.encoded_size(Decimal);
74  for(size_t j = 0; j != output_size; ++j)
75  {
76  ct_divide_u8(copy, 10, copy, remainder);
77  output[output_size - 1 - j] = Charset::digit2char(remainder);
78  if(copy.is_zero())
79  break;
80  }
81  }
82  else
83  throw Invalid_Argument("Unknown BigInt encoding method");
84  }
85 
86 /*
87 * Encode a BigInt
88 */
89 std::vector<uint8_t> BigInt::encode(const BigInt& n, Base base)
90  {
91  if(base == Binary)
92  return BigInt::encode(n);
93 
94  std::vector<uint8_t> output(n.encoded_size(base));
95  encode(output.data(), n, base);
96  for(size_t j = 0; j != output.size(); ++j)
97  if(output[j] == 0)
98  output[j] = '0';
99 
100  return output;
101  }
102 
103 /*
104 * Encode a BigInt
105 */
107  {
108  if(base == Binary)
109  return BigInt::encode_locked(n);
110 
111  secure_vector<uint8_t> output(n.encoded_size(base));
112  encode(output.data(), n, base);
113  for(size_t j = 0; j != output.size(); ++j)
114  if(output[j] == 0)
115  output[j] = '0';
116 
117  return output;
118  }
119 
120 /*
121 * Encode a BigInt, with leading 0s if needed
122 */
124  {
126  BigInt::encode_1363(output.data(), output.size(), n);
127  return output;
128  }
129 
130 //static
131 void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n)
132  {
133  const size_t n_bytes = n.bytes();
134  if(n_bytes > bytes)
135  throw Encoding_Error("encode_1363: n is too large to encode properly");
136 
137  const size_t leading_0s = bytes - n_bytes;
138  encode(&output[leading_0s], n, Binary);
139  }
140 
141 /*
142 * Encode two BigInt, with leading 0s if needed, and concatenate
143 */
145  {
146  secure_vector<uint8_t> output(2 * bytes);
147  BigInt::encode_1363(output.data(), bytes, n1);
148  BigInt::encode_1363(output.data() + bytes, bytes, n2);
149  return output;
150  }
151 
152 /*
153 * Decode a BigInt
154 */
155 BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base)
156  {
157  BigInt r;
158  if(base == Binary)
159  r.binary_decode(buf, length);
160  else if(base == Hexadecimal)
161  {
162  secure_vector<uint8_t> binary;
163 
164  if(length % 2)
165  {
166  // Handle lack of leading 0
167  const char buf0_with_leading_0[2] =
168  { '0', static_cast<char>(buf[0]) };
169 
170  binary = hex_decode_locked(buf0_with_leading_0, 2);
171 
172  binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]),
173  length - 1,
174  false);
175  }
176  else
178  length, false);
179 
180  r.binary_decode(binary.data(), binary.size());
181  }
182  else if(base == Decimal)
183  {
184  for(size_t i = 0; i != length; ++i)
185  {
186  if(Charset::is_space(buf[i]))
187  continue;
188 
189  if(!Charset::is_digit(buf[i]))
190  throw Invalid_Argument("BigInt::decode: "
191  "Invalid character in decimal input");
192 
193  const uint8_t x = Charset::char2digit(buf[i]);
194 
195  if(x >= 10)
196  throw Invalid_Argument("BigInt: Invalid decimal string");
197 
198  r *= 10;
199  r += x;
200  }
201  }
202  else
203  throw Invalid_Argument("Unknown BigInt decoding method");
204  return r;
205  }
206 
207 }
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
secure_vector< uint8_t > hex_decode_locked(const char input[], size_t input_length, bool ignore_ws)
Definition: hex.cpp:165
size_t bits() const
Definition: bigint.cpp:281
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:751
uint8_t char2digit(char c)
Definition: charset.cpp:231
bool is_zero() const
Definition: bigint.h:420
void binary_encode(uint8_t buf[]) const
Definition: bigint.cpp:387
static secure_vector< uint8_t > encode_locked(const BigInt &n)
Definition: bigint.h:763
bool is_space(char c)
Definition: charset.cpp:221
Definition: alg_id.cpp:13
size_t bytes() const
Definition: bigint.cpp:266
void ct_divide_u8(const BigInt &x, uint8_t y, BigInt &q_out, uint8_t &r_out)
Definition: divide.cpp:82
static BigInt decode(const uint8_t buf[], size_t length)
Definition: bigint.h:786
size_t encoded_size(Base base=Binary) const
Definition: bigint.cpp:297
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:165
char digit2char(uint8_t b)
Definition: charset.cpp:253
bool is_digit(char c)
Definition: charset.cpp:210
void binary_decode(const uint8_t buf[], size_t length)
Definition: bigint.cpp:397
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:123
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
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:144
void set_sign(Sign sign)
Definition: bigint.h:566
std::string to_dec_string() const
Definition: big_code.cpp:15