Base64를 Base64URL로 변환하는 방법
- 입력 · Base64에 Base64를 붙여넣으세요. 줄 바꿈된 Base64의 줄 바꿈과
data:...;base64,접두사는 자동으로 제거됩니다. - 출력 · Base64URL에 URL-safe 문자열이 나타납니다.
- 받는 쪽이 끝의
=를 유지하길 원하면 출력 아래의 패딩 (=) 을 선택하세요. - 출력 복사를 누르세요. Base64URL → Base64 전환이나 Base64URL을 Base64로를 쓰면 다시 되돌릴 수 있습니다.
입력을 바이트로 디코딩한 뒤 다시 인코딩하므로, 올바른 Base64가 아닌 문자열은 절반만 변환된 결과 대신 오류를 냅니다.
예시
| Base64 | Base64URL | 비고 |
|---|---|---|
PDw/Pz8+Pg== | PDw_Pz8-Pg | /와 + 치환, == 제거 |
eyJyb2xlIjoiYWRtaW4+In0= | eyJyb2xlIjoiYWRtaW4-In0 | >가 든 JSON, = 하나 제거 |
E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw+cM= | E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM | RFC 7636 부록 B의 PKCE challenge |
+/8= | -_8 | 바이트 fb ff |
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | 변화 없음: +, /, = 없음 |
마지막 행 같은 경우는 흔합니다. 짧은 JSON과 ASCII 텍스트는 +나 / 없이 인코딩되는 경우가 많고, 길이가 3바이트의 배수면 패딩도 없으므로 두 형식이 같아집니다. 그래서 변환을 깜빡해도 테스트에서는 드러나지 않다가, 어떤 값이 우연히 +나 /를 만들 때 비로소 문제가 됩니다.
URL을 깨뜨리는 표준 Base64 문자
표준 Base64의 세 문자는 URL에서 특별한 의미를 가집니다.
+는 쿼리 문자열에서 공백을 뜻하므로, 많은 프레임워크에서?t=a+b가a b로 전달됩니다./는 경로 구간을 나누므로, 경로에 든 Base64가 쪼개지거나 엉뚱하게 라우팅될 수 있습니다.=는 쿼리 파라미터의 이름과 값을 나누므로, 안전하려면%3D로 써야 합니다.
RFC 4648 5절은 이런 경우를 위해 Base64URL을 정의하며, +와 / 자리에 -와 _를 쓰고 패딩은 생략해도 됩니다. 이런 값은 경로, 쿼리 문자열, 쿠키, 파일 이름에서 이스케이프할 필요가 없습니다. 자세한 내용은 Base64와 Base64URL 비교 글에서 다룹니다.
Base64URL이 필요한 곳
- JWT와 JWS. JSON Web Token의 세 구간은 모두 패딩 없는 Base64URL을 씁니다. JWT 디코더로 읽을 수 있고, 형식은 JWT 속 Base64에서 설명합니다.
- OAuth PKCE. 해시 도구는 verifier의 SHA-256 다이제스트를 표준 Base64로 출력하는 경우가 많지만,
code_challenge는 그 다이제스트를 패딩 없는 Base64URL로 쓴 값이어야 합니다. 이 변환이 마지막 단계입니다. - WebAuthn과 JWK. 자격 증명 ID, challenge, JSON Web Key의 키 파라미터는 Base64URL입니다.
- 서명된 URL과 링크 속 토큰. 비밀번호 재설정 링크나 다운로드 링크처럼 값이 경로나 쿼리 문자열에 들어가는 경우입니다.
중간에 표준 형식을 거치지 않고 텍스트를 바로 Base64URL로 인코딩하려면 Base64URL 인코더를 사용하세요.
코드에서 Base64를 Base64URL로
import base64
base64.urlsafe_b64encode(b"<<???>>").rstrip(b"=").decode() # 'PDw_Pz8-Pg'
Buffer.from("PDw/Pz8+Pg==", "base64").toString("base64url"); // 'PDw_Pz8-Pg'
"PDw/Pz8+Pg==".replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); // same, without Buffer
Python의 urlsafe_b64encode는 패딩을 유지하므로 rstrip이 필요합니다. Node의 "base64url" 인코딩은 패딩을 제거합니다. 자세한 내용은 Python과 Node.js 가이드에 있습니다.
자주 묻는 질문
Base64URL로 변환하면 데이터가 바뀌나요?
아닙니다. 두 알파벳은 같은 바이트를 인코딩하며, 문자 두 개와 패딩만 다릅니다. 어느 형식을 디코딩해도 똑같은 바이트가 나옵니다.
변환할 때 = 패딩을 빼야 하나요?
받는 쪽에 맞추세요. JWT(RFC 7515)와 PKCE(RFC 7636)는 패딩이 없어야 합니다. 둘 다 받는 라이브러리도 있고, 일부 오래된 디코더는 패딩을 요구하는데, 그럴 때는 패딩 (=) 을 선택하세요.
정규식으로 Base64를 Base64URL로 바꿀 수 있나요?
네. JavaScript에서는 s.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "")입니다. 입력이 깨끗한 한 줄이라고 가정하므로, PEM 파일이나 이메일에서 가져왔다면 먼저 줄 바꿈을 제거하세요.
표준 Base64를 퍼센트 인코딩하는 것도 방법이 되나요?
되기는 하지만 +, /, =가 각각 세 글자인 %2B, %2F, %3D로 바뀌고, URL을 두 번 디코딩하거나 +를 공백으로 읽는 시스템에서는 여전히 값이 깨집니다. Base64URL에는 두 문제가 모두 없습니다.