Botan  2.8.0
Crypto and TLS for C++11
base64.cpp
Go to the documentation of this file.
1 /*
2 * Base64 Encoding and Decoding
3 * (C) 2010,2015 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/base64.h>
9 #include <botan/internal/codec_base.h>
10 #include <botan/exceptn.h>
11 #include <botan/internal/rounding.h>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 class Base64 final
18  {
19  public:
20  static inline size_t encoding_bytes_in() BOTAN_NOEXCEPT
21  {
22  return m_encoding_bytes_in;
23  }
24  static inline size_t encoding_bytes_out() BOTAN_NOEXCEPT
25  {
26  return m_encoding_bytes_out;
27  }
28 
29  static inline size_t decoding_bytes_in() BOTAN_NOEXCEPT
30  {
31  return m_encoding_bytes_out;
32  }
33  static inline size_t decoding_bytes_out() BOTAN_NOEXCEPT
34  {
35  return m_encoding_bytes_in;
36  }
37 
38  static inline size_t bits_consumed() BOTAN_NOEXCEPT
39  {
40  return m_encoding_bits;
41  }
42  static inline size_t remaining_bits_before_padding() BOTAN_NOEXCEPT
43  {
44  return m_remaining_bits_before_padding;
45  }
46 
47  static inline size_t encode_max_output(size_t input_length)
48  {
49  return (round_up(input_length, m_encoding_bytes_in) / m_encoding_bytes_in) * m_encoding_bytes_out;
50  }
51  static inline size_t decode_max_output(size_t input_length)
52  {
53  return (round_up(input_length, m_encoding_bytes_out) * m_encoding_bytes_in) / m_encoding_bytes_out;
54  }
55 
56  static void encode(char out[8], const uint8_t in[5]) BOTAN_NOEXCEPT
57  {
58  out[0] = Base64::m_bin_to_base64[(in[0] & 0xFC) >> 2];
59  out[1] = Base64::m_bin_to_base64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
60  out[2] = Base64::m_bin_to_base64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
61  out[3] = Base64::m_bin_to_base64[in[2] & 0x3F];
62  }
63 
64  static inline uint8_t lookup_binary_value(char input) BOTAN_NOEXCEPT
65  {
66  return Base64::m_base64_to_bin[static_cast<uint8_t>(input)];
67  }
68 
69  static inline bool check_bad_char(uint8_t bin, char input, bool ignore_ws)
70  {
71  if(bin <= 0x3F)
72  {
73  return true;
74  }
75  else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
76  {
77  std::string bad_char(1, input);
78  if(bad_char == "\t")
79  { bad_char = "\\t"; }
80  else if(bad_char == "\n")
81  { bad_char = "\\n"; }
82  else if(bad_char == "\r")
83  { bad_char = "\\r"; }
84 
85  throw Invalid_Argument(
86  std::string("base64_decode: invalid base64 character '") +
87  bad_char + "'");
88  }
89  return false;
90  }
91 
92  static void decode(uint8_t* out_ptr, const uint8_t decode_buf[4])
93  {
94  out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4);
95  out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2);
96  out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3];
97  }
98 
99  static inline size_t bytes_to_remove(size_t final_truncate)
100  {
101  return final_truncate;
102  }
103 
104  private:
105  static const size_t m_encoding_bits = 6;
106  static const size_t m_remaining_bits_before_padding = 8;
107 
108 
109  static const size_t m_encoding_bytes_in = 3;
110  static const size_t m_encoding_bytes_out = 4;
111 
112 
113  static const uint8_t m_bin_to_base64[64];
114  static const uint8_t m_base64_to_bin[256];
115  };
116 
117 const uint8_t Base64::m_bin_to_base64[64] =
118  {
119  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
120  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
121  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
122  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
123  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
124  };
125 
126 /*
127 * base64 Decoder Lookup Table
128 * Warning: assumes ASCII encodings
129 */
130 const uint8_t Base64::m_base64_to_bin[256] =
131  {
132  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
133  0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
134  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
135  0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
136  0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35,
137  0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
138  0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04,
139  0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
140  0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
141  0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C,
142  0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
143  0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
144  0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
145  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
146  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
147  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
148  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
149  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
150  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
151  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
152  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
153  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
154  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
155  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
156  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
157  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
158  };
159 }
160 
161 size_t base64_encode(char out[],
162  const uint8_t in[],
163  size_t input_length,
164  size_t& input_consumed,
165  bool final_inputs)
166  {
167  return base_encode(Base64(), out, in, input_length, input_consumed, final_inputs);
168  }
169 
170 std::string base64_encode(const uint8_t input[],
171  size_t input_length)
172  {
173  const size_t output_length = Base64::encode_max_output(input_length);
174  std::string output(output_length, 0);
175 
176  size_t consumed = 0;
177  size_t produced = 0;
178 
179  if(output_length > 0)
180  {
181  produced = base64_encode(&output.front(),
182  input, input_length,
183  consumed, true);
184  }
185 
186  BOTAN_ASSERT_EQUAL(consumed, input_length, "Consumed the entire input");
187  BOTAN_ASSERT_EQUAL(produced, output.size(), "Produced expected size");
188 
189  return output;
190  }
191 
192 size_t base64_decode(uint8_t out[],
193  const char in[],
194  size_t input_length,
195  size_t& input_consumed,
196  bool final_inputs,
197  bool ignore_ws)
198  {
199  return base_decode(Base64(), out, in, input_length, input_consumed, final_inputs, ignore_ws);
200  }
201 
202 size_t base64_decode(uint8_t output[],
203  const char input[],
204  size_t input_length,
205  bool ignore_ws)
206  {
207  size_t consumed = 0;
208  size_t written = base64_decode(output, input, input_length,
209  consumed, true, ignore_ws);
210 
211  if(consumed != input_length)
212  { throw Invalid_Argument("base64_decode: input did not have full bytes"); }
213 
214  return written;
215  }
216 
217 size_t base64_decode(uint8_t output[],
218  const std::string& input,
219  bool ignore_ws)
220  {
221  return base64_decode(output, input.data(), input.length(), ignore_ws);
222  }
223 
225  size_t input_length,
226  bool ignore_ws)
227  {
228  const size_t output_length = Base64::decode_max_output(input_length);
229  secure_vector<uint8_t> bin(output_length);
230 
231  size_t written = base64_decode(bin.data(),
232  input,
233  input_length,
234  ignore_ws);
235 
236  bin.resize(written);
237  return bin;
238  }
239 
240 secure_vector<uint8_t> base64_decode(const std::string& input,
241  bool ignore_ws)
242  {
243  return base64_decode(input.data(), input.size(), ignore_ws);
244  }
245 
246 size_t base64_encode_max_output(size_t input_length)
247  {
248  return Base64::encode_max_output(input_length);
249  }
250 
251 size_t base64_decode_max_output(size_t input_length)
252  {
253  return Base64::decode_max_output(input_length);
254  }
255 
256 }
size_t base_decode(Base &&base, uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws=true)
Definition: codec_base.h:99
size_t base64_decode_max_output(size_t input_length)
Definition: base64.cpp:251
size_t base64_encode_max_output(size_t input_length)
Definition: base64.cpp:246
int(* final)(unsigned char *, CTX *)
#define BOTAN_NOEXCEPT
Definition: compiler.h:154
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:161
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:81
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
Definition: alg_id.cpp:13
size_t base64_decode(uint8_t out[], const char in[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
Definition: base64.cpp:192
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
size_t round_up(size_t n, size_t align_to)
Definition: rounding.h:21
size_t base_encode(Base &&base, char output[], const uint8_t input[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: codec_base.h:32