:::: MENU ::::

base64 encode & decode

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 <stdio.h>
#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