Base64는 byte 배열을 읽는 방식을 의미합니다. (보통 우리가 사용하는 UTF8, ASCII 등이 있지요)
Base64는 3byte (24bit) 단위로 자르고, 6bit씩을 취해 해당 값에 매칭되는 base64테이블로 매핑해줍니다.
이 때, 원문이 없는 경우는 "=" 문자열을 넣어 길이를 채워줍니다.
아래는 aB1@ 를 base64로 변환 한 결과입니다.
Base64 Table : ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
일단 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();
}
}
'C# > Console' 카테고리의 다른 글
[C# Console] AES256 사용 (+ 자바) (0) | 2025.04.02 |
---|---|
[C#] 프로세스 실행 및 대기 (Process.Start , Process.WaitForExit) (0) | 2024.01.30 |
[C#] 금액 (숫자) -> 한글 (원)로 변환하기 (0) | 2023.01.23 |
[C#] StructLayout : 클래스/구조체 크기 설정 (0) | 2022.08.03 |
[C#] 제이슨 JSON (JObject, JArray, Serialize, Deserialize) (0) | 2022.06.30 |