Skip to content

Instantly share code, notes, and snippets.

@opsJson
Last active July 21, 2024 22:41
Show Gist options
  • Save opsJson/33a2a113188b021f5b9fc313a942bf47 to your computer and use it in GitHub Desktop.
Save opsJson/33a2a113188b021f5b9fc313a942bf47 to your computer and use it in GitHub Desktop.
Base64 codec in C
#ifndef _BASE64_H_
#define _BASE64_H_
#ifndef BASE64_ALLOC
#include <stdlib.h>
#define BASE64_ALLOC malloc
#endif
#ifndef BASE64_STRLEN
#include <string.h>
#define BASE64_STRLEN strlen
#endif
char *b64_encode(const void *data, unsigned int size_bytes) {
char *result;
const char *ptr;
unsigned int i, j;
static const char *lookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (data == NULL || size_bytes == 0) return NULL;
ptr = data;
result = BASE64_ALLOC(((size_bytes + 2) / 3 * 4) + 1);
if (result == NULL) return NULL;
for (i=0,j=0; i<size_bytes; i+=3) {
char a = ptr[i];
char b = (i + 1 < size_bytes) ? ptr[i + 1] : 0;
char c = (i + 2 < size_bytes) ? ptr[i + 2] : 0;
result[j++] = lookup[(a & 0xFC) >> 2];
result[j++] = lookup[((a & 0x03) << 4) | ((b & 0xF0) >> 4)];
result[j++] = (i + 1 < size_bytes) ? lookup[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)] : '=';
result[j++] = (i + 2 < size_bytes) ? lookup[c & 0x3F] : '=';
}
result[j] = '\0';
return result;
}
char *b64_encode_str(const char *cstr) {
return b64_encode(cstr, BASE64_STRLEN(cstr));
}
void *b64_decode(const char *cstr) {
char *result;
unsigned int i, j, length;
static const char lookup[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1,
-1, 0, 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, -1, -1, -1, -1, -1, -1, 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
};
if (cstr == NULL) return NULL;
length = BASE64_STRLEN(cstr);
if (length % 4 != 0) return NULL;
result = BASE64_ALLOC((length / 4) * 3 + 1);
if (result == NULL) return NULL;
for (i=0,j=0; i<length; i+=4) {
char a = (cstr[i] <= 'z') ? lookup[(unsigned char)cstr[i]] : -1;
char b = (cstr[i + 1] <= 'z') ? lookup[(unsigned char)cstr[i + 1]] : -1;
char c = (cstr[i + 2] <= 'z') ? lookup[(unsigned char)cstr[i + 2]] : -1;
char d = (cstr[i + 3] <= 'z') ? lookup[(unsigned char)cstr[i + 3]] : -1;
if (a == -1 || b == -1 || c == -1 || d == -1) {
free(result);
return NULL;
}
result[j++] = (a << 2) | ((b & 0x30) >> 4);
if (cstr[i + 2] != '=') {
result[j++] = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
}
if (cstr[i + 3] != '=') {
result[j++] = ((c & 0x03) << 6) | d;
}
}
result[j] = '\0';
return result;
}
#endif /* _BASE64_H_ */
/*///////////////////////////////////
Testing:
///////////////////////////////////*/
#include <stdio.h>
int main(void) {
{
char *str = "Many hands make light work.";
char *encoded = b64_encode_str(str);
char *decoded = b64_decode(encoded);
printf("str encoded: (%s)\n", encoded);
printf("str decoded: (%s)\n\n", decoded);
}
{
int numbers[] = {1, 2, 3, 4};
char *encoded = b64_encode(numbers, sizeof(numbers));
int *decoded = b64_decode(encoded);
printf("numbers encoded: %s\n", encoded);
printf("numbers decoded: {%i, %i, %i, %i}\n", decoded[0], decoded[1], decoded[2], decoded[3]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment