JWT 서명자 및 검증기

자신의 키로 토큰에 서명하고, 비밀키, PEM, JWK 또는 실시간 JWKS로 토큰을 검증하며, API가 게시할 키 집합을 만드세요. 모든 암호화 연산은 브라우저에서 이루어집니다.

JWT는 서명만큼만 믿을 수 있습니다. 누구나 토큰을 읽을 수 있습니다 — 디코딩은 아무것도 증명하지 않습니다 — 그래서 이 도구는 디코더가 할 수 없는 일을 합니다. 사용자의 키로 토큰에 서명하고(HS256/384/512, RS256/384/512, ES256/384/512, EdDSA), 비밀키, PEM 또는 JWK 공개 키, 붙여넣은 JWKS, kid 매칭이 되는 실시간 JWKS URL로 토큰을 검증하며, 사용자의 API가 게시할 JWKS를 만듭니다. 함께 제공되는 가이드 JWT 서명 및 검증은 디코딩이 검증이 아닌 이유, 알고리즘 혼동 공격의 원리, 그리고 "검증됨"이 증명하는 것과 증명하지 못하는 것을 설명합니다. 키 없이 토큰을 읽으려면 JWT 디코더를, 키 자체에 대해서는 생성과 변환을 다루는 SSH 키 제품군을 사용하세요.

마지막 업데이트:

토큰 서명

🔒 서명과 검증은 WebCrypto를 이용해 로컬에서 이루어집니다. 비밀키와 개인 키는 전송되지도, 저장되지도, 기록되지도 않습니다. 페이지를 새로고침하면 사라집니다.

키가 이 페이지를 떠나는 일은 없습니다

서명과 검증은 여기에 붙여넣거나 생성한 키를 이용해 브라우저의 WebCrypto로 수행됩니다. 비밀키와 개인 키는 페이지 메모리에만 존재합니다. 업로드되지 않고, localStorage나 쿠키에 기록되지 않으며, URL에 들어가지도 않습니다. 페이지를 새로고침하거나 닫으면 사라집니다. 유일한 예외는 사용자가 직접 시작하는 JWKS URL 가져오기입니다. 입력한 URL만 전송되어 공개 키를 가져올 뿐, 비밀키는 절대 전송되지 않습니다. 운영 키를 어디에든 붙여넣기 전에 JWT 서명 및 검증을 읽어 보세요.

솔직한 한계

EdDSA에는 최신 브라우저가 필요합니다. WebCrypto Ed25519는 구형 브라우저에 없으며, 이 페이지는 서명을 흉내 내는 대신 그 사실을 솔직하게 밝힙니다. 어디에서나 동작하는 대체 수단은 ECDSA P-256입니다.

암호화된 PEM(암호로 잠긴 개인 키)은 버전 1에서 지원되지 않습니다. 이 페이지는 이를 공개적으로 거부합니다. 먼저 openssl pkcs8 -topk8 -nocrypt로 복호화하세요. 암호를 웹 페이지에 붙여넣으면 안 됩니다.

JWKS URL 가져오기는 해당 서버가 CORS 헤더를 보내느냐에 달려 있습니다. 많은 ID 공급자가 보내지만, 보내지 않는 경우 가져오기가 솔직하게 실패하고 페이지는 JWKS를 붙여넣으라고 안내합니다. 가져오는 것은 공개 키뿐입니다. JWKS URL에는 비밀이 실리지 않습니다.

서명이 디코딩을 이길 때

JWT를 디코딩하는 것은 읽는 것입니다. 헤더와 페이로드는 base64url이며, 토큰을 가진 사람은 누구나 둘 다 볼 수 있습니다. 그래서 디코더만으로는 정말 중요한 단 하나의 질문에 답할 수 없습니다. 발급자가 정말 서명했는가? 서명은 그 일의 나머지 절반입니다. 개인 키(또는 HMAC 비밀키)를 가진 사람이 서명을 만들고, 검증은 공개 키로 같은 수학을 다시 수행합니다. 이 페이지는 두 절반을 모두 브라우저에 둡니다. 관련된 키는 웹 도구가 다루는 가장 민감한 입력이기 때문입니다.

이 구분은 비대칭 알고리즘에서 가장 중요합니다. HS256에서는 검증하는 비밀키와 서명하는 비밀키가 같습니다. 토큰을 확인할 수 있는 사람은 누구나 토큰을 만들 수도 있습니다. 하나의 서비스 안에서는 괜찮지만, 그 밖에서는 유출입니다. RS256, ES256, EdDSA에서는 서명 키가 발급자에게 머물고 공개 키만 이동합니다. API는 JWKS를 게시하고, 새 kid를 추가해 키를 교체하며, 전 세계의 모든 검증자가 위조할 힘은 전혀 갖지 않은 채 토큰을 확인하게 할 수 있습니다.

이 도구가 거부하는 것

두 가지 거부는 의도적입니다. 첫째는 alg: none입니다. 서명이 필요 없다고 주장하는 토큰은 이유와 함께 전면 거부됩니다. 이를 받아들이는 검증자는 위조를 받아들입니다. 둘째는 알고리즘 혼동입니다. HMAC 비밀키로 제공된 RS256 토큰(또는 그 반대)은 명시적 경고와 함께 실패하며, 키를 다른 계열로 조용히 재해석하지 않습니다. 둘 다 고전적인 JWT 공격이며, 둘 다 구조적으로 차단됩니다. 키 계열은 토큰의 alg 계열과 일치해야 하며, 그렇지 않으면 검증이 실패합니다.

