Skip to content

Instantly share code, notes, and snippets.

@svagionitis
Created May 27, 2013 23:58
Show Gist options
  • Save svagionitis/5659642 to your computer and use it in GitHub Desktop.
Save svagionitis/5659642 to your computer and use it in GitHub Desktop.
Base 64 encoding/decoding https://en.wikipedia.org/wiki/Base64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
/*The index Base64 table.*/
static const unsigned char indexBase64Tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* ##########################################################################################
Name : encodebase64
Description : Encode a character string (binary or text) to an ASCII string format.
Further info in http://en.wikipedia.org/wiki/Base64
Arguments Type Description
===================== ===================== =====================================
inputData(IN) const unsigned char * The input string to be encoded.
inputDataLen(IN) int The length of the input string.
outputData(OUT) char ** The encoded string.
outputDataLen(OUT) int * The length of the encoded string.
Return Values Description
========================================= =====================================
1 For successful encoding.
0 Failure.
Globals Type Description
===================== ========================== =====================================
indexBase64Tbl static const unsigned char The Base64 index table.
Locals Type Description
===================== =================== =====================================
i, j unsigned int General indexes.
threeOctets unsigned int It's a temporary integer where three
input characters stored in order to
make the bit calculations.
remainLength The remaining length of the input
string.
encChars The four resulting encoded characters.
############################################################################################ */
unsigned char encodebase64(const unsigned char *inputData, int inputDataLen, char **outputData, int *outputDataLen){
unsigned int i = 0, j = 0;
/*Calculate the output string size.*/
*outputDataLen = (inputDataLen + 2 - ((inputDataLen + 2) % 3)) / 3 * 4;
/*Allocate memory for the output string.*/
*outputData = (char *)malloc((*outputDataLen)*sizeof(char));
if (*outputData == NULL){
printf("Enc Mem alloc Error.\n");
return FALSE;
}
else/*Initialize*/
memset(*outputData, 0, strlen(*outputData));
for(i = 0, j = 0;i<inputDataLen, j<*outputDataLen;i+=3, j+=4){
unsigned int threeOctets = 0x0U;
unsigned int remainLength = inputDataLen - i;
unsigned char encChars[4];
memset(encChars, 0, sizeof(encChars));
/*
memcpy(&octets3, &inputData[i], 3*sizeof(unsigned char));
bcopy(&inputData[i], &octets3, 3*sizeof(unsigned char));
*/
/*
Put the three characters in the unsigned int buffer. If the three
characters are "Man" then we will see the following in the buffer:
String: M a n
Decimal: 77 97 110
Hexadecimal: 0x4D 0x61 0x6E
Binary: 01001101 01100001 01101110
So the buffer will have the value 0x004D616E (in decimal 5,071,214).
*/
threeOctets |= inputData[i] << 16;
threeOctets |= inputData[i+1] << 8;
threeOctets |= inputData[i+2];
/*
Now we want to take the 6 bits from these three characters.
77 97 110
| |
010011010110000101101110
| | |
19 22 5 46
Mask 0x0000003F = 00000000000000000000000000111111
Mask 0x00000FC0 = 00000000000000000000111111000000
Mask 0x0003F000 = 00000000000000111111000000000000
Mask 0x00FC0000 = 00000000111111000000000000000000
00000000010011010110000101101110
& 00000000000000000000000000111111 (0x0000003F)
----------------------------------
00000000000000000000000000101110 (0x2E, 46)
00000000010011010110000101101110
& 00000000000000111111000000000000 (0x0003F000)
----------------------------------
12
00000000000000010110000000000000 >> 00000000000000000000000000010110 (0x16, 22)
*/
encChars[3] = (unsigned char) (threeOctets & 0x0000003F);
encChars[2] = (unsigned char)((threeOctets & 0x00000FC0) >> 6);
encChars[1] = (unsigned char)((threeOctets & 0x0003F000) >> 12);
encChars[0] = (unsigned char)((threeOctets & 0x00FC0000) >> 18);
(*outputData)[j] = indexBase64Tbl[encChars[0]];
(*outputData)[j+1] = indexBase64Tbl[encChars[1]];
(*outputData)[j+2] = ((remainLength > 1) ? indexBase64Tbl[encChars[2]] : '=');
(*outputData)[j+3] = ((remainLength > 2) ? indexBase64Tbl[encChars[3]] : '=');
}
return TRUE;
}
/* ##########################################################################################
Name : decodebase64
Description : Decode a Base64 encoded character string to it's original message.
Further info in http://en.wikipedia.org/wiki/Base64
Arguments Type Description
===================== ===================== =====================================
inputData(IN) const unsigned char * The input string to be decoded.
inputDataLen(IN) int The length of the input string.
outputData(OUT) char ** The decoded string.
outputDataLen(OUT) int * The length of the decoded string.
Return Values Description
========================================= =====================================
1 For successful decoding.
0 Failure.
Globals Type Description
===================== ========================== =====================================
Locals Type Description
===================== =================== =====================================
i, j, k unsigned int General indexes.
threeOctets unsigned int It's a temporary integer where four
input characters stored in order to
make the bit calculations.
indexTable unsigned char The four indexes for the Base64 table.
############################################################################################ */
unsigned char decodebase64(const unsigned char *inputData, int inputDataLen, char **outputData, int *outputDataLen){
unsigned int i = 0, j = 0;
/*Calculate the output string size.*/
*outputDataLen = (inputDataLen + 2 - ((inputDataLen + 2) % 4)) / 4 * 3;
/*Allocate memory for the output string.*/
*outputData = (char *)malloc((*outputDataLen)*sizeof(char));
if (*outputData == NULL){
printf("Dec Mem alloc Error.\n");
return FALSE;
}
else/*Initialize*/
memset(*outputData, 0, strlen(*outputData));
for(i = 0, j = 0;i<inputDataLen, j<*outputDataLen;i+=4, j+=3){
unsigned char k = 0, indexTable[4];
unsigned int threeOctets = 0x0U;
memset(indexTable, 0, sizeof(indexTable));
for (k = 0;k<4;k++){
if (isupper(inputData[i+k]))
/*
The first 26 characters in the index Base64 table are the Uppercase alphabet.
65 is the decimal value for 'A'.
*/
indexTable[k] = inputData[i+k] - 65;
else if (islower(inputData[i+k]))
/*
The following 26 characters are the lowercase alphabet.
97 is the decimal value for 'a'.
*/
indexTable[k] = (inputData[i+k] - 97) + 26;
else if (isdigit(inputData[i+k]))
/*
The following 10 characters are the ten digits.
48 is the decimal value for '0'.
*/
indexTable[k] = (inputData[i+k] - 48) + 52;
else if (inputData[i+k] == '+')
indexTable[k] = 62;
else if (inputData[i+k] == '/')
indexTable[k] = 63;
}
/*
Store the index values in the unsigned int buffer in order to make the appropriate
bitwise calculation for decoding.
*/
threeOctets |= (indexTable[3] & 0x3F);
threeOctets |= (indexTable[2] & 0x3F) << 6;
threeOctets |= (indexTable[1] & 0x3F) << 12;
threeOctets |= (indexTable[0] & 0x3F) << 18;
(*outputData)[j] = (unsigned char)((threeOctets & 0x00FF0000) >> 16);
(*outputData)[j+1] = (unsigned char)((threeOctets & 0x0000FF00) >> 8);
(*outputData)[j+2] = (unsigned char) (threeOctets & 0x000000FF);
}
return TRUE;
}
int main(int argc, char *argv[]){
//const unsigned char testString[] = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
//const unsigned char testString[] = "sur";
//const unsigned char testString[] = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=";
//const unsigned char testString[] = "UGFzc3dvcmQ6";
const unsigned char testString[] = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";
//const unsigned char testString[] = "c3Vy";
//const unsigned char testString[] = "c3VyZS4=";
char *outData = NULL;
int stringLength = 0, outLength = 0;
unsigned char returnOut = 0;
if ( argc <= 2 ){
usage();
}
else if ( argc == 3) {
}
stringLength = strlen((const char *)testString);
printf("Input String Length: %d\n", stringLength);
/*
returnOut = encodebase64(testString, stringLength, &outData, &outLength);
if (returnOut == FALSE)
return FALSE;
*/
returnOut = decodebase64(testString, stringLength, &outData, &outLength);
if (returnOut == FALSE)
return FALSE;
printf("Base64 String Size: %d\n", outLength);
printf("Base64 Out String: %s\n", outData);
return TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment