base64란 64진수라는 뜻.
즉 2진수 데이터를 64진수 데이터로 변경하는 것.
예를 들면 a, b, c의 경우 ASCII값은 0x61, 0x62, 0x63이고, 2진수로 01100001, 01100010, 01100011이다
이것을 6bit씩 끊으면…. 011000 010110 001001 100011 가 되고, 각각 값은 0x18(24), 0x16(22), 0x09(9), 0x23(35)가 된다.
base64의 문자셋은 다음과 같으므로,
A~Z : 0 ~25
a~z : 26 ~51
0~9 : 52 ~ 61
+ : 62
/ : 63
위 abc는 YWJj가 된다.
만약 딱 떨어지지 않는 경우 남는 비트의 경우 6 bit 문자를 0으로 padding하고 그래도 남는 6 bit 문자는 = 으로 치환한다.
C코드
#include <stdlib.h>
#include <time.h>
#include <endian.h>
static const char MimeBase64[] = {
‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’,
‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’,
‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’,
‘Y’, ‘Z’, ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’,
‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’,
‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’,
‘w’, ‘x’, ‘y’, ‘z’, ‘0’, ‘1’, ‘2’, ‘3’,
‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘+’, ‘/’
};
static int DecodeMimeBase64[256] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */
52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */
-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */
41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */
};
typedef union{
struct{
unsigned char c1,c2,c3;
};
struct{
unsigned int e1:6,e2:6,e3:6,e4:6;
};
} BF;
int endian = 0; // little : 0, big : 1
void base64e(char *src, char *result, int length){
int i, j = 0;
BF temp;
if(endian == 0){ // little endian(intel)
for(i = 0 ; i < length ; i = i+3, j = j+4){
temp.c3 = src[i];
if((i+1) > length) temp.c2 = 0x00;
else temp.c2 = src[i+1];
if((i+2) > length) temp.c1 = 0x00;
else temp.c1 = src[i+2];
result[j] = MimeBase64[temp.e4];
result[j+1] = MimeBase64[temp.e3];
result[j+2] = MimeBase64[temp.e2];
result[j+3] = MimeBase64[temp.e1];
if((i+2) > length) result[j+2] = ‘=’;
if((i+3) > length) result[j+3] = ‘=’;
}
} else { // big endian(sun)
for(i = 0 ; i < length ; i = i+3, j = j+4){
temp.c1 = src[i];
if((i+1) > length) temp.c2 = 0x00;
else temp.c2 = src[i+1];
if((i+2) > length) temp.c3 = 0x00;
else temp.c3 = src[i+2];
result[j] = MimeBase64[temp.e4];
result[j+1] = MimeBase64[temp.e3];
result[j+2] = MimeBase64[temp.e2];
result[j+3] = MimeBase64[temp.e1];
if((i+2) > length) result[j+2] = ‘=’;
if((i+3) > length) result[j+3] = ‘=’;
}
}
}
void base64d(char *src, char *result, int *length){
int i, j = 0, src_length, blank = 0;
BF temp;
src_length = strlen(src);
if(endian == 0){ // little endian(intel)
for(i = 0 ; i < src_length ; i = i+4, j = j+3){
temp.e4 = DecodeMimeBase64[src[i]];
temp.e3 = DecodeMimeBase64[src[i+1]];
if(src[i+2] == ‘=’){
temp.e2 = 0x00;
blank++;
} else temp.e2 = DecodeMimeBase64[src[i+2]];
if(src[i+3] == ‘=’){
temp.e1 = 0x00;
blank++;
} else temp.e1 = DecodeMimeBase64[src[i+3]];
result[j] = temp.c3;
result[j+1] = temp.c2;
result[j+2] = temp.c1;
}
} else { // big endian(sun)
for(i = 0 ; i < src_length ; i = i+4, j = j+3){
temp.e4 = DecodeMimeBase64[src[i]];
temp.e3 = DecodeMimeBase64[src[i+1]];
if(src[i+2] == ‘=’){
temp.e2 = 0x00;
blank++;
} else temp.e2 = DecodeMimeBase64[src[i+2]];
if(src[i+3] == ‘=’){
temp.e1 = 0x00;
blank++;
} else temp.e1 = DecodeMimeBase64[src[i+3]];
result[j] = temp.c1;
result[j+1] = temp.c2;
result[j+2] = temp.c3;
}
}
*length = j-blank;
}
int main(void){
char str1[]=”테스트문자열입니다.ABCabc123,./”;
char str2[]=”7YWM7Iqk7Yq466y47J6Q7Je07J6F64uI64ukLkFCQ2FiYzEyMywuLw==”;
char *result;
int src_size;
struct timespec start,end;
if (__LITTLE_ENDIAN == BYTE_ORDER) endian == 0;
else endian == 1;
src_size = strlen(str1);
result = (char *)malloc((4 * (src_size / 3)) + (src_size % 3 ? 4 : 0) + 1);
clock_gettime(CLOCK_REALTIME, &start);
base64e(str1, result, src_size);
clock_gettime(CLOCK_REALTIME, &end);
float time_dif = (end.tv_sec – start.tv_sec) + ((end.tv_nsec – start.tv_nsec) );
printf(“함수 수행 시간: %f\n”, time_dif);
printf(“%s\n%s\n”,str1,result);
free(result);
src_size = strlen(str2);
result = (char *)malloc(3 * (src_size / 4));
base64d(str2,result,&src_size);
printf(“%s\n%s\n길이:%d\n”,str2,result,src_size);
free(result);
}
온라인에서 base64를 테스트 할 수 있는 사이트 : http://ostermiller.org/calc/encode.html