세 번째 거부는 더 미묘합니다. 이 페이지는 토큰이 "신뢰할 수 있다"고 절대 말하지 않습니다. 유효한 서명은 토큰이 어떤 키로 서명되었다는 것, 만료 검사는 유효 기간 안에 있다는 것을 증명할 뿐입니다. 그 키를 신뢰할지는 키가 어디에서 왔는지에 대한 판단입니다. ID 공급자의 잘 알려진 URL에서 가져온 JWKS, 직접 고정한 공개 키, 직접 생성한 비밀키. 가이드 JWT 서명 및 검증은 "검증됨"이 증명하는 것과 증명하지 못하는 것을 설명합니다.

JWT 용어, 정확히 짚고 넘어가기

JWT. JSON Web Token(RFC 7519): 당사자 간에 클레임을 전달하는 간결하고 URL 안전한 방식 — header.payload.signature, 각각 base64url로 인코딩됩니다. 페이로드는 누구나 읽을 수 있으며, 비밀에 의존하는 것은 서명뿐입니다.

JWS. JSON Web Signature(RFC 7515): JWT의 바탕이 되는 서명 형식입니다. JWT는 페이로드가 JSON 클레임 집합인 JWS입니다.

JWK. JSON Web Key(RFC 7517): 하나의 암호 키를 나타내는 JSON 객체 — kty, 그리고 키 재료(RSA의 n/e, EC의 x/y, Ed25519의 x, 공유 비밀키의 k).

JWKS. JSON Web Key Set: "keys" 배열을 가진 객체 — 발급자가 공개 키를 게시하는 표준 방식이며, 보통 /.well-known/jwks.json에 있습니다.

kid. 키 ID: 어떤 키가 토큰에 서명했는지를 말해주는 헤더 클레임입니다. 검증자는 이를 JWKS와 대조합니다. kid가 없으면 집합에 키가 하나일 때 그 키가 사용되며, 페이지는 그 사실을 밝힙니다.

alg. 서명 알고리즘을 지정하는 헤더 클레임(HS256, RS256, ES256, EdDSA…). 검증자는 받아들일 알고리즘을 고정해야 합니다. 토큰 자신의 alg 클레임을 신뢰하는 것이 혼동 공격입니다.

HMAC. Hash-based Message Authentication Code: 대칭 서명 — 같은 비밀키로 서명하고 검증합니다. 빠르고 단순합니다. 비밀키를 가진 사람은 누구나 토큰을 만들 수 있습니다.

RSASSA-PKCS1-v1_5. RS256/384/512의 바탕이 되는 RSA 서명 방식: 해시를 감싸 개인 지수로 거듭제곱합니다. 결정적입니다. 같은 입력은 항상 같은 서명 바이트를 만듭니다.

EdDSA. Edwards-curve Digital Signature Algorithm: 여기서는 Ed25519 — 작은 키, 빠른 검증, 결정적 서명입니다. WebCrypto 지원을 위해 최신 브라우저가 필요합니다.

자주 묻는 질문

이 페이지에 개인 키를 붙여넣어도 안전한가요?

이 페이지에서는 키가 브라우저를 절대 떠나지 않습니다. 서명은 WebCrypto로 페이지 메모리에서 실행되며, 아무것도 업로드되거나 저장되거나 기록되지 않고, 새로고침하면 지워집니다. 위험한 패턴은 서버 측 서명기입니다. 개인 키가 네트워크를 건너기 때문입니다. 로컬에서도 신뢰하는 기기를 사용하세요. 공용 기기에서 운영 키를 붙여넣었다면 노출된 것으로 취급하세요. 실제 키를 붙여넣는 대신 여기서 테스트 키를 생성하세요.

제 RS256 토큰이 비밀키로 검증되지 않는 이유는 무엇인가요?

비밀키와 RSA 키는 다른 계열이며, 이 페이지는 둘을 섞는 것을 거부합니다. 그 거부가 바로 알고리즘 혼동 방지 장치입니다. RS256 토큰에는 발급자의 RSA 공개 키(PEM, JWK 또는 JWKS)가 필요합니다. 비밀키로는 HS256/384/512만 검증할 수 있습니다. 공개 키가 잘못된 형태라면 변환하세요. JWKS 탭에서 PEM ⇄ JWK 변환이 가능합니다.

JWKS URL 가져오기는 실제로 무엇을 전송하나요?

입력한 URL로 JSON을 요청하는 GET 요청 한 번입니다. 키도, 비밀키도, 토큰도, 식별자도 함께 가지 않습니다. 응답은 공개 키 집합입니다. 서버가 CORS 헤더를 보내지 않으면 브라우저가 읽기를 차단하고, 페이지는 JWKS를 붙여넣으라고 안내합니다.

여기서는 토큰이 검증되는데 API가 거부합니다. 왜 그런가요?

여기의 검증은 제공한 키에 대해 서명과 시간 창을 확인합니다. API는 클레임도 확인합니다. 기대하는 발급자(iss), 서비스하는 대상(aud), 현재 신뢰하는 키 ID(kid)입니다. 교체되어 빠진 키로 서명된 토큰이나 다른 대상을 위해 만들어진 토큰은 수학적으로는 검증되지만 정당하게 거부됩니다.

제 브라우저에서 EdDSA가 동작하지 않습니다. 어떻게 해야 하나요?

Ed25519에는 최신 브라우저가 필요합니다. 구형 브라우저에는 WebCrypto Ed25519가 아예 없으며, 이 페이지는 흉내 내는 대신 그 사실을 밝힙니다. 대체 수단으로 ES256(ECDSA P-256)을 사용하세요. WebCrypto가 있는 곳에서는 어디서나 지원되며, 이 페이지가 키를 생성해 줄 수 있습니다. Ed25519를 꼭 써야 한다면 브라우저를 업데이트하세요.