태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.


2008/06/02 01:29

Base64 Encode/Decode

조인시 위키에 기재되어있는 내용을 Visual C++에서 실행가능하도록 약간 수정한 코드입니다.

시중에 돌아다니는 base64관련 함수를 짜집기 한겁니다. 출처는 PHP3 에 들어간 Base64 Encode & Decode Source 랍니다.

목적으로 하는 문자열을 입력하면 base64로 인코딩과 디코딩을 시켜줍니다. base64는
웹에서 데이터를 전달(Content-Transfer)하기 위한 목적으로 사용됩니다. 사람이 읽을 수 없는 (바이너리)데이터의 경우 내용과 형태가 멋대로인 경우가 많아서 이 상태 그대로는 HTTP프로토콜을 이용해서 전달하기가 애매모호한데, 이것을 일관성 있는 데이터로 바꿔줍니다. base64인코딩을 할경우 US-ASCII에서 이용하는 65개의 pritable 문자로 데이터를 재구성합니다.

인코딩와 디코딩에 사용되는 알고리즘이 간단하다는 장점이 있지만 데이터를 인코딩할경우 원래 데이터에 비해서 33%정도 크기가 커진다는 단점이 존재 합니다.

<!> 이 함수는 완전하지 않은 버젼입니다. 내부에서 malloc()를 한후 free()하는 과정이 없으므로 메모리 누수가 발생할 수 있습니다. 약간 수정을 해야 될것 같은데, 일단은 그냥 올립니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char *__base64_encode(const unsigned char *str, 
        int length, int *ret_length);
unsigned char *__base64_decode(const unsigned char *str, 
        int length, int *ret_length);

int main()
{
   unsigned char *str, *dst;
   char *source = "1";
   int  size;
 
   str = __base64_encode((unsigned char *)source, strlen(source), &size);
   printf("%s : %d\n", str, size);
   dst = __base64_decode(str, strlen((const char *)str), &size);
   printf("%s : %d\n", dst, size);
 
   free(str);
   free(dst);

   return 0;
 
}

static char __base64_table[] ={
   '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', '+', '/', '\0'
};
 
static char __base64_pad = '=';
 
unsigned char *__base64_encode(const unsigned char *str, int length, int *ret_length) {
   const unsigned char *current = str;
   int i = 0;
   unsigned char *result = (unsigned char *)malloc(((length + 3 - length % 3) * 4 / 3 + 1) * sizeof(char));
 
   while (length > 2) { /* keep going until we have less than 24 bits */
      result[i++] = __base64_table[current[0] >> 2];
      result[i++] = __base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
      result[i++] = __base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
      result[i++] = __base64_table[current[2] & 0x3f];
 
      current += 3;
      length -= 3; /* we just handle 3 octets of data */
   }
 
   /* now deal with the tail end of things */
   if (length != 0) {
      result[i++] = __base64_table[current[0] >> 2];
      if (length > 1) {
         result[i++] = __base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
         result[i++] = __base64_table[(current[1] & 0x0f) << 2];
         result[i++] = __base64_pad;
      }
      else {
         result[i++] = __base64_table[(current[0] & 0x03) << 4];
         result[i++] = __base64_pad;
         result[i++] = __base64_pad;
      }
   }
   if(ret_length) {
      *ret_length = i;
   }
   result[i] = '\0';
   return result;
}
 
/* as above, but backwards. :) */
unsigned char *__base64_decode(const unsigned char *str, int length, int *ret_length) {
   const unsigned char *current = str;
   int ch, i = 0, j = 0, k;
   /* this sucks for threaded environments */
   static short reverse_table[256];
   static int table_built;
   unsigned char *result;
 
   if (++table_built == 1) {
      char *chp;
      for(ch = 0; ch < 256; ch++) {
         chp = strchr(__base64_table, ch);
         if(chp) {
            reverse_table[ch] = chp - __base64_table;
         } else {
            reverse_table[ch] = -1;
         }
      }
   }
 
   result = (unsigned char *)malloc(length + 1);
   if (result == NULL) {
      return NULL;
   }
 
   /* run through the whole string, converting as we go */
   while ((ch = *current++) != '\0') {
      if (ch == __base64_pad) break;
 
      /* When Base64 gets POSTed, all pluses are interpreted as spaces.
         This line changes them back.  It's not exactly the Base64 spec,
         but it is completely compatible with it (the spec says that
         spaces are invalid).  This will also save many people considerable
         headache.  - Turadg Aleahmad <turadg@wise.berkeley.edu>
      */
 
      if (ch == ' ') ch = '+';
 
      ch = reverse_table[ch];
      if (ch < 0) continue;
 
      switch(i % 4) {
      case 0:
         result[j] = ch << 2;
         break;
      case 1:
         result[j++] |= ch >> 4;
         result[j] = (ch & 0x0f) << 4;
         break;
      case 2:
         result[j++] |= ch >>2;
         result[j] = (ch & 0x03) << 6;
         break;
      case 3:
         result[j++] |= ch;
         break;
      }
      i++;
   }
 
   k = j;
   /* mop things up if we ended on a boundary */
   if (ch == __base64_pad) {
      switch(i % 4) {
      case 0:
      case 1:
         free(result);
         return NULL;
      case 2:
         k++;
      case 3:
         result[k++] = 0;
      }
   }
   if(ret_length) {
      *ret_length = j;
   }
   result[k] = '\0';
   return result;
}

원문출처(조인시위키)
http://www.joinc.co.kr/modules/moniwiki/wiki.php/Code/C/base64
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 Comment 0