Skip to content

Instantly share code, notes, and snippets.

@kvelakur
Last active December 16, 2015 20:38
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 kvelakur/a3ac17ebf5614547ded9 to your computer and use it in GitHub Desktop.
Save kvelakur/a3ac17ebf5614547ded9 to your computer and use it in GitHub Desktop.
Base 64 encoding and decoding using OpenSSL

Base 64 encoding and decoding using OpenSSL

Functions to encode an array of bytes to Base64, and decode a Base64 string to an array of bytes.

#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
/**
* @brief Use the openssl library to decode a base64 string to a C string.
*
* @param[in] The Base64 encoded string. Has to null terminated.
* @param[out] The length of the decoded string.
*
* @retval Pointer to decoded array of bytes. Note that array is not null-terminated.
* NULL if decoding failed.
* Caller has to free the memory after using the decoded string.
*/
unsigned char *base64_decode(char* b64message, size_t *decode_len)
{
BIO *bio = NULL, *b64 = NULL;
unsigned char *buffer = NULL;
size_t msglen = strlen(b64message);
if(msglen == 0) goto cleanup;
bio = BIO_new_mem_buf(b64message, -1);
if(bio == NULL) goto cleanup;
b64 = BIO_new(BIO_f_base64());
if(b64 == NULL) goto cleanup;
// New lines should't matter
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
bio = BIO_push(b64, bio);
// The maximum possible length, after accounting for padding and CR+LF is msglen*3/4
buffer = (unsigned char*) malloc(sizeof(char)*(msglen*3)/4);
if (buffer == NULL) goto cleanup;
*decode_len = (size_t) BIO_read(bio, buffer, (int) msglen);
cleanup:
BIO_free_all(bio);
return buffer;
}
/**
* @brief Use the openssl library to encode a byte array to a Base64 string.
*
* @param[in] The byte array to be encoded.
* @param[in] The length of the byte array buffer.
*
* @retval Pointer to encoded null-terminated string, or NULL if encoding failed.
* Caller has to free the memory after using the encoded string.
*/
char *base64_encode(unsigned char *buffer, size_t length)
{
BIO *bio = NULL, *b64 = NULL;
BUF_MEM *bufferPtr = NULL;
char *b64text = NULL;
if(length <= 0) goto cleanup;
b64 = BIO_new(BIO_f_base64());
if(b64 == NULL) goto cleanup;
bio = BIO_new(BIO_s_mem());
if(bio == NULL) goto cleanup;
bio = BIO_push(b64, bio);
if(BIO_write(bio, buffer, (int)length) <= 0) goto cleanup;
if(BIO_flush(bio) != 1) goto cleanup;
BIO_get_mem_ptr(bio, &bufferPtr);
b64text = (char*) malloc((bufferPtr->length + 1) * sizeof(char));
if(b64text == NULL) goto cleanup;
memcpy(b64text, bufferPtr->data, bufferPtr->length);
b64text[bufferPtr->length] = '\0';
BIO_set_close(bio, BIO_NOCLOSE);
cleanup:
BIO_free_all(bio);
return b64text;
}
int main() {
char to_encode[] = "Test data !@#$%^&*()";
char to_decode[] = "VGVzdCBkYXR\n\n\n\n\n\n\n\n"
"hICFAIyQlXiYqKCk=";
char *encoded = NULL;
unsigned char *decoded = NULL;
size_t i;
encoded = base64_encode((unsigned char *) to_encode, strlen(to_encode));
if(encoded == NULL) goto exit;
printf("%s\n", encoded);
size_t len;
decoded = base64_decode(to_decode, &len);
if(decoded == NULL) goto exit;
for(i = 0; i < len; i++) putchar(decoded[i]);
printf("\n");
exit:
free(decoded);
free(encoded);
return 0;
}
all:
gcc -g -o base64.out base64.c -lcrypto -lm -Werror
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment