암호화, signing, verification 그리고 JWT

xxziiko·2025년 3월 6일

[Network]

목록 보기
6/8
post-thumbnail

1. 암호화(Encryption)

데이터를 보호하기 위해 원본 데이터를 읽을 수 없는 형태로 변환하는 과정

  • 네트워크에서 데이터가 전송될 때, 암호화를 통해 데이터를 보호한다.
  • 예를 들어, HTTPS 프로토콜을 사용할때 브라우저와 서버간의 통신은 TLS(Transport Layer Security)를 통해 암호화되며 이를 통해 제 3자가 네트워크 트래픽을 가로채더라도 데이터를 읽을수 없도록 보호한다.
  • 암호와의 주요 목표는 데이터의 기밀성을 유지하는 것.
    • 대칭키 암호화: 하나의 키를 사용하여 데이터를 암호화하고 복호화한다.
      • AES(Advanced Encryption Standard)가 대표적인 대칭키 암호화 알고리즘
    • 비대칭키 암호화: 공개키와 비밀키 두 개의 키를 사용
    • 한 키로 암호화하면 다른 키로만 복호화 할 수 있다.
      • RSA와 ECC(Elliptic Curve Cryptography)


2. 서명(Signing)

데이터를 생성한 발신자가 자신의 비밀키를 사용하여 메시지나 문서에 디지털 서명을 추가하는 과정

  • 데이터가 신뢰할수 있는 출처에서 온 것임을 증명하고, 전송 과정에서 변조되지 않았음을 확인하는 데 사용된다.
  • 진위성 보장: 서명을 통해 수신자는 데이터가 신뢰할 수 있는 발신자로부터 온 것임을 확인할 수 있다.
  • 무결성 검증: 서명된 데이터는 전송 과정에서 변경되었는지 여부를 확인할 수 있다. 변경되었다면 서명은 유효하지 않는다.
  • 비대칭 암호화: 일반적으로 비대칭 암호화 방식을 사용하여 서명을 생성하고 검증한다. 발신자는 자신의 비밀키로 데이터를 서명하고, 수신자는 발신자의 공개키로 서명을 검증한다.
  • 예를 들어, 이메일이나 소프트웨어 배포 시 서명을 통해 수신자는 데이터의 출처를 검증하고 무결성을 확인


3. 검증(Verification)

서명된 데이터를 받은 수신자가 해당 데이터의 무결성과 출처를 확인하기 위해 발신자의 공개키를 사용하여 서명의 유효성을 검사하는 과정

검증과정

  • 서명 복호화: 서명을 공개키로 복호화하여 원본 해시값을 복원
  • 해시 비교: 복원된 해시값과 메시지에서 재계산된 해시값을 비교하여 서명 유효성을 검증
  • 네트워크 상에서 받은 데이터나 메세지가 신뢰할 수 있는 출처로부터 온 것인지 확인하는 데 사용한다.
  • 예를 들어, 서버와 클라이언트 간의 인증 과정에서 사용자의 인증 정보를 검증하거나, 소프트웨어 업데이트 시 서명을 검증해 안전한지 확인


암호화(Encryption) vs 서명(Signing)의 차이는?

  • 암호화는 데이터 기밀성을 보호하는 목적이고 서명은 데이터 무결성과 신뢰성을 보장한다.
  • 암호화는 내용을 숨기는 방식이고, 서명은 변조 여부를 확인하는 방식이다.
  • 암호화는 승인된 사용자만 복호화가 가능하며 서명은 비밀키로 서명 & 공개키로 검증하여 변조를 방지, 발신자의 신원을 인증하는 기능도 포함된다.

즉, 암호화기밀성(confidentiality), 서명무결성(integrity)인증(authentication)을 보장한다.



JWT(JSON Web Token)

사용자 인증 및 정보 전달을 위한 웹 표준 토큰

  • 서버와 클라이언트 간에 신뢰할 수 있는 정보를 Header방식을 사용하여 전송.

구성 요소

  • Header: 토큰의 타입(JWT)과 서명 알고리즘 정보를 포함
  • Payload: 사용자 ID와 같은 클레임(Claims)을 포함하여, 서버에서 필요로 하는 사용자 정보를 저장
  • Signature: Header와 Payload를 비밀키로 서명하여, 토큰의 무결성(데이터 변조 방지)을 검증

JWT 특징

  • stateless한 특성을 유지할 수 있다.
  • 거의 모든 요청에 토큰이 포함되므로 트래픽 크기에 영향을 미칠 수 있다.
  • 토큰에 정보가 많아져서 토큰의 크기가 커진다면 네트워크에 부하를 줄 수 있다.
  • 페이로드는 암호화되지 않고 BASE64로 인코딩 된 것이기 때문에 중요한 정보를 담아서는 안된다. (누구나 디코딩하여 확인이 가능하기 때문)
  • 확장성에 유리하며 MSA 환경에 적용하기 편하다
    • 웹 어플리케이션의 서버 확장 방식은 수평 확장이다. → 한 대가 아닌 여러 대의 서버가 요청을 처리하는 방식
    • 이 때 별도의 작업이 없다면 세션 기반 인증 방식은 세션 불일치 문제를 겪을 수 있다.
    • 토큰 기반 인증 방식서버가 직접 인증을 저장하지 않고 클라이언트가 저장하는 방식이기 때문에 이러한 세션 불일치 문제로부터 자유롭다.

