JWA( JSON Web Algorithms )

뾰족머리삼돌이·2024년 11월 8일
0

Spring Security

목록 보기
13/16

프로젝트에서 사용자 인증 구현을 맡았을 때, REST API를 목표로 삼고 JWT 인증을 선택했다.
당시에는 서버에서 세션을 사용하지 않고, 토큰을 주고받으며 검증하는 인증방법이라는 정도만 이해하고 있었기때문에 구글링을 포함하여 찾아낸 정보를 바탕으로 JWT생성 코드를 작성했다.

그러나, 코드를 작성하는 와중에서 한 문제점에 직면했던 기억이 있다.

바로, JWT의 Signature 부분 생성에 필요한 암호화 알고리즘(JWA) 를 선택하는 부분이었다.
HS256, RS256, PS256 ... 각 암호화 알고리즘이 어떤 이점이 있고, 무엇을 기준으로 판단해야할지 몰랐기에 참고하고있던 자료에서 사용한 알고리즘을 그대로 사용했던 기억이 있다.

현재에 이르러서는 JWT 구조를 학습하면서 해당 선택이 JWA를 선택하는 것이며,
이것이 JWT의 Signature 생성에 사용된다는 사실을 이해하게 되었다.

이번 포스팅에서는 각 암호화 알고리즘 방식에 어떤 차이가있고, JWS에서 사용하는 알고리즘은 무엇이 다른지에 대해 알아볼 생각이다.

간략하게 개념 느낌으로 알아볼 생각이다

JWA

JWT( JSON Web Token )는 총 3가지 파츠로 구분된다.

  • 토큰의 정보를 담고있는 Header
  • 토큰에 담긴 정보를 담고있는 Payload
  • 토큰의 유효성 판단을 위한 Signature

여기서 JWA는 Signature 생성에 사용되며, 적용되는 알고리즘 정보는 Header에 작성된다.

jwt.io의 위 예시를 예로들면 HS256 알고리즘을 이용하여 Signature를 생성함을 파악할 수 있다.

또한, Signature 생성이 어떻게 이뤄지는 지도 나타나있다.
HS256( Base64Encode(header) + "." + Base64Encode(payload), 임의의 secret)

이렇게 Signatrue 생성에 사용되는 알고리즘은 JWT가 JWE냐, JWS냐에 따라 서로다른 알고리즘이 사용된다.

JWS

JWS( JSON Web Signatrue )에 사용가능한 알고리즘 목록은 아래와 같다.

HS 시리즈( 대칭키 )

HS시리즈는 HMAC을 생성하는 알고리즘들을 의미한다. ( ex : HMAC SHA-○○○ )
MAC 생성에 있어 임의의 Secret 값을 사용하기 때문에, MAC을 생성한 사람이 누군지 판단하는게 가능하다.

뒤에 표기되는 256, 384, 512는 사용되는 SHA( Secured Hash Algorithm ) 의 종류를 뜻하며, 생성되는 해시의 길이를 의미한다.
즉, SHA256을 이용해 생성된 해시는 256비트( 32byte )의 크기를 가진다.

Base64 인코딩까지 들어가니 생성되는 Signatrue는 (32 * 4)/3 인 43 byte가 된다.

MAC은 메시지 인증에 사용되는 작은 크기의 정보를 의미한다.

위키피디아에서 가져온 이미지에서 확인할 수 있듯,

인증이 필요한 정보( 메시지 )를 이용해 변조가 불가능한 MAC을 생성하고, 송수신자가 이를 이용하여 옳은 메시지인지를 판단하는 용도로 사용된다.

RS 시리즈( 비대칭키 )

RS시리즈는 RSASSA-PKCS1-v1_5을 이용해 서명을 생성해내는 것을 의미한다. ( ex : RSASSA-PKCS1-v1_5 SHA-○○○ )
RSASSA-PKCS1-v1_5는 간략하게 설명하면 PUBLIC KEY와 PRIVATE KEY를 이용하는 비대칭키 암호화 방식이다.

