HMAC•RSA 알고리즘을 사용한 JWT Signature

2025. 4. 6. 01:32·CS

참여하고 있는 스터디에서 위 주제로 간단한 세션 발표를 진행하게 되어, 관련하여 글을 준비하게 되었다.😵

 

글의 목표는 다음과 같다.

  • JWT 서명(Signature)에 대해 간략히 리뷰한다.
  • HMAC / RSA 알고리즘을 사용해 JWT 서명을 생성하고 검증하는 과정을 이해한다.
  • 분산 환경에서 JWT를 어떻게 검증할 수 있을지 알아본다.

 


1. JWT Signature

  • JWT의 세 번째 구성 요소
  • Base64 URL 인코딩 된 Header + Payload를 secret key로 암호화 한 값
    • 무결성: Payload의 위조 여부 확인
    • 신뢰성: 누가 보냈는지 인증 가능

 

 

 

 

 

 

 

 

 

 

 

 


2. JWT Signature 생성

- HS256

 

 

1. 개념

  • HS256은 HMAC 방식 + SHA-256 해시 함수를 사용한 알고리즘
    • HMAC (Hash-based Message Authentication Code)
      • JWT의 위변조 되었는지 검증하기 위해, 비밀키를 해싱 과정에 추가
      • 독립적인 암호화 알고리즘이라기보다는 해시 알고리즘을 확장한 알고리즘
    • SHA256 (Secure Hash Alogrithm 256bit)
      • 입력값을 32 byte 고정된 길이의 해시값으로 변환하는 단방향 해시 알고리즘
  • 즉, 데이터 암호화가 아닌 데이터의 무결성을 확인하는 알고리즘이다.

 

 

2. 서명 생성 (송신자)

  • Base64 URL 인코딩 한 Header와 Payload를 입력값으로, 비밀키(my-secret-key)를 대칭키로 활용해 HMAC-SHA256 해시 값을 계산한다.
    • 입력: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0
    • 비밀 키: my-secret-key
    • 결과: HMAC-SHA256 해시 값
  • 결과 해시 값을 Base64 URL 인코딩을 하면 JWT 서명(Signature)이 만들어진다.
  • 이를 조합한 JWT는 다음과 같다.
    • eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Base64UrlEncode(해시 값)

 

 

3. 서명 검증 (수신자)

  • 송신자와 같은 방식으로 JWT의 Header와 Payload를 결합
  • 동일한 비밀 키(my-secret-key)를 사용해 HMAC-SHA256 알고리즘으로 해시 값을 계산
  • 계산된 해시 값과 JWT Signature와 일치하면 유효한 토큰으로 인정

 


 

- RS256

 

1. 개념

  • RS256은 RSA 비대칭키 서명 + SHA-256 해시 함수를 사용한 서명 알고리즘이다.
    • RSA
      • 공개키와 개인키 쌍을 사용하는 비대칭키 암호화 알고리즘
    • SHA256 (Secure Hash Alogrithm 256bit)
      • 입력 데이터를 32 byte 고정된 길이의 해시값으로 변환하는 단방향 해시 알고리즘
    •  

 

 

2. 서명 생성 (송신자)

  • Base64 URL 인코딩 한 Header와 Payload를 입력값으로, 개인키를 사용해 RSA-SHA256 알고리즘으로 해시 값을 계산
    • 입력: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0
    • 비밀 키: private-key
    • 결과: SHA256 해시 값
  • 이 해시 값을 다시 Base64 URL 인코딩을 하면 JWT 서명(Signature)이 만들어진다.

 

 

3. 서명 검증 (수신자)

  • 신자와 같은 방식으로 JWT의 Header와 Payload를 결합
  • 송신자가 제공한 공개키를 사용해 RSA-SHA256 알고리즘으로 서명을 복호화하여 해시 값 계산
  • 계산된 해시 값과 JWT Signature와 일치하면 유효한 토큰으로 인정

 

 


3. 분산 환경에서의 JWT 검증

하나의 단일 서버 환경에서는 문제 없이 JWT를 검증할 수 있다.

하지만 분산 환경에서는 JWT를 발급하는 주체와 검증하는 주체가 서로 다른 경우가 생긴다.

이 때, JWT의 서명을 안전하게 검증할 수 있는 구조가 필요하다.

 

- 대칭키 방식

1. 동작 원리

  • 모든 서버가 동일한 대칭키(secret key)를 공유하여 JWT를 생성하고 검증한다.

 

2. 분산 환경에서의 문제점

  • 모든 서버에 동일한 secret key를 배포해야 함
  • 키 유출 시, 위조된 JWT 생성 가능
  • 키를 변경하는 것이 어려움

 


 

