1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h>
const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const int base64_chars_inverse[] = { [43] = 62, [47] = 63, [48] = 52, [49] = 53, [50] = 54, [51] = 55, [52] = 56, [53] = 57, [54] = 58, [55] = 59, [56] = 60, [57] = 61, [65] = 0, [66] = 1, [67] = 2, [68] = 3, [69] = 4, [70] = 5, [71] = 6, [72] = 7, [73] = 8, [74] = 9, [75] = 10, [76] = 11, [77] = 12, [78] = 13, [79] = 14, [80] = 15, [81] = 16, [82] = 17, [83] = 18, [84] = 19, [85] = 20, [86] = 21, [87] = 22, [88] = 23, [89] = 24, [90] = 25, [97] = 26, [98] = 27, [99] = 28, [100] = 29, [101] = 30, [102] = 31, [103] = 32, [104] = 33, [105] = 34, [106] = 35, [107] = 36, [108] = 37, [109] = 38, [110] = 39, [111] = 40, [112] = 41, [113] = 42, [114] = 43, [115] = 44, [116] = 45, [117] = 46, [118] = 47, [119] = 48, [120] = 49, [121] = 50, [122] = 51 };
char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) { *output_length = 4 * ((input_length + 2) / 3); char *encoded_data = malloc(*output_length + 1); if (encoded_data == NULL) return NULL;
for (size_t i = 0, j = 0; i < input_length;) { uint32_t octet_a = i < input_length ? data[i++] : 0; uint32_t octet_b = i < input_length ? data[i++] : 0; uint32_t octet_c = i < input_length ? data[i++] : 0;
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
encoded_data[j++] = base64_chars[(triple >> 3 * 6) & 0x3F]; encoded_data[j++] = base64_chars[(triple >> 2 * 6) & 0x3F]; encoded_data[j++] = base64_chars[(triple >> 1 * 6) & 0x3F]; encoded_data[j++] = base64_chars[(triple >> 0 * 6) & 0x3F]; }
static const int mod_table[] = {0, 2, 1}; for (size_t i = 0; i < mod_table[input_length % 3]; ++i) encoded_data[*output_length - 1 - i] = '=';
encoded_data[*output_length] = '\0'; return encoded_data; }
unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) { if (input_length % 4 != 0) return NULL;
*output_length = input_length / 4 * 3; if (data[input_length - 1] == '=') (*output_length)--; if (data[input_length - 2] == '=') (*output_length)--;
unsigned char *decoded_data = malloc(*output_length); if (decoded_data == NULL) return NULL;
for (size_t i = 0, j = 0; i < input_length;) { uint32_t sextet_a = data[i] == '=' ? 0 & i++ : base64_chars_inverse[data[i++]]; uint32_t sextet_b = data[i] == '=' ? 0 & i++ : base64_chars_inverse[data[i++]]; uint32_t sextet_c = data[i] == '=' ? 0 & i++ : base64_chars_inverse[data[i++]]; uint32_t sextet_d = data[i] == '=' ? 0 & i++ : base64_chars_inverse[data[i++]];
uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; }
return decoded_data; }
|