Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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