JWT 알고리즘: HS256과 RS256

JWT 알고리즘: HS256과 RS256

JWT 헤더의 alg 필드에 들어가는 값이 곧 서명 알고리즘을 가리켜요. 그중에서도 가장 많이 만나는 두 가지가 HMAC 기반의 HS256과 RSA 기반의 RS256이에요. 둘 다 SHA-256 해시를 쓰지만, 키의 성격과 누가 만들고 누가 검증하는지가 완전히 달라요. 어느 상황에 어떤 걸 써야 하는지 알려면 그 차이부터 보는 게 좋아요. 알고리즘 식별자와 동작은 RFC 7518(JSON Web Algorithms)이 정의해요.

출처: 공식문서 - RFC 7518 JSON Web Algorithms (JWA)

본문

HS256 — 대칭 키(비밀 키) HMAC

HMAC(Hash-based Message Authentication Code)은 **비밀 키(secret)**와 암호학적 해시 함수를 함께 써서 MAC을 만든다는 아이디어예요. MAC을 만든 쪽이 반드시 그 MAC 키를 소유하고 있었다는 걸 증명할 수 있어요.

JWA의 alg 값으로는 HS256, HS384, HS512가 있고, 각각 SHA-256, SHA-384, SHA-512 해시를 써요.

alg = HS256  →  HMAC using SHA-256
alg = HS384  →  HMAC using SHA-384
alg = HS512  →  HMAC using SHA-512

HMAC 키는 해시 출력과 같은 크기 이상이어야 해요. 예를 들어 HS256은 출력이 256비트이므로 키도 256비트 이상이어야 하고, HS384는 384비트 이상, HS512는 512비트 이상이어야 해요.

HS256의 특징은 발급과 검증이 같은 비밀 키를 공유한다는 점이에요. 서버 하나가 직접 발급하고 검증하는 단일 서비스 인증에 적합하지만, 키가 유출되면 토큰을 위조할 수 있다는 리스크가 있어요.

RS256 — 공개/개인 키 쌍(RSA) 디지털 서명

RS256은 RSASSA-PKCS1-v1_5 디지털 서명 알고리즘(RFC 3447의 PKCS #1)에 SHA-256을 결합한 방식이에요. 이 계열의 alg 값은 다음과 같아요.

alg = RS256  →  RSASSA-PKCS1-v1_5 using SHA-256
alg = RS384  →  RSASSA-PKCS1-v1_5 using SHA-384
alg = RS512  →  RSASSA-PKCS1-v1_5 using SHA-512

RSA 알고리즘에는 2048비트 이상의 키가 반드시 쓰여야 해요.

RS256은 개인 키로 서명하고 공개 키로 검증해요. 서명은 RSASSA-PKCS1-v1_5-SIGN과 SHA-256을, 서명자의 개인 키로 만들어요. 검증은 서명자의 개인 키에 대응하는 공개 키RSASSA-PKCS1-v1_5-VERIFY에 넘겨 수행해요.

이 구조 덕분에 인증 서버(발급자)는 개인 키를 지키고, 검증하는 각 서비스에는 공개 키만 배포하면 돼요. 여러 서비스가 같은 토큰을 검증해야 하는 분산 환경(예: 마이크로서비스)에서 RS256이 선호되는 이유예요.

어떤 알고리즘을 '반드시' 지원해야 하나

RFC 7519 §8은 준수 구현이 반드시(MUST) 구현해야 하는 것을 HS256none으로 규정하고, RS256ES256(ECDSA P-256 SHA-256)은 권장(RECOMMENDED)으로 둬요. 그 밖의 알고리즘과 키 크기는 선택(OPTIONAL)이에요.

보안 관점에서 none 알고리즘은 키 없이 서명을 생략하는 방식이라, 검증 쪽에서 반드시 허용하지 않도록 주의해야 해요. algnone으로 바꿔 서명 검증을 우회하는 공격(알고리즘 혼동)이 알려져 있어요.

더 알아보기