Header와 Payload를 SHA256을 적용해 32byte의 해시값으로 만들고,
2048 비트 이상의 key값을 RSA private key로 이용하여 최종 Signature값을 생성해낸다.

이후, RSA public key로 이 Signatrue 값을 검증한다.

뒤에 표기되는 256, 384, 512는 사용되는 SHA( Secured Hash Algorithm ) 의 종류를 뜻하며, 생성되는 해시의 길이를 의미한다.
단, RS시리즈는 생성되는 서명값의 길이가 사용된 RSA키의 길이와 동일하다. ( 최소 256 byte )

Base64 인코딩까지 들어가니 생성되는 Signatrue는 (256 * 4)/3 인 342 byte가 된다.

ES 시리즈( 비대칭키 )

ES시리즈는 ECDSA를 이용해 서명을 생성해내는 것을 의미한다 ( ex : ECDSA P-256 and SHA-256 )
ECDSA( Elliptic Curve Digital Signature Algorithm ) 을 이용하기 때문에 서명 생성에 SHA 말고 타원곡선 정보가 필요하다.

대략적인 서명 생성 과정

  1. 타원곡선 정보인 P-○○○와 SHA-○○○, private key를 이용하여 (R, S) 쌍 생성
    • 이때, R과 S는 256비트의 부호없는 정수다
  2. R과 S를 빅 엔디안 순서의 옥텟 시퀀스로 변환
    • 이를통해, 32바이트 배열을 생성
  3. 생성된 두 32바이트 배열을 R - S 순서로 연결
  4. 총 64바이트의 Signature 생성

대략적인 서명 검증 과정

  1. 64바이트의 Signatrue 인지 검증
    • 64바이트가 아니라면 검증 실패
  2. 두 개의 32바이트 배열로 구분하여 각각 R과 S로 나타내며, 옥텟 시퀀스로 변환
  3. JWS Signing Input, R, S, public key를 입력으로 ECDSA P-○○○ SHA-○○○ validator를 이용해 검증

PS 시리즈( 비대칭키 )

PS 시리즈는 RSASSA-PSS를 이용해 서명을 생성해내는 것을 의미한다.

SHA-○○○ 및 private key를 이용해 MGF1 마스크를 생성하고, 다시한번 SHA-○○○를 이용해 Signature를 생성한다.
이후, 검증에서는 SHA-○○○를 마스크 생성함수로 이용해 MGF1 값을 구하고 SHA-○○○와 public key 등을 이용한다.

요약

요약하자면 JWS의 암호화 알고리즘에는 대칭키를 이용한 방법 1개비대칭키를 이용한 방법 3개가 존재하는 셈이다.

생성되는 JWT의 크기와 성능, 호환성 등을 고려하여 선택해야한다.
특히, 대칭키를 이용한 방법에서는 secret 값을 쉽게 알아내지 못하는 값으로 사용해야한다.

JWE

JWE( JSON Web Encryption )에 사용가능한 알고리즘 목록은 아래와 같다.

JWE는 JWS와 다르게 Signature를 생성하지 않는다.
CEK( Content Encryption Key )라는 값을 생성해내는데 JWA가 사용된다.

JWE는 아래 구조로 이루어지는데,

  • JOSE Header
    - JWE Protected Header
    - JWE Shared Unprotected Header( JWE JSON Serialization를 사용하는 경우 )
    - JWE Per-Recipient Unprotected Header( JWE JSON Serialization를 사용하는 경우 )
  • JWE Encrypted Key
  • JWE Initialization Vector
  • JWE Ciphertext
  • JWE Authentication Tag
  • JWE AAD( JWE JSON Serialization를 사용하는 경우 )

ciphertextAuthentication Tag를 특정하는 과정에서 대칭키로 사용되는 값이 CEK다.

일반적으로 접하기 힘든 유형의 JWT이기 때문에 자세한 내용은 RFC 7516 문서를 참고해보자

참고

0개의 댓글