base64.c (2667B)
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <limits.h> #include "base64.h" #define BASE64_FOLD 76 int base64_index(const char *, char); const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* * Return the index of a base64 char in the table */ int base64_index(const char *base64, char ch) { uint8_t idx = 0; for (idx = 0; idx < 64; idx++) if (base64[idx] == ch) return idx; return ch == '=' ? 0 : -1; } /* * Encode the given message in base64, allocate memory to store the encoded * message, and return the size allocated. */ size_t base64_encode(char **buf, const unsigned char *msg, size_t len) { size_t i, j; uint64_t b64; size_t size; /* calculate size needed for the base64 buffer */ size = (len / 3) * 4 + (len % 3 ? 4 : 0); *buf = malloc(size); memset(*buf, 0, size); for (i = j = 0; i < len; i+=3) { /* concatenate 3 bytes into one 24 bits quantum, or 0 */ b64 = 0; b64 |= (msg[i]<<16); b64 |= ((i+1 < len ? msg[i+1] : 0) << 8); b64 |= i+2 < len ? msg[i+2] : 0; /* extract 4 base64 values from it */ (*buf)[j++] = base64_table[63 & (b64>>18)]; (*buf)[j++] = base64_table[63 & (b64>>12)]; (*buf)[j++] = i+1 < len ? base64_table[63 & (b64>>6)] : '='; (*buf)[j++] = i+2 < len ? base64_table[63 & b64] : '='; } return size; } /* * Allocate size to decode a base64 message, decode it in the buffer and * return the allocated size. */ size_t base64_decode(char **buf, const unsigned char *msg, size_t len) { uint64_t b64; size_t size, i, j; size = (len / 4) * 3; size -= msg[len - 1] == '=' ? 1 : 0; size -= msg[len - 2] == '=' ? 1 : 0; *buf = malloc(size); if (*buf == NULL) return 0; memset(*buf, 0, size); for (i = j = 0; i < len; i+=4) { b64 = 0; b64 |= (base64_index(base64_table, msg[i])<<18); b64 |= (base64_index(base64_table, msg[i+1])<<12); b64 |= i + 2 < len ? (base64_index(base64_table, msg[i+2])<<6) : 0; b64 |= i + 3 < len ? (base64_index(base64_table, msg[i+3])) : 0; if (j < size) (*buf)[j++] = 255 & (b64>>16); if (j < size) (*buf)[j++] = 255 & (b64>>8); if (j < size) (*buf)[j++] = 255 & (b64); } return size; } /* * Write a base64 encoded message to the given file pointer, folded at the * given width (defaults to BASE64_FOLD if specified width is 0). */ size_t base64_fold(FILE *fp, char *base64, size_t len, size_t fold) { size_t i; fold = fold > 0 ? fold : BASE64_FOLD; for (i = 0; i < len; i += BASE64_FOLD) { fwrite(base64+i, 1, i+BASE64_FOLD>len?len-i:BASE64_FOLD, fp); fwrite("\n", 1, 1, fp); } return fold; } |