동작 원리

  1. 사용자가 로그인하면, 서버는 사용자 정보를 포함한 JWT를 생성하여 클라이언트에 전달한다.

  2. 클라이언트는 JWT를 LocalStorage 또는 쿠키에 저장하여 요청 시 JWT를 Authorization 헤더에 포함하여 서버에 보낸다.

    Authorization: Bearer <JWT_TOKEN>
  3. 서버는 전달받은 JWT를 검증하여 요청을 처리한다.

    • 서명이 유효한지, 발신자가 신뢰할 수 있는지 확인
    • 유효기간이 만료되지 않았는지 확인

JWT는 Stateless(무상태) 인증을 지원하므로, 서버는 별도의 세션 저장소가 필요 없다.

다만, 인증에 필요한 정보가 토큰에 있기에 별도의 저장소가 필요 없지만 보안성을 높이기 위해 Refresh Token을 사용하는경우에는 별도의 저장소에 저장하여 사용할 수도 있다. (stateless하지 않을 수 있음) 하지만 JWT는 토큰이 만료되었을 때만 저정소에 접근하기 때문에 접근하는 횟수는 적다.



JWT와 암호화

  • JWT는 서명을 사용하여 데이터의 무결정을 보장한다.
    • 헤더와 페이로드를 JSON 문자열로 결합하고 결합된 문자열을 해싱 알고리즘을 사용하여 해시 값으로 변환
    • 해시 값을 비밀 키 또는 개인키로 암호화하여 서명을 생성
  • JWT는 서명(Signing)으로 무결성을 보장하지만, 페이로드가 암호화되는 것은 아니다. 만약 민감한 데이터를 JWT에 포함해야 한다면, JSON Web Encryption(JWE)를 사용하여 페이로드까지 암호화하는 방식을 고려해야 한다.

JWT를 쿠키에 저장할 수도 있다.

  • JWT는 기본적으로 Header 방식을 통해 클라이언트-서버 간 토큰을 주고 받는다.
  • Authorization 헤더에 포함되어 HTTP 요청과 함께 서버로 전송한다.
  • 보안 강화를 위해 쿠키에 저장하여 사용하는 방식으로도 사용된다.
  • 서버에서 JWT를 생성해 쿠키로 보내거나, Header방식으로 받은 쿠키를 클라이언트에서 쿠키에 저장할 수도 있다.

서버에서 HTTP 헤더로 응답 보낼 때

Set-Cookie: token=JWT_TOKEN; HttpOnly; Secure; SameSite=Strict
  • HttpOnly; Secure; SameSite=Strict 옵션이 필요
  • SameSite=Strict가 없으면 다른 사이트에서 CSRF 공격 가능

클라이언트에서 쿠키를 설정하는 방식

document.cookie = "token=<JWT_TOKEN>; HttpOnly; Secure";


공식문서(RFC 6750)에서 Authorization Header 방식을 권장하는 이유

공식문서에서 언급한 Authorization 헤더를 사용하는 이유

  1. 보안 강화
  • 쿠키 기반 인증은 CSRF 공격에 취약할 수 있지만, Authorization 헤더 방식은 CSRF 영향을 받지 않는다.
  • 쿠키 기반 방식도 CSRF 토큰과 SameSite 속성을 활용하면 보안성을 확보할 수 있지만, API 인증 방식에서는 Authorization 헤더가 더 유연하다.

RFC 6750에서 Authorization 헤더를 권장하는 이유 중 하나는 CSRF 공격을 방어하는 데 유리하기 때문이다. 하지만 쿠키 기반 인증도 CSRF Token과 SameSite 속성을 적절히 활용하면 보안성을 확보할 수 있다. 다만, Authorization 헤더 방식이 쿠키 정책에 영향을 받지 않아, API를 여러 도메인에서 활용할 때 더 유연하다.

  1. 캐싱 문제 방지
  • Authorization 헤더 방식은 기본적으로 캐싱되지 않음.
  • 쿠키는 기본적으로 캐시될 가능성이 있어, 서버에서 Cache-Control: no-store 등의 설정이 필요하다.
  1. HTTP 표준 준수
  • Authorization 헤더를 사용하는 것은 HTTP 표준에 부합(stateless 특징)하며, 이는 서버와 클라이언트 간의 일관된 인증 방식을 제공
    RFC 6750에서 권장하는 Authorization 헤더 방식은 기본적으로 Stateless한 Access Token을 사용하는 것.

쿠키방식으로도 JWT를 사용하여 Stateless한 구조를 설계할 수 있다. 그러나 현실적인 구현에서는 토큰 재발급(Refresh Token)을 활용하게 되고, Refresh Token을 안전하게 관리하기 위해 서버에 저장하는 경우도 있으며, 이를 통해 세션 기반 인증과 유사한 일부 Stateful한 요소가 포함될 수 있다.

따라서 보안을 고려한다면 헤더방식, 쿠키방식 모두 완전한 Stateless 구조를 유지하기는 어렵고, 일부 Stateful한 구조를 갖게 될 수 밖에 없다.

ref.
https://jwt.io/
https://oauth.net/2/bearer-tokens/

0개의 댓글