Base64는 byte 배열을 읽는 방식을 의미합니다. (보통 우리가 사용하는 UTF8, ASCII 등이 있지요)

Base64는 3byte (24bit) 단위로 자르고, 6bit씩을 취해 해당 값에 매칭되는 base64테이블로 매핑해줍니다.

이 때, 원문이 없는 경우는 "=" 문자열을 넣어 길이를 채워줍니다.

아래는 aB1@ 를 base64로 변환 한 결과입니다.

 

Base64 Table : ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

 

base64 나눠지는 형식

 

 

일단 C# 에서 제공되는 코드가 있는데 내부 구현이 궁금하여 테스트 해보게 되었습니다.

 

[C# base64 기존 제공]

string text = "aB1@"; //원본
byte[] bytes = Encoding.UTF8.GetBytes(plainText); //원하는 인코딩으로 byte 만들기
string base64String = Convert.ToBase64String(bytes); //byte배열 -> base64 텍스트 변환
byte[] base64bytes = Convert.FromBase64String(base64String); //base64 텍스트 -> byte배열 변환
string originText = Encoding.UTF8.GetString(base64bytes); //원본과 일치

 

 

[C# 직접 구현 - 4Byte int 형으로 비트 값 연산에 사용 (GPT 도움..!)]

using System;
using System.Collections.Generic;
using System.Text;

class Test
{
    private const string table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    private const string plainText = "aB1@";

    static void Main()
    {
        byte[] bytes = Encoding.UTF8.GetBytes(plainText);

        string base64Text = Base64Encoding(bytes); //직접 구현
        string base64Text2 = Convert.ToBase64String(bytes); //기존 제공

        Console.WriteLine("base64 텍스트 : " + base64Text);
        Console.WriteLine("base64 텍스트2 : " + base64Text2);

        byte[] base64bytes = Base64Decoding(base64Text); //직접 구현
        byte[] base64bytes2 = Convert.FromBase64String(base64Text2); //기존 제공

        Console.WriteLine("원본 복원 : " + Encoding.UTF8.GetString(base64bytes));
        Console.WriteLine("원본 복원2 : " + Encoding.UTF8.GetString(base64bytes2));
    }

    private static string Base64Encoding(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < bytes.Length; i += 3)
        {
            int value = 0;
            int paddingCount = 0;

            //3byte씩 합쳐주기
            for (int j = i; j < i + 3; ++j)
            {
                value = value << 8;

                if (j < bytes.Length)
                {
                    value |= bytes[j];
                }
                else
                {
                    paddingCount++;
                }
            }

            //Masking
            //1111 1100 0000 0000 0000 0000 (0x3F << 6 << 6 << 6)
            //0000 0011 1111 0000 0000 0000 (0x3F << 6 << 6)
            //0000 0000 0000 1111 1100 0000 (0x3F << 6)
            //0000 0000 0000 0000 0011 1111 (0x3F)
            int masking = 0x3F << 6 << 6 << 6;

            //3byte를 6bit로 쪼개기 (없다면 패딩처리 '=')
            for (int j = 0; j < 4; ++j)
            {
                if (paddingCount > 3 - j)
                {
                    sb.Append("=");
                }
                else
                {
                    int v = (value & masking) >> 6 * (3 - j);
                    sb.Append(table[v]);
                }

                masking = masking >> 6;
            }
        }

        return sb.ToString();
    }

    private static byte[] Base64Decoding(string text)
    {
        List<byte> byteList = new List<byte>();

        for (int i = 0; i < text.Length; i += 4)
        {
            int value = 0;
            int paddingCount = 0;

            for (int j = i; j < i + 4; ++j)
            {
                value = value << 6;

                if (text[j] != '=')
                {
                    value |= table.IndexOf(text[j]);
                }
                else
                {
                    paddingCount++;
                }
            }

            int masking = 0xFF << 8 << 8;

            for (int j = 0; j < 3; ++j)
            {
                if (paddingCount > (2 - j))
                {
                    break;
                }
                else
                {
                    int v = (value & masking) >> 8 * (2 - j);
                    byteList.Add((byte)v);
                }

                masking = masking >> 8;
            }

            //Console.WriteLine("Processing... " + Encoding.UTF8.GetString(byteList.ToArray()));
        }

        return byteList.ToArray();
    }
}

 

+ Recent posts