RFC 4648 - Base64 Encoding
0. 들어가면서
시스템 개발을 하면 Base64 인코딩(encoding)과 디코딩(decoding)을 수행하는 코드들을 많이 볼 수 있습니다. 예전에는 데이터를 암복호화하는 작업이라 잘못 이해하고 있었지만, Base64 인코딩은 엄밀히 암호화하는 작업이 아니기 때문에 언제든지 데이터를 디코딩을 통해 확인할 수 있습니다. 최근 프로젝트들에서도 Base64 인코딩, 디코딩 작업을 수행하는 코드를 작성했는데, 어떤 이유에서 이런 작업이 필요한지 궁금하여 관련된 내용을 공부 후 포스트로 정리하였습니다.
1. Encoding and Decoding
인코딩은 정보의 형태나 형식을 변환하는 처리나 처리 방식을 의미합니다. 텍스트, 이미지, 비디오 같은 정보나 데이터를 정해진 규칙에 의해 다른 형식으로 변환하는 작업입니다. 디코딩은 인코딩과 반대 작업을 의미합니다. 다른 형태의 데이터를 다시 텍스트, 이미지, 비디오 같은 정보 혹은 데이터로 변환하는 작업입니다.
2. Base64 Encoding
디코딩은 인코딩의 반대 작업이기 때문에 인코딩에 대해서만 알아볼 예정입니다. RFC 4648 표준 문서를 읽어보면 Base64 인코딩에 대해 다음과 같이 소개하고 있습니다.
Base encoding of data is used in many situations to store or transfer data in environments that, perhaps for legacy reasons, are restricted to US-ASCII [1] data.
시스템이 사용할 수 있는 데이터 형식이 US-ASCII로 제한되는 환경에서 데이터를 저장하거나 전송하는 상황에서 많이 사용된다고 합니다. Base64는 6비트(bit)를 사용해 표현할 수 있는 64개 문자들을 가지고 데이터를 인코딩합니다.
- A~Z, a~z, 0~9 그리고 두 개의 특수 문자를 사용합니다.
- 두 개의 특수 문자는 종종 다른 것들이 사용됩니다.
- 8 비트 데이터를 6비트로 전환하기 때문에 길이가 맞지 않는 부분은 = 문자를 패딩(padding)으로 사용해 채웁니다.
RFC 표준에서 Base64 인코딩에 사용되는 문자들을 다음과 같이 정의합니다.
2.1. Encoding Examples
어떤 과정을 통해 인코딩 작업이 이뤄지는지 살펴보겠습니다. 8비트로 표현된 데이터 3글자를 6비트로 표현히먄 4글자로 변경됩니다.
- 앞에서부터 6비트씩 나눕니다.
- 6비트 값을 10진수로 표현합니다.
- 10진수에 해당하는 문자를 Base64 테이블에서 찾습니다.
- 해당 문자로 변환합니다.
+--first octet--+-second octet--+--third octet--+
|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+-----------+---+-------+-------+---+-----------+
|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|
+--1.index--+--2.index--+--3.index--+--4.index--+
예를 들어 8비트 6개 문자를 6비트로 전환하는 과정은 다음과 같습니다.
- 앞에서부터 6비트로 나눕니다.
- 6비트들을 10진수로 표현합니다.
- 10진수에 매치되는 문자를 Base64 테이블에서 찾습니다.
Input data: 0x14fb9c03d97e
Hex: 1 4 f b 9 c | 0 3 d 9 7 e
8-bit: 00010100 11111011 10011100 | 00000011 11011001 01111110
6-bit: 000101 001111 101110 011100 | 000000 111101 100101 111110
Decimal: 5 15 46 28 0 61 37 62
Output: F P u c A 9 l +
비트 길이가 맞지 않는 경우 패딩을 사용합니다. 패딩을 사용하는 경우 다음과 같은 방법으로 변환됩니다.
- 앞에서부터 6비트로 나눕니다.
- 6비트들을 10진수로 표현합니다.
- 마지막 문자에서 6비트로 표현할 때 부족한 2비트는 00을 채웁니다.
- 10진수에 매치되는 문자를 Base64 테이블에서 찾습니다.
- 마지막 패딩이 추가되었음을 알려주기 위해 = 문자를 추가합니다.
Input data: 0x14fb9c03d9
Hex: 1 4 f b 9 c | 0 3 d 9
8-bit: 00010100 11111011 10011100 | 00000011 11011001
pad with 00
6-bit: 000101 001111 101110 011100 | 000000 111101 100100
Decimal: 5 15 46 28 0 61 36
pad with =
Output: F P u c A 9 k =
- 앞에서부터 6비트로 나눕니다.
- 6비트들을 10진수로 표현합니다.
- 마지막 문자에서 6비트로 표현할 때 부족한 4비트는 0000을 채웁니다.
- 10진수에 매치되는 문자를 Base64 테이블에서 찾습니다.
- 마지막 패딩이 추가되었음을 알려주기 위해 == 문자를 추가합니다.
Input data: 0x14fb9c03
Hex: 1 4 f b 9 c | 0 3
8-bit: 00010100 11111011 10011100 | 00000011
pad with 0000
6-bit: 000101 001111 101110 011100 | 000000 110000
Decimal: 5 15 46 28 0 48
pad with = =
Output: F P u c A w = =
f
문자를 직접 변환하면 다음과 같은 과정을 거칩니다.
f
문자는 ASCII 코드로 표현하면102
입니다.102
를 이진수로 표현하면0110 0110
입니다.- 앞부터 6비트씩 자르고 부족한 값은 00 비트를 추가합니다.
011001 100000
입니다.
011001 100000
을 십진수로 표현하면25 32
입니다.25 32
를 Base64 테이블의 문자로 매핑하면Zg==
입니다.- 패딩 비트가 추가된 회수만큼 = 문자를 추가합니다. Zg입니다.
3. Why do we use Base64 encoding?
Base64 인코딩은 6비트로 한 글자를 표현하기 때문에 예시의 f
가 Zg==
로 변환되는 것처럼 데이터의 길이가 커집니다. 데이터의 크기가 커지고 인코딩과 디코딩 같은 추가 연산이 필요함에도 Base64 인코딩을 사용하는 이유는 다음과 같습니다.
- 바이너리 데이터 전송의 안정성
- 시스템마다 바이너리 데이터를 다루는 방식이 다르기 때문에 어떤 경우에 특정 바이트 값이 손상될 수 있습니다.
- Base64는 바이너리 데이터를 텍스트 데이터로 변환하여 안정성을 높이므로 MIME(Multipurpose Internet Mail Extensions) 형식에서 많이 사용됩니다.
- URL 전송
- 일부 특수 문자는 URL에서 특별한 용도로 예약되어 있거나 문제를 일으킵니다.
- Base64는 안전한 URL 전송을 위해 사용됩니다.
- 데이터 변환
- 데이터를 읽기 어렵게 만들거나 숨기기 위해 사용합니다.
- 실제로 데이터를 암호화하진 않지만 빠르게 형태를 변환할 수 있기 때문에 간단한 형태의 보안을 제공합니다.
댓글남기기