Created
May 27, 2013 23:58
-
-
Save svagionitis/5659642 to your computer and use it in GitHub Desktop.
Base 64 encoding/decoding https://en.wikipedia.org/wiki/Base64
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
#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