- 비대칭키 방식

1. 동작 원리

  • 인증 서버는 개인키로 JWT를 생성한다.
  • 검증 서버들은 공개키만으로 검증한다.

 

2. 분산 환경에서의 이점

  • 공개키는 안전하게 공유 가능 → 검증 서버가 많아도 문제 없음
  • 개인키는 하나의 발급 서버에만 보관
  • 키 교체도 안전하게 진행 가능 (JWK + kid)

 

 

3. JWKS & 키 교체 (Key Rotation)

  • 인증 서버는 공개키를 JWKS(JSON Web Key Set) 형태로 공개한다.
    • https://your-auth-server.com/.well-known/jwks.json 와 같은 URL로 공개
  • 검증 서버는 JWK Set에서 JWT의 kid 필드를 참조해, JWKS에서 해당 키를 찾아 서명 검증한다.
  • 이를 통해 비대칭키 교체를 유연하게 할 수 있다.
// 새로운 JWT 시 rsa-key-2 개인키 사용
{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "rsa-key-2"
}


// JWK (Json Web Key)
{
  "keys": [
    {
      "kty": "RSA",
      "kid": "rsa-key-1",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    },
    {
      "kty": "RSA",
      "kid": "rsa-key-2",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    }
  ]
}

 

 


4. 그럼 어떤 방식을 선택할 수 있을까?

단일 서버 환경에서는 대칭키 기반의 HS256 알고리즘을 사용하는 것이 충분하다.

하나의 서버가 JWT를 생성하고 검증까지 담당하므로, 비밀 키를 외부에 노출하거나 여러 서버 간 키를 공유할 필요가 없기 때문이다.

 

그러나 서버가 여러 대로 구성된 분산 환경에서는 모든 서버에 동일한 비밀 키를 배포해야 되고, 이 과정에서 키가 유출될 경우 보안 사고로 이어질 수 있다. 또한 비밀 키를 교체 시, 교체된 비밀 키를 배포하는 과정에서 다시 유출 위험에 노출된다.


하지만 비대칭키 기반의 RS256 알고리즘을 사용하면, JWT 생성은 개인키로 수행하고 검증은 공개키만으로 할 수 있어 키 관리가 매우 편해진다. 공개키는 검증 서버에 안전하게 배포할 수 있고, 개인키는 오직 인증 서버만 보관하면 된다. 또한 JWKS를 통해 공개키를 인증 서버에서 통합적으로 관리하고, kid를 이용해 키 교체도 유연하게 할 수 있다.

결론적으로,

  • 단일 서버 → HS256으로 간편하게 구성하고
  • 분산 서버 → RS256 + JWKS로 안정성과 확장성 확보하자!
저작자표시 (새창열림)

'CS' 카테고리의 다른 글

대칭키와 비대칭키  (0) 2025.04.05
'CS' 카테고리의 다른 글
  • 대칭키와 비대칭키
wch_t
wch_t
  • wch_t
    끄적끄적(TIL)
    wch_t
  • 글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기 (170)
      • Architecture (0)
      • Algorithm (67)
        • Math (5)
        • Simulation (1)
        • Data Structure (4)
        • DP (7)
        • Brute Fource (10)
        • Binary Search (6)
        • Greedy (2)
        • Graph (11)
        • Mst (1)
        • Shortest path (10)
        • Two Pointer (1)
        • Tsp (3)
        • Union Find (2)
        • Mitm (1)
      • CS (2)
        • 데이터베이스 (5)
        • 네트워크 (5)
      • DB (6)
      • DevOps (17)
        • AWS (9)
        • Docker (1)
        • CI-CD (5)
      • Error (1)
      • Project (0)
        • kotrip (0)
      • Spring (59)
        • 끄적끄적 (5)
        • 기본 (9)
        • MVC 1 (7)
        • MVC 2 (11)
        • ORM (8)
        • JPA 1 (7)
        • JPA 2 (5)
        • Spring Data Jpa (7)
      • Test (2)
      • TIL (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    애플
    docker
    TempTable
    spring-cloud-starter-aws-secrets-manager-config
    response_mode
    Sxssf
    Jenkins
    docker: not found
    백준 17299 파이썬
    apache poi
    spring-cloud-starter-bootstrap
    form_post
    aws secrets manager
    scope
    Merge
    view algorithm
    백준 17289 파이썬
    백준 3015 파이썬
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
wch_t
HMAC•RSA 알고리즘을 사용한 JWT Signature
상단으로

티스토리툴바