8 #include <botan/base64.h>
9 #include <botan/exceptn.h>
10 #include <botan/mem_ops.h>
11 #include <botan/internal/rounding.h>
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',
'+',
'/'
25 void do_base64_encode(
char out[4],
const uint8_t in[3])
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) )];
38 size_t& input_consumed,
43 size_t input_remaining = input_length;
44 size_t output_produced = 0;
46 while(input_remaining >= 3)
48 do_base64_encode(out + output_produced, in + input_consumed);
55 if(final_inputs && input_remaining)
57 uint8_t remainder[3] = { 0 };
58 for(
size_t i = 0; i != input_remaining; ++i)
59 remainder[i] = in[input_consumed + i];
61 do_base64_encode(out + output_produced, remainder);
63 size_t empty_bits = 8 * (3 - input_remaining);
64 size_t index = output_produced + 4 - 1;
65 while(empty_bits >= 8)
71 input_consumed += input_remaining;
75 return output_produced;
82 std::string output(output_length, 0);
87 if (output_length > 0)
103 size_t& input_consumed,
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 };
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;
146 for(
size_t i = 0; i != input_length; ++i)
148 const uint8_t bin = BASE64_TO_BIN[
static_cast<uint8_t
>(input[i])];
152 decode_buf[decode_buf_pos] = bin;
155 else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
157 std::string bad_char(1, input[i]);
160 else if(bad_char ==
"\n")
162 else if(bad_char ==
"\r")
166 std::string(
"base64_decode: invalid base64 character '") +
173 if(final_inputs && (i == input_length - 1))
177 for(
size_t j = decode_buf_pos; j != 4; ++j)
179 final_truncate = (4 - decode_buf_pos);
184 if(decode_buf_pos == 4)
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];
192 input_consumed = i+1;
196 while(input_consumed < input_length &&
197 BASE64_TO_BIN[static_cast<uint8_t>(input[input_consumed])] == 0x80)
202 size_t written = (out_ptr - output) - final_truncate;
214 consumed,
true, ignore_ws);
216 if(consumed != input_length)
223 const std::string& input,
226 return base64_decode(output, input.data(), input.length(), ignore_ws);
253 return (
round_up(input_length, 3) / 3) * 4;
258 return (
round_up(input_length, 4) * 3) / 4;
size_t base64_encode_max_output(size_t input_length)
size_t base64_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
void clear_mem(T *ptr, size_t n)
std::vector< T, secure_allocator< T >> secure_vector
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
size_t base64_decode_max_output(size_t input_length)
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
size_t round_up(size_t n, size_t align_to)