겸손한 개발을 위한 자양분

BASE64 Encode/Decode

CODE2009. 6. 26. 14:00

#include 
#include 
#include 

static const	char Base64_EM[]	= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";	//!< Base64 인코드 테이블
static			char Base64_DM[256]	= {0,};																	//!< Base64 디코드 테이블


/*!
\brief		
	Base64 초기화 함수
	제공되는 다른 함수를 사용하기 이전에 선행 호출
\see		
*/
void base64_Init()
{
	for(int i = 0; i<256; i++)
		Base64_DM[i] = -1;

	for(int i = 0; i<64; i++)
		Base64_DM[Base64_EM[i]] = i;

	return;
}

/*!
\brief
	Base64 Encode 함수
	메모리의 내용을 문자열로 변환하여 주는 함수

\param[in]	pInBuf 			문자열로 바꿀 메모리의 포인터
\param[in]	ulSize			문자열로 바꿀 메모리의 크기
\param[out]	ppOutBuf 		변환된 문자열을 받을 메모리 포인터이며, 내부에서 할당하여 반환하므로 사용이 끝나면 free 하여야 한다.

\return		할당된 ppOutBuf 메모리의 크기
\see		
*/
int base64_Encode(unsigned char *pInBuf, unsigned long ulSize, unsigned char **ppOutBuf)
{
	unsigned char	input[3]  = {0,};
	unsigned char	output[4] = {0,};

	unsigned long	ulOutbufSize	= 0;

	unsigned long	ulOctaPosition	= 0;
	unsigned long	ulOctaSplit		= 0;
	unsigned long	ulHexaSplit		= 0;

	unsigned char	*pOctaBit		= 0;
	unsigned char	*pOctaBit_endof	= 0;

	pOctaBit_endof	= pInBuf + ulSize - 1;
	ulOutbufSize	= (4 * (ulSize / 3)) + (ulSize % 3? 4 : 0) + 1;

	(*ppOutBuf)		= (unsigned char*)malloc(ulOutbufSize);

	for  (pOctaBit = pInBuf;pOctaBit <= pOctaBit_endof; ulOctaSplit++, pOctaBit++) {
		ulOctaPosition			= ulOctaSplit % 3;
		input[ulOctaPosition]	= *pOctaBit;

		if (ulOctaPosition == 2 || pOctaBit == pOctaBit_endof) {
			output[0] = ((input[0] & 0xFC) >> 2);
			output[1] = ((input[0] & 0x3) << 4) | ((input[1] & 0xF0) >> 4);
			output[2] = ((input[1] & 0xF) << 2) | ((input[2] & 0xC0) >> 6);
			output[3] = (input[2] & 0x3F);

			(*ppOutBuf)[ulHexaSplit++] = Base64_EM[output[0]];
			(*ppOutBuf)[ulHexaSplit++] = Base64_EM[output[1]];
			(*ppOutBuf)[ulHexaSplit++] = ulOctaPosition == 0? '_' : Base64_EM[output[2]];
			(*ppOutBuf)[ulHexaSplit++] = ulOctaPosition <  2? '_' : Base64_EM[output[3]];

			input[0] = input[1] = input[2] = 0;
		}
	}

	(*ppOutBuf)[ulHexaSplit] = '\0';

	return ulOutbufSize;
}

/*!
\brief
	Base64 Decode 함수
	문자열을 원본 데이터로 변환하여 주는 함수

\param[in]	pInBuf 			변환할 문자열
\param[in]	ulSize			복원할 사이즈, Encode시의 Return 값과 같다.
\param[out]	pOutBuf 		복원 내용을 받을 메모리 포인터

\return		복원된 데이터의 사이즈
\see	base64_Encode	
*/
int base64_Decode(unsigned char *pInBuf, unsigned long ulSize, unsigned char *pOutBuf)
{
	unsigned long	ulOctaPosition	= 0;
	unsigned long	ulHexaPosition	= 0;
	
	unsigned char*	pOctaBit		= 0;
	unsigned char	cOctaBit		= 0;
	char			cHexaBit		= 0;
	char			cHexaBit_prev	= 0;

	for ( pOctaBit = pInBuf; *pOctaBit != '\0'; ++pOctaBit ) {
		cHexaBit = Base64_DM[(int) *pOctaBit];

		if ( cHexaBit != -1 ) {
			switch ( ulHexaPosition ) {
				case 0:
					++ulHexaPosition;
					break;
				case 1:
					cOctaBit = ( ( cHexaBit_prev << 2 ) | ( ( cHexaBit & 0x30 ) >> 4 ) );
					if ( ulOctaPosition < ulSize )
						pOutBuf[ulOctaPosition++] = cOctaBit;
					++ulHexaPosition;
					break;
				case 2:
					cOctaBit = ( ( ( cHexaBit_prev & 0xf ) << 4 ) | ( ( cHexaBit & 0x3c ) >> 2 ) );
					if ( ulOctaPosition < ulSize )
						pOutBuf[ulOctaPosition++] = cOctaBit;
					++ulHexaPosition;
					break;
				case 3:
					cOctaBit = ( ( ( cHexaBit_prev & 0x03 ) << 6 ) | cHexaBit );
					if ( ulOctaPosition < ulSize )
						pOutBuf[ulOctaPosition++] = cOctaBit;
					ulHexaPosition = 0;
					break;
			}
			cHexaBit_prev = cHexaBit;
		}
	}

	return ulOctaPosition;

}