Skip to content

Instantly share code, notes, and snippets.

@ligouras
Forked from barrysteyn/Base64.md
Last active August 29, 2015 14:10
Show Gist options
  • Save ligouras/ceeb85fa6876b88ea21a to your computer and use it in GitHub Desktop.
Save ligouras/ceeb85fa6876b88ea21a to your computer and use it in GitHub Desktop.
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <string.h>
#include <assert.h>
#include "base64.h"
//Encodes a binary safe string to base64
int Base64Encode(const uint8_t *buffer, size_t length, char **b64text) {
BIO *bio, *b64;
BUF_MEM *bufferPtr;
b64 = BIO_new(BIO_f_base64());
bio = BIO_new(BIO_s_mem());
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line
BIO_write(bio, buffer, length);
(void) BIO_flush(bio);
BIO_get_mem_ptr(bio, &bufferPtr);
(void) BIO_set_close(bio, BIO_NOCLOSE);
BIO_free_all(bio);
*b64text = (*bufferPtr).data;
return 1;
}
//Calculates the length of a decoded string
static size_t calcDecodeLength(const char *b64input) {
size_t padding = 0;
size_t len = strlen(b64input);
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
padding = 2;
else if (b64input[len-1] == '=') //last char is =
padding = 1;
return (size_t)len * 0.75 - padding;
}
//Decodes a base64 encoded string
int Base64Decode(char *b64message, uint8_t **buffer, size_t *length) {
BIO *bio, *b64;
size_t decodeLen = calcDecodeLength(b64message);
*buffer = (uint8_t *) malloc(decodeLen);
bio = BIO_new_mem_buf(b64message, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
*length = BIO_read(bio, *buffer, strlen(b64message));
assert(*length == decodeLen); //length should equal decodeLen, else something went horribly wrong
BIO_free_all(bio);
return 1;
}
#include <stdint.h>
int Base64Encode(const uint8_t *buffer, size_t length, char **b64text);
int Base64Decode(char *b64message, uint8_t **buffer, size_t *length);
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "base64.h"
int main(int argc, char **argv) {
const char *helloWorld = "Hello World";
char *base64EncodeOutput;
uint8_t *base64DecodeOutput;
size_t base64DecodeOutputLength;
if (argc > 1) {
Base64Encode((const uint8_t *)argv[1], strlen(argv[1]), &base64EncodeOutput);
printf("Base64Encode(\"%s\"): %s\n", argv[1], base64EncodeOutput);
}
else {
Base64Encode((const uint8_t *)helloWorld, strlen(helloWorld), &base64EncodeOutput);
printf("Base64Encode(\"%s\"): %s\n", helloWorld, base64EncodeOutput);
}
Base64Decode(base64EncodeOutput, &base64DecodeOutput, &base64DecodeOutputLength);
printf("Base64Decode(\"%s\"):\n", base64EncodeOutput);
printf("\t bytes: \"");
for(int i = 0; i < base64DecodeOutputLength; i++)
if (isprint(base64DecodeOutput[i]))
printf("%c", base64DecodeOutput[i]);
else
printf(".");
printf("\"\n");
printf("\t length: %zu\n", base64DecodeOutputLength);
if (base64DecodeOutput)
free(base64DecodeOutput);
if (base64EncodeOutput)
free(base64EncodeOutput);
return(0);
}
CC = gcc
CFLAGS = -Wall -Werror -std=gnu99
all: base64
base64.o: base64.c base64.h
main.o: main.c
OBJECTS = base64.o main.o
base64: $(OBJECTS)
$(CC) $(OBJECTS) -o base64 -lcrypto
clean:
@rm $(OBJECTS) base64
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment