2 * UCW Library -- Base 64 Encoding & Decoding
4 * (c) 2002, Robert Spalek <robert@ucw.cz>
5 * (c) 2018, Pavel Charvat <pchar@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
14 #include <ucw/base64.h>
16 const byte base64_enc_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
17 const byte base64_dec_table[256] = {
18 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
19 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
20 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f,
21 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x40, 0x80, 0x80,
22 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
23 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80,
24 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
25 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80,
26 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
27 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
28 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
29 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
30 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
31 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
32 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
33 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
36 uint base64_encode(byte *dest, const byte *src, uint len)
38 const byte *ptr = src;
39 const byte *end = src + len;
42 /* keep going until we have less than 24 bits */
44 for (const byte *x = end - 2; ptr < x; )
46 out[0] = base64_enc_table[ptr[0] >> 2];
47 out[1] = base64_enc_table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)];
48 out[2] = base64_enc_table[((ptr[1] & 0x0f) << 2) + (ptr[2] >> 6)];
49 out[3] = base64_enc_table[ptr[2] & 0x3f];
54 /* now deal with the tail end of things */
57 out[0] = base64_enc_table[ptr[0] >> 2];
58 out[3] = BASE64_PADDING;
61 out[1] = base64_enc_table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)];
62 out[2] = base64_enc_table[(ptr[1] & 0x0f) << 2];
66 out[1] = base64_enc_table[(ptr[0] & 0x03) << 4];
67 out[2] = BASE64_PADDING;
75 uint base64_decode(byte *dest, const byte *src, uint len)
77 const byte *ptr = src;
78 const byte *end = src + len;
85 if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
88 while (ch > BASE64_DEC_PADDING);
92 if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
93 goto end; // Broken base64 encoding, we only have 6 bits
95 while (ch > BASE64_DEC_PADDING);
96 val = (val << 6) | ch;
99 if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
106 while (ch > BASE64_DEC_PADDING);
107 val = (val << 6) | ch;
110 if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
118 while (ch > BASE64_DEC_PADDING);
119 val = (val << 6) | ch;