base64.c (3181B)
1 /* 2 * base64.c - Base64 encoding/decoding functions 3 */ 4 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <stddef.h> 8 9 /* Base64 encoding table */ 10 static const char base64_chars[] = 11 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 12 13 /* Base64 encode */ 14 char* base64_encode(const uint8_t *data, size_t len, size_t *out_len) { 15 size_t encoded_len = 4 * ((len + 2) / 3); 16 char *encoded = malloc(encoded_len + 1); 17 if (!encoded) return NULL; 18 19 size_t i, j; 20 for (i = 0, j = 0; i < len; ) { 21 uint32_t octet_a = i < len ? data[i++] : 0; 22 uint32_t octet_b = i < len ? data[i++] : 0; 23 uint32_t octet_c = i < len ? data[i++] : 0; 24 25 uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c; 26 27 encoded[j++] = base64_chars[(triple >> 18) & 0x3F]; 28 encoded[j++] = base64_chars[(triple >> 12) & 0x3F]; 29 encoded[j++] = base64_chars[(triple >> 6) & 0x3F]; 30 encoded[j++] = base64_chars[triple & 0x3F]; 31 } 32 33 /* Add padding */ 34 for (i = 0; i < (3 - len % 3) % 3; i++) { 35 encoded[encoded_len - 1 - i] = '='; 36 } 37 38 encoded[encoded_len] = '\0'; 39 if (out_len) *out_len = encoded_len; 40 return encoded; 41 } 42 43 /* Base64 decoding table */ 44 static const unsigned char base64_decode_table[256] = { 45 ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, 46 ['G'] = 6, ['H'] = 7, ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, 47 ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, ['Q'] = 16, ['R'] = 17, 48 ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, 49 ['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, 50 ['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, 51 ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41, 52 ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47, 53 ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, 54 ['2'] = 54, ['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, 55 ['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63 56 }; 57 58 /* Base64 decode */ 59 uint8_t* base64_decode(const char *data, size_t len, size_t *out_len) { 60 if (len == 0 || len % 4 != 0) return NULL; 61 62 size_t decoded_len = len / 4 * 3; 63 if (data[len - 1] == '=') decoded_len--; 64 if (data[len - 2] == '=') decoded_len--; 65 66 uint8_t *decoded = malloc(decoded_len); 67 if (!decoded) return NULL; 68 69 size_t i, j; 70 for (i = 0, j = 0; i < len;) { 71 uint32_t sextet_a = base64_decode_table[(unsigned char)data[i++]]; 72 uint32_t sextet_b = base64_decode_table[(unsigned char)data[i++]]; 73 uint32_t sextet_c = base64_decode_table[(unsigned char)data[i++]]; 74 uint32_t sextet_d = base64_decode_table[(unsigned char)data[i++]]; 75 76 uint32_t triple = (sextet_a << 18) + (sextet_b << 12) + 77 (sextet_c << 6) + sextet_d; 78 79 if (j < decoded_len) decoded[j++] = (triple >> 16) & 0xFF; 80 if (j < decoded_len) decoded[j++] = (triple >> 8) & 0xFF; 81 if (j < decoded_len) decoded[j++] = triple & 0xFF; 82 } 83 84 if (out_len) *out_len = decoded_len; 85 return decoded; 86 }