base64 인코딩 디코딩 예제 c 소스

본 글은 base64 encoder/decoder예제 c 소스 코드를 싣고 있다.

BASE64


BASE64는 일련의 데이터를 64종류"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"의 문자만을 이용하여 표현하도록 하는 부호화 방식이다. Base64는 인터넷 이메일 프로토콜이나 http url등에서 사용된다. 

부호화 과정은 아래와 같다.

문자 : Hello
Hex 코드 : 0x48 0x65 0x6c 0x6c 0x6f
8bits bin 코드: 01001000 01100101 01101100 01101100 01101111

8비트 단위의 문자를 6비트 단위로 분리한다.

6bits bin 코드 : 010010  000110  010101  101100  011011  000110  1111 00  ‘=’

6비트 2진 코드 값은 BASE64 코드 테이블의 인덱스이고 각 인덱스의 문자로 base64 부호화 한다. 마지막 모자라는 비트는 0으로 채우며, 4글자 단위로 부호화 하기 때문에 4글자가 안되면 ‘=’기호를 사용해 4글자를 맞춘다.

Base64 코드 : aGVsbG8=


Base64 Encoder source code


Base64 인코더 소스는 아래와 같다. 위의 부호화 예대로 text데이터를 받아 6bit 단위로 나누어 base64 코드 테이블에 맞춰 부호화를 진행한다.

static const char base64code_ascii[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int text2base64_size(const char *text)
{
int len = strlen(text);
return ((len + 2) / 3 * 4);
}

int base64_encoder(char *in, int in_size, char *out, int out_size)
{
int i = 0;
int o = 0;

if (!in || !out) return 0;
if (text2base64_size(in) > out_size) return 0;

while (i < in_size - 2 && o+4 <= out_size)
{
out[o++] = base64code_ascii[(in[i] >> 2) & 0x3F];
out[o++] = base64code_ascii[((in[i] & 0x3) << 4) | ((int)(in[i + 1] & 0xF0) >> 4)];
out[o++] = base64code_ascii[((in[i + 1] & 0xF) << 2) | ((int)(in[i + 2] & 0xC0) >> 6)];
out[o++] = base64code_ascii[in[i + 2] & 0x3F];
i += 3;
}

if (i < in_size)
{
out[o++] = base64code_ascii[(in[i] >> 2) & 0x3F];
if (i == (in_size - 1))
{
out[o++] = base64code_ascii[((in[i] & 0x3) << 4)];
out[o++] = '='; // padding
}
else
{
out[o++] = base64code_ascii[((in[i] & 0x3) << 4) | ((int)(in[i + 1] & 0xF0) >> 4)];
out[o++] = base64code_ascii[((in[i + 1] & 0xF) << 2)];
}

out[o++] = '='; // padding
}

return o;
}

Base64 Decoder source


Base64 디코더 소스는 아래와 같다. base64 부호화 된 결과는 ascii 문자로 표현된다. ascii테이블에서 base64 코드 문자에 테이블의 인덱스 값을 넣어 복호화에 사용하였다. Base64에서 사용하지 않은 문자는 0xff값을 넣어 코드의 오류나 패딩 등을 검사하도록 했다. Base64 코드의 문자들은 각각이 6 bits 데이터이고, 위 부호화와 반대로 6bits 데이터들을 모아 8bits의 문자 코드로 복호화 한다.

static const unsigned char asciicode_base64code[256] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
// 0x2b +, 0x2f /
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63, 
// 0x30 : 0,1,2,...
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
// 0x40: @,A,B,C,...
0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
//0x50: P,Q,R,S,...
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff, 
// 0x60 : `,a,b,c,...
0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
// 0x70 : p,q,r,s,...
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

아래 함수는 파라메터인 code 데이터의 유효한 base64코드의 길이를 반환하는 함수다. 데이터에 base64 문자가 아니거나 패딩 문자가 발견되면, 그전 데이터 길이를 반환한다.

int base64code_size(const char *code, int len)
{
int real_code_len = 0;
if (!code)
return 0;

while (real_code_len < len && asciicode_base64code[code[real_code_len]] != 0xff)
{
real_code_len++;
}

return real_code_len;
}

int base642text_size(const char *code,int len)
{
return ((base64code_size(code,len) + 3) / 4) * 3;
}

int base64_decoder(const char *in, int in_size, char *out, int out_size)
{
int i = 0;
int o = 0;
int real_code_len = 0;

if (!in || !out) return 0;
if (out_size < base642text_size(in, in_size)) return 0;

real_code_len = base64code_size(in, in_size);


while (i + 4 < real_code_len)
{
out[o++] = (char)(asciicode_base64code[in[i]] << 2 | asciicode_base64code[in[i+1]] >> 4);
out[o++] = (char)(asciicode_base64code[in[i + 1]] << 4 | asciicode_base64code[in[i + 2]] >> 2);
out[o++] = (char)(asciicode_base64code[in[i + 2]] << 6 | asciicode_base64code[in[i + 3]]);
i += 4;
}

if (real_code_len - i > 1)
{
out[o++] = (char)(asciicode_base64code[in[i]] << 2 | asciicode_base64code[in[i + 1]] >> 4);
}

if (real_code_len - i > 2)
{
out[o++] = (char)(asciicode_base64code[in[i + 1]] << 4 | asciicode_base64code[in[i + 2]] >> 2);
}

if (real_code_len - i > 3)
{
out[o++] = (char)(asciicode_base64code[in[i + 2]] << 6 | asciicode_base64code[in[i + 3]]);
}

return o;
}


인코더/디코더 테스트 코드

char *str = "hello base64 !";
char base64_code[128] = { 0, };
char text[128] = { 0, };
int ret = 0;

printf("%s\n", str);

ret = base64_encoder(str, strlen(str), base64_code, 128);
printf("base64 encoding : %s\n",base64_code);

ret = base64_decoder(base64_code, ret, text, 128);
printf("base64 decoding : %s\n",text);

 

댓글

이 블로그의 인기 게시물

바로 프로젝트 적용 가능한 FIR Filter (low/high/band pass filter )를 c나 python으로 만들기

간단한 cfar 알고리즘에 대해

쉽게 설명한 파티클 필터(particle filter) 동작 원리와 예제

windows에서 간단하게 크롬캐스트(Chromecast)를 통해 윈도우 화면 미러링 방법

mkfs.fat Device or resource busy 에러 해결법