8 #include <botan/base64.h>
9 #include <botan/mem_ops.h>
10 #include <botan/internal/rounding.h>
11 #include <botan/internal/assert.h>
18 static const byte BIN_TO_BASE64[64] = {
19 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
20 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
21 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
22 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
23 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'
26 void do_base64_encode(
char out[4],
const byte in[3])
28 out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)];
29 out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
30 out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
31 out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )];
39 size_t& input_consumed,
44 size_t input_remaining = input_length;
45 size_t output_produced = 0;
47 while(input_remaining >= 3)
49 do_base64_encode(out + output_produced, in + input_consumed);
56 if(final_inputs && input_remaining)
58 byte remainder[3] = { 0 };
59 for(
size_t i = 0; i != input_remaining; ++i)
60 remainder[i] = in[input_consumed + i];
62 do_base64_encode(out + output_produced, remainder);
64 size_t empty_bits = 8 * (3 - input_remaining);
65 size_t index = output_produced + 4 - 1;
66 while(empty_bits >= 8)
72 input_consumed += input_remaining;
76 return output_produced;
82 std::string output((round_up<size_t>(input_length, 3) / 3) * 4, 0);
103 size_t& input_consumed,
111 static const byte 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 byte* out_ptr = output;
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 byte bin = BASE64_TO_BIN[
static_cast<byte>(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")
165 throw std::invalid_argument(
166 std::string(
"base64_decode: invalid base64 character '") +
173 if(final_inputs && (i == input_length - 1))
177 for(
size_t i = decode_buf_pos; i != 4; ++i)
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<byte>(input[input_consumed])] == 0x80)
202 size_t written = (out_ptr - output) - final_truncate;
214 consumed,
true, ignore_ws);
216 if(consumed != input_length)
217 throw std::invalid_argument(
"base64_decode: input did not have full bytes");
223 const std::string& input,
226 return base64_decode(output, &input[0], input.length(), ignore_ws);
size_t base64_decode(byte 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)
#define BOTAN_ASSERT_EQUAL(value1, value2, msg)
size_t base64_encode(char out[], const byte in[], size_t input_length, size_t &input_consumed, bool final_inputs)