Base64URL을 Base64로 변환하는 방법
- 입력 · Base64URL에 Base64URL을 붙여넣으세요. 패딩은 있어도 없어도 되고, 입력에 표준
+와/가 섞여 있어도 괜찮습니다. - 출력 · Base64에 표준 Base64가 나타납니다.
-와_는+와/로 바뀌고 패딩이 복원됩니다. - 출력 아래의 패딩 (=) 옵션은 기본으로 켜져 있습니다. 줄 바꿈으로 결과를 PEM용 64자나 MIME용 76자에서 줄 바꿀 수 있습니다.
- 출력 복사를 누르세요. Base64 → Base64URL 전환이나 Base64를 Base64URL로를 쓰면 반대 방향으로 변환합니다.
패딩을 얼마나 붙여야 하나
Base64는 4자 단위 그룹으로 작동합니다. Base64URL은 보통 마지막 그룹을 채우는 =를 빼고 쓰므로, 길이를 보면 몇 개를 되돌려야 하는지 알 수 있습니다.
| 길이 mod 4 | 붙일 패딩 | 예시 |
|---|---|---|
| 0 | 없음 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 (36자) |
| 2 | == | PDw_Pz8-Pg (10자)는 PDw/Pz8+Pg==가 됨 |
| 3 | = | eyJyb2xlIjoiYWRtaW4-In0 (23자)는 eyJyb2xlIjoiYWRtaW4+In0=가 됨 |
| 1 | 잘못된 값 | 남은 문자 하나로는 바이트 하나를 온전히 담을 수 없음 |
잘 알려진 예시 페이로드 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ는 70자로 나머지가 2이므로, 같은 문자열 뒤에 ==를 붙인 것이 됩니다. 자세한 원리는 패딩 가이드에 있습니다.
표준 Base64가 필요한 이유
많은 디코더가 표준 알파벳만 받으며, Base64URL을 넣으면 저마다 다른 방식으로 실패합니다.
- GNU coreutils의
base64 -d는 처음 나오는-나_직전까지 디코딩한 내용을 출력한 뒤base64: invalid input을 냅니다. - Java의
Base64.getDecoder()는IllegalArgumentException을 던집니다. URL-safe 입력에는Base64.getUrlDecoder()를 써야 합니다. - .NET의
Convert.FromBase64String은-,_, 빠진=에 대해FormatException을 던집니다. - Python의
base64.b64decode가 위험한 경우입니다. 기본적으로 표준 알파벳 밖의 문자를 오류 없이 버립니다.b64decode("PDw_Pz8-Pg==")는b'<<???>>'대신b'<<\x0f\xcf\xc3\xe0'를 돌려줍니다.
마지막 경우는 토큰을 다루는 코드라면 꼭 테스트해 볼 만합니다. 예외 없이 잘못된 바이트가 나오면 대개 한참 뒤에 서명 검증 실패나 데이터 손상으로 드러납니다.
코드에서 Base64URL을 Base64로
import base64
def b64url_to_bytes(s: str) -> bytes:
return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
b64url_to_bytes("PDw_Pz8-Pg") # b'<<???>>'
base64.b64encode(b64url_to_bytes("PDw_Pz8-Pg")).decode() # 'PDw/Pz8+Pg=='
-len(s) % 4는 빠진 =의 개수로, 올바른 입력이면 0, 1, 2 중 하나입니다. urlsafe_b64decode는 패딩이 있어야 하므로 호출 전에 붙입니다.
function b64urlToB64(s) {
const b = s.replace(/-/g, "+").replace(/_/g, "/");
return b + "=".repeat((4 - (b.length % 4)) % 4);
}
b64urlToB64("PDw_Pz8-Pg"); // 'PDw/Pz8+Pg=='
Node.js에서는 Buffer.from(s, "base64url").toString("base64") 한 번으로 같은 일을 합니다. 각 표준 라이브러리의 URL-safe 디코더는 Python, Java, C# 페이지를 참고하세요.
자주 생기는 문제
- “마지막 문자 그룹이 불완전합니다”. 길이를 4로 나눈 나머지가 1입니다. 문자열 일부가 사라진 것으로, 줄 바꿈에서 끊겼거나 URL이 잘린 경우가 많습니다.
- 입력에
.가 있음. JWT는 Base64URL 세그먼트 세 개를 점으로 잇습니다. 세그먼트를 하나씩 변환하세요. 토큰 전체는 JWT 디코더가 받습니다. - 문자열에
%3D가 있음. Base64URL 위에 퍼센트 인코딩이 더해진 값입니다. 먼저 URL 디코딩으로 디코딩하세요.
자주 묻는 질문
Base64URL에 패딩을 다시 붙이려면 어떻게 하나요?
끝에 =를 붙여 길이를 4의 배수로 맞추세요. 나머지가 2이면 두 개, 3이면 한 개입니다. 올바른 데이터에서 나머지가 1인 경우는 생기지 않습니다. 이 변환기가 알아서 처리해 줍니다.
JWT에서 base64 -d가 실패하는 이유는 무엇인가요?
GNU base64 -d는 표준 알파벳만 알기 때문에 처음 나오는 -나 _에서 invalid input을 내고 멈춥니다. 먼저 여기서 세그먼트를 변환하거나, URL-safe 알파벳을 읽는 basenc --base64url -d를 사용하세요.
문자열에 문자가 하나 더 많으면 어떻게 되나요?
길이를 4로 나눈 나머지가 1인 Base64URL 문자열은 잘렸거나 문자가 하나 더 들어간 것입니다. 변환기가 마지막 그룹이 불완전하다고 알려 주므로 값을 어떻게 복사했는지 확인하세요.
JWT를 읽으려면 표준 Base64가 필요한가요?
이 사이트에서는 필요 없습니다. JWT 디코더와 Base64URL 디코더는 Base64URL을 바로 읽습니다. 다른 도구나 라이브러리가 표준 Base64만 받을 때 변환하세요.