Last active
July 21, 2024 22:41
-
-
Save opsJson/33a2a113188b021f5b9fc313a942bf47 to your computer and use it in GitHub Desktop.
Base64 codec in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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