Botan  2.11.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,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  {
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  secure_vector<uint8_t> enc = n.encode_locked(base);
57  copy_mem(output, enc.data(), enc.size());
58  }
59 
60 namespace {
61 
62 std::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 
69 secure_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 */
81 std::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 */
96 secure_vector<uint8_t> BigInt::encode_locked(const BigInt& n, Base base)
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 */
111 secure_vector<uint8_t> BigInt::encode_1363(const BigInt& n, size_t bytes)
112  {
113  if(n.bytes() > bytes)
114  throw Encoding_Error("encode_1363: n is too large to encode properly");
115 
116  secure_vector<uint8_t> output(bytes);
117  n.binary_encode(output.data(), output.size());
118  return output;
119  }
120 
121 //static
122 void 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 */
133 secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes)
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 */
146 BigInt 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  {
155  secure_vector<uint8_t> binary;
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 
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 }
BigInt const BigInt & x
Definition: numthry.h:139
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
BigInt size_t n
Definition: bigint.h:1096
const uint8_t * buf
Definition: ffi.h:371
uint8_t char2digit(char c)
Definition: charset.cpp:231
BigInt size_t bits
Definition: numthry.h:210
void const BigInt BigInt BigInt & r
Definition: divide.h:23
botan_mp_t remainder
Definition: ffi.h:831
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
bool is_space(char c)
Definition: charset.cpp:221
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:122
Definition: alg_id.cpp:13
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
size_t bytes
Definition: ffi.h:150
void ct_divide_u8(const BigInt &x, uint8_t y, BigInt &q_out, uint8_t &r_out)
Definition: divide.cpp:82
uint8_t base
Definition: ffi.h:749
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:164
void BlockCipher const uint8_t size_t uint8_t output[]
Definition: package.h:29
char digit2char(uint8_t b)
Definition: charset.cpp:253
bool is_digit(char c)
Definition: charset.cpp:210
secure_vector< uint8_t > hex_decode_locked(const char input[], size_t input_length, bool ignore_ws)
Definition: hex.cpp:165