Skip to content

Instantly share code, notes, and snippets.

@timothyqiu
Created May 31, 2016 02:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timothyqiu/2de812e0f85099a5f38e17777cb4390f to your computer and use it in GitHub Desktop.
Save timothyqiu/2de812e0f85099a5f38e17777cb4390f to your computer and use it in GitHub Desktop.
Base64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char const encode_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"01234567890+/";
char *base64_encode(char const *data, size_t size);
char *base64_decode(char const *code, size_t *size);
int main(int argc, char *argv[])
{
char *encoded = NULL, *decoded = NULL;
size_t size = 0;
if (argc != 2) {
printf("usage: %s STRING\n", argv[0]);
return 0;
}
encoded = base64_encode(argv[1], strlen(argv[1]));
printf("Encoded: %s\n", encoded);
decoded = base64_decode(encoded, &size);
decoded = realloc(decoded, size + 1);
decoded[size] = '\0';
printf("Decoded: %s (size=%zd)\n", decoded, size);
free(encoded);
free(decoded);
return 0;
}
char *base64_encode(char const *data, size_t size)
{
size_t len = (size + 2) / 3 * 4;
char *code = malloc(len + 1);
size_t offset = 0, pos = 0;
unsigned char buffer[3];
if (code == NULL) return NULL;
while (offset < size) {
memset(buffer, 0, sizeof(buffer));
memcpy(buffer, data + offset, offset + 2 < size ? 3 : (size - offset));
code[pos++] = encode_map[ (buffer[0] >> 2)];
code[pos++] = encode_map[(buffer[0] & 0x03) << 4 | (buffer[1] >> 4)];
code[pos++] = encode_map[(buffer[1] & 0x0F) << 2 | (buffer[2] >> 6)];
code[pos++] = encode_map[(buffer[2] & 0x3F) ];
offset += 3;
}
for (offset = offset - size; offset > 0; offset--)
code[len - offset] = '=';
code[len] = '\0';
return code;
}
char *base64_decode(char const *code, size_t *size)
{
size_t len = strlen(code);
size_t offset = 0, pos = 0;
char *data = NULL;
*size = len / 4 * 3 - (code[len - 1] == '=')
- (code[len - 2] == '=');
data = malloc(*size);
if (data == NULL) return NULL;
char decode_map[128];
for (offset = 0; offset < 64; offset++)
decode_map[encode_map[offset]] = offset;
for (offset = 0; offset < *size; offset++) {
pos = offset / 3 * 4;
switch (offset % 3) {
case 0: data[offset] = decode_map[code[pos + 0]] << 2 |
decode_map[code[pos + 1]] >> 4;
break;
case 1: data[offset] = decode_map[code[pos + 1]] << 4 |
decode_map[code[pos + 2]] >> 2;
break;
case 2: data[offset] = ((decode_map[code[pos + 2]] << 6) & 0xC0) |
decode_map[code[pos + 3]];
break;
}
}
return data;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment