Base64 문자열 디코드 방법 (그리고 JWT 페이로드)

Base64는 가역적 인코딩일 뿐 암호화가 아닙니다. 한 단계로 디코드하고 Unicode를 올바르게 처리하며 Base64url을 사용하는 JWT 섹션을 읽습니다.

Base64는 사실 무엇인가

Base64는 바이너리 데이터를 64개의 인쇄 가능한 ASCII 문자에 매핑합니다. 키 없이 완전히 가역적이므로 암호화가 아니라 인코딩입니다 — 비밀을 「숨기는」 용도로는 절대 사용하지 마세요.

인코딩과 디코딩

브라우저에서는 btoa로 인코딩하고 atob로 디코딩합니다. 비 ASCII 텍스트는 UTF-8로 한 번 왕복시키세요. 그래야 é, ü, 你 같은 문자가 깨진 바이트로 변하지 않습니다.

JWT 읽기

JWT는 점으로 이어진 세 개의 Base64url 섹션 — header, payload, signature — 로 이루어집니다. 앞의 두 개를 디코딩하면 claim을 읽을 수 있습니다. signature는 바이너리라 사람이 읽도록 만들어진 게 아닙니다.

Base64와 Base64url의 차이

표준 Base64는 +와 /를 사용하고 =로 패딩합니다. URL 안전 변종인 Base64url은 그것들을 -와 _로 바꾸고 패딩을 제거하므로, 그 값을 URL과 JWT 안에 안전하게 넣을 수 있습니다.

디코딩은 검증이 아니다

JWT를 디코딩하면 claim은 보이지만 진위 여부는 전혀 보장되지 않습니다. payload에 "role":"admin"이라고 적힌 token은 누구나 위조할 수 있습니다. 발급자의 키로 검증한 서명만이 token이 진짜임을 증명합니다. 검증되지 않은 token을 근거로 신뢰 결정을 내리지 마세요.

흔한 JWT 클레임과 그 의미

iss는 발급자, sub는 주체(사용자 ID), aud는 의도한 audience, exp는 만료(Unix 초), iat는 발급 시각, nbf는 «not before», jti는 고유 ID입니다. 사용자 정의 claim은 이것들과 나란히 들어갑니다. exp와 aud는 클라이언트뿐 아니라 반드시 서버 쪽에서도 확인하세요.

패딩과 URL 안전 변형

Base64url은 보통 = 패딩 없이 도착합니다. 코드에서 디코딩하려면 길이를 =로 4의 배수로 맞춘 뒤, -를 +로 _를 /로 바꾸고 일반 Base64 디코더를 돌리세요. 브라우저의 atob는 Base64url을 직접 받지 않으므로 변환을 먼저 해야 합니다.