개발자 도구 · Base64 인코더 및 디코더
RFC 4648 설명: Base64, base32 및 base16을 정의하는 표준
· 배경
베이스64 인코딩
RFC 4648는 모든 Base64 구현 뒤에 있는 짧고 읽기 쉬운 문서입니다. 이 게시물에서는 명시한 내용, 의도적으로 공개한 내용, 구현이 여전히 다른 이유를 살펴봅니다.
두 개의 라이브러리, 동일한 문자열에 대한 두 개의 답변 — 표준만이 해결하는 실제 상호 운용성 퍼즐
두 개의 JavaScript 라이브러리는 동일한 문자열에 대해 각각 정확성을 주장하는 서로 다른 Base64를 반환할 수 있습니다. RFC 4648는 그러한 불일치를 해결해야 하는 읽을 수 있는 12페이지 분량의 문서이지만 RFC가 의도적으로 특정 결정을 응용 프로그램에 맡기기 때문에 구현은 여전히 다릅니다. 이 문서에서는 RFC 4648이 지정하는 내용, 의도적으로 호출자에게 위임하는 내용, 표준을 한 번 읽으면 대부분의 실제 상호 운용성 문제가 해결되는 이유를 설명합니다. Base64 인코더 및 디코더 도구에는 RFC 4648 테스트 벡터가 포함되어 있어 신뢰할 수 있는 예제와 비교하여 구현을 확인할 수 있습니다.
RFC 4648는 MIME(RFC 2045)의 Base64, Privacy-Enhanced Mail(RFC 1421)의 Base64, S/MIME(RFC 2630)의 base32 및 다양한 소스의 base16과 같은 여러 이전 문서를 대체하고 통합했습니다. MIME과 PEM에는 각각 고유한 알파벳과 규칙이 있었고 MIME 줄 바꿈은 PEM의 64 열 블록과 충돌했기 때문에 통합이 필요했습니다. RFC 4648는 다섯 가지 인코딩 계열(base64, base64url, base32, base32hex 및 base16)을 한 곳에서 정의하며, 각 계열에는 자체 알파벳, 패딩 규칙 및 예제 테스트 벡터가 있습니다. base64 알파벳은 A-Z, a-z, 0-9, 더하기 및 슬래시 순서입니다.
구현 및 테스트 벡터가 설정하는 것 — 표준 및 URL 안전 알파벳, 패딩 및 공백 처리
각 문자는 6 비트를 나타냅니다. 3개의 입력 바이트(24 비트)는 4개의 출력 문자에 매핑됩니다. 알파벳은 임의적이지 않습니다. EBCDIC과 ASCII가 다른 문자를 피하고 C 문자열 리터럴에서 이스케이프해야 하는 제어 문자, 따옴표 및 백슬래시를 피합니다. base64url 변형은 URL과 파일 이름에서 예약된 문자를 피하기 위해 더하기를 대시로 바꾸고 슬래시를 밑줄로 바꿉니다. 두 변형 모두 동일하게 유효합니다. RFC 4648 섹션 2은 base64를 지정하고, 섹션 5은 base64url을 지정하며 애플리케이션은 어떤 것을 사용하는지 명시해야 합니다.
등호 문자로 패딩하면 출력이 4자의 배수가 됩니다. 입력이 1 바이트(8 비트)인 경우 출력은 문자 2개와 등호 2개입니다. 입력이 2바이트(16비트)인 경우 출력은 3자 + 1 등호입니다. 입력이 3 바이트의 배수인 경우 패딩이 필요하지 않습니다. 일부 응용 프로그램에서는 패딩을 생략하거나 디코딩 시 패딩 누락을 허용합니다. RFC 4648 섹션 3.2에서는 표준 인코딩을 항상 패딩된 것으로 정의하지만, 섹션 3.3에서는 디코더가 호환성을 위해 누락된 패딩을 허용할 수 있음을 명시합니다.
이 도구가 구현하는 알파벳 — 표준 Base64 및 Base64url; 다른 기지는 범위 밖에 남아 있습니다.
구현이 일치하지 않는 이유는 패딩 구별 때문입니다. 엄격한 디코더는 누락된 등호를 거부하는 반면 관대한 디코더는 이를 허용합니다. RFC 4648에서는 다음과 같이 명시적으로 말합니다. 패드 문자 같음은 URL에서 사용될 때 일반적으로 퍼센트 인코딩되므로 base64url 출력이 URL 매개변수에서 직접 사용되는 경우 패딩은 필요하지 않으며 생략해야 합니다. 이 문장은 URL 안전 모드와 패딩 생략이 독립적인 선택임에도 불구하고 종종 짝을 이루는 이유 중 하나입니다. 섹션 5(base64url)은 패딩을 금지하지 않습니다. 단지 일반적인 관행을 언급할 뿐입니다.
base64url을 선택하는 호출자는 수신 시스템에 패딩이 필요한지 여부를 결정해야 합니다. 입력의 알파벳이 아닌 문자는 디코더마다 다르게 처리됩니다. RFC 4648 섹션 3.1 상태: 구현 시 기본 알파벳 외부 문자가 포함된 경우 인코딩을 거부해야 합니다. 그러나 3.3 섹션에서는 MIME Base64(RFC 2045)가 76 문자 줄바꿈에 줄 바꿈을 허용하고 MIME용 디코더는 공백을 건너뛰어야 한다는 점을 명시합니다. RFC는 엄격한 디코딩(알파벳이 아닌 모든 문자 거부)과 MIME 호환 디코딩(공백 건너뛰기, 다른 문자 거부)을 구별합니다.
패딩, 알파벳이 아닌 문자 및 표준 인코딩 — 대부분의 디코더 불일치를 설명하는 섹션
애플리케이션은 따라야 할 규칙을 선택해야 합니다. 표준은 두 가지를 모두 정의합니다. Base32는 A-Z 및 2-7(총 32 문자)를 사용하여 5개의 입력 바이트(40 비트)를 8개의 출력 문자로 인코딩합니다. Base32hex는 0-9 및 a-v를 알파벳 문자로 대체하며, 소문자를 선호하는 상황에서 유용합니다.
Base16은 16진수입니다: 0-9 및 a-f. Base32 및 base32hex에는 6 및 7 섹션에 자체 패딩 규칙이 있으며 RFC는 각 알파벳에 대해 별도의 테스트 벡터를 제공합니다. 대부분의 개발자에게는 base64와 base64url만 필요합니다. base32, base32hex 및 base16은 완전성과 TOTP 비밀(RFC 4226) 및 DNS 인코딩과 같은 애플리케이션을 위해 RFC에 포함되어 있습니다.
이 구현에서 볼 수 있는 애플리케이션 선택 — 줄 바꿈, 엄격한 텍스트 디코딩 및 오류 처리
RFC 4648의 테스트 벡터는 구현을 확인하기 위한 기준 진실입니다. 문자열 f, fo, foo, foob, fooba 및 foobar를 인코딩하면 Zg==, Zm8=, Zm9v, Zm9vYg==, Zm9vYmE= 및 Zm9vYmFy와 같은 특정 base64 출력이 생성됩니다. 이러한 문자열에 대해 다른 출력을 생성하는 구현은 올바르지 않습니다. RFC는 base32, base32hex 및 base16에 대해 동등한 테스트 벡터를 제공합니다. Base64 인코더 및 디코더 도구에는 이러한 벡터가 포함되어 있으므로 표준에 대한 출력을 확인할 수 있습니다. 줄 바꿈은 base64 문제가 아니라 MIME 문제입니다.
RFC 2045는 76 문자 라인을 지정합니다. RFC 4648 섹션 3.1에서는 MIME의 맥락에서 이를 기록하지만 base64 자체의 요구 사항으로 지정하지는 않습니다. 일부 애플리케이션은 64 문자(원래 PEM 표준)로 줄 바꿈됩니다. 다른 사람들은 전혀 포장하지 않습니다. 엄격한 RFC 4648 base64 디코더는 알파벳과 패딩에서만 작동합니다. MIME 호환 디코더는 줄바꿈(CR, LF, CRLF)을 건너뛰어야 합니다. MIME 외부에서 base64를 사용하는 애플리케이션은 수신 시스템에서 요구하지 않는 한 줄바꿈을 추가해서는 안 됩니다. RFC는 base64의 일부로 줄 바꿈을 정의하지 않습니다.
작업된 예: RFC 자체 테스트 벡터 — 'foobar' 접두사를 인코딩하고 브라우저에서 확인
공백 처리는 구현 차이의 또 다른 지점입니다. RFC 4648에서는 엄격한 디코더가 알파벳이 아닌 문자를 거부해야 한다고 말합니다. MIME으로 래핑된 base64(RFC 2045 base64)는 서식 지정에 공백을 허용합니다. 두 표준은 출력 바이트가 무엇인지에 대해서는 동의하지만 어떤 입력이 유효한지에 대해서는 다릅니다. 대부분의 JavaScript 구현은 MIME 호환성을 선택하고 공백을 건너뜁니다. 엄격한 규칙은 브라우저에서 거의 사용되지 않습니다. Base64 인코더 및 디코더는 공백 포함(MIME) 입력과 엄격한 입력을 모두 허용하므로 구분이 명확합니다. 정식 대 용서 디코딩이 최종 주요 차이입니다.
정식 디코딩은 RFC 4648 섹션 3.2을 따릅니다. 잘못된 패딩 거부, 누락된 패딩 거부, 알파벳이 아닌 문자 거부. 웹 표준(HTML 사양에서는 이를 forgiving-base64라고 함)에 사용되는 용서 디코딩에는 규칙이 추가됩니다. 공백을 무시하고, 누락된 패딩을 허용하고, 표준 base64 모드에서도 대시와 밑줄을 플러스 슬래시로 허용합니다. JavaScript의 atob()은 관대합니다. 엄격한 RFC 4648 디코더는 더 엄격합니다. 둘 다 틀린 것은 아닙니다. 그들은 다른 맥락을 제공합니다. 사용자나 네트워크에서 데이터를 읽는 애플리케이션은 상대방이 어떤 규칙을 기대하는지 알아야 합니다.
여기서 다루지 않는 내용 — MIME 및 PEM 문서 자체와 언어별 API
RFC는 다섯 가지 알파벳 중 어느 것, 패딩을 요구할지 허용할지, 공백을 요구할지 허용할지, 대시 밑줄을 슬래시와 동일하게 처리할지 여부, 오류를 보고하는 방법, 입력 끝을 처리하는 방법, 누락된 패딩을 허용할지 여부, 할당할 출력 바이트 수, 크기 제한을 알리는 방법 등 9가지 선택 사항을 애플리케이션에 맡깁니다. 이러한 선택은 두 RFC 4648 구현이 동일한 입력에 대해 동의하지 않을 수 있는 이유를 설명합니다. RFC를 한 번 읽어보세요. 테스트 벡터와 비교하여 구현을 확인하십시오. 귀하의 애플리케이션이 어떤 옵션을 사용하는지 명시하십시오. 가정이 아닌 실제 피어와의 상호 운용성을 테스트합니다.
RFC 이해 4648는 대부분의 Base64 분쟁을 해결합니다. 왜냐하면 불일치는 일반적으로 RFC 자체에 관한 것이 아니라 양측이 선택한 옵션에 관한 것이기 때문입니다. RFC는 한 시간 안에 끝까지 읽을 수 있을 만큼 간단합니다. 표준은 알파벳을 정의하고 테스트 벡터를 제공하며 구현 시 결정해야 할 사항을 경고합니다. Base64 인코더 및 디코더 도구를 사용하면 테스트 벡터를 실험하고 실제 표준 알파벳을 확인할 수 있습니다. 대부분의 일상적인 base64 사용에는 깊은 RFC 지식이 필요하지 않습니다. 그러나 인코딩 불일치를 디버깅하거나 익숙하지 않은 API와 통합할 때 표준을 한 번 읽으면 추측이 제거됩니다.
요약: 표준을 한 번 읽어 보세요. Base64 인코더 및 디코더를 사용하여 표준 알파벳의 테스트 벡터를 빠르게 확인할 수 있는 방법
RFC 4648는 수십 년간의 임시 기본 인코딩 방식을 하나의 읽기 가능한 사양으로 통합한 것입니다. base64를 언제 사용해야 하는지 정의하지 않습니다(MIME, PEM, JWT, 데이터 URI 등은 각각 고유한 사양을 갖습니다). 이는 base64가 무엇인지 정의합니다. 5개의 인코딩 계열을 정의하고 어떤 옵션이 정식인지 확인함으로써 RFC는 구현이 올바른지 확인할 수 있습니다. 신뢰할 수 있는 테스트 벡터가 출발점입니다. 구현이 foobar를 인코딩하고 Zm9vYmFy 이외의 것을 생성하는 경우 RFC는 구현이 잘못되었다고 말합니다.
해당 권한을 확인 체크포인트로 사용합니다. 각 RFC 테스트 벡터를 인코딩하고 정확한 문자를 비교한 다음 결과를 디코딩하여 원래 바이트가 변경되지 않은 상태로 반환되는지 확인합니다. 이 브라우저 기반 검사는 라이브러리 레이블에 의존하지 않고 표준 자체를 참조로 유지하면서 통합의 다른 부분에서 발생하는 문제로부터 알파벳 또는 패딩 실수를 분리합니다.