들어가며
진행중인 프로젝트에는 회원이 일반회원과 서드파티회원으로 구분되어있다.
일반 회원이 로그인할 때, 서버는 HS256 알고리즘으로 서명 후 클라이언트에게 JWT를 발급하며
서명 검증은 클라이언트로부터 요청이 들어올때만 서버측에서 검증하게끔 적용했다.
이후 Apple 로그인도 적용해야할 일이 생겼다. 공식 문서를 통해 인증과정을 살펴보니 Apple 로그인시 Apple ID Server 측에서 발급되는 토큰은 HS256이 아닌 RS256 알고리즘으로 서명해야 했다.
회원 종류별로 다른 서명 알고리즘을 사용되고있는데 서명 알고리즘 별 인증 과정에 대해 정리하면 좋을것 같아 포스팅하고자 한다.
HS256
HS256 는 HMAC SHA256 의 줄임말이다.
SHA256이란?
여러 해시 함수의 종류 중 하나가 SHA256 (Secure Hash Algorithm) 이다.
해싱이란?
임의의 길이의 데이터를 고정된 길이의 값으로 바꾸는 과정 즉, 매핑하는 과정을 '해싱'이라 하며 해싱된 결과는 해시값이라고 부른다.
해싱은 자료구조에서 빠른 자료 검색을 위해 매핑하는 과정이지만, 해싱된 데이터는 복원이 불가능하여 (단방향 암호화) 암호화적 용도로도 사용된다.
HMAC SHA256
HAMC은 Hash-based Message Authentication Code 라는 뜻을 가진다.
해싱에 대해서 다시 얘기해볼 때 입력값이 같다면 해싱된 해시값은 항상 동일하기 때문에 수정에 대한 검출은 가능하지만 거짓 행세하는 것을 검출하기는 어렵다.
거짓행세에 대해 검출하고 차단하기위해 SHA256으로 해싱된 메세지를 메세지 인증 코드(private key <- 추측임..)로 암호화(서명) 하여 송신하고 수신측에서는 동일하게 소유한 private key로 복호화 및 서명을 검증하는 방식이다. 동일하게 소유했다는것은 즉, HMAC SHA256 알고리즘이 대칭키 방식임을 알 수 있다.
암, 복호화? 서명, 검증?
client와 server간 공개키 방식을 사용해 메세지를 주고받는다고 가정할 때
client에서 plain message 를 해시함수로 해싱 후 해싱된 해시값을 private key로 암호화한다. 여기까지의 과정을 단순히 ’서명’ 또는 ‘Signature’라고 한다.
client는 plain message 와 최종적으로 산출된 ciper message 를 함께 첨부하여 server로 송신한다.
server는 수신 받은 plain message 를 client 에서 사용한 동일한 해시함수로 해싱 후 해싱된 meessage 를 얻는다. 그리고 server 측이 소유한 public key 로 수신 받은 ciper message 를 복호화하여 해싱된 message 를 얻는다. 결과적으로 두쌍의 해싱된 message 쌍을 비교하여 동일하다면 서명에 대해 ‘검증’이 성공한것이고 서로 다르거나 검증 과정에서 오류가 있다면 ‘검증’이 실패한것이다.
*대칭키 방식은 위의 내용에서 public key를 private key로 치환한것으로 생각하면 될것같다.
RS256
RS256는 RSA + SHA256을 줄임말로 대칭키방식인 HS256과 달리 공개키를 이용하는 대표적인 암호화방식인 RSA을 사용한것이다.
메세지를 SHA256 알고리즘으로 해싱 한뒤 private key로 암호화(서명)한다. public key를 발급받은 어떠한 주체는 앞서 암호화(서명)된 해싱값을 복호화 또는 서명을 검증하는 할수 있는 방식이다.
public key는 이름 그대로 보안을 유지할 필요가 없기 때문에 ID 공급자는 이 public key를 메타 데이터 URL을 통해 쉽게 구할 수 있도록 제공한다.
그럼 언제, 어느 알고리즘을 적용해야 할까?
HS256 알고리즘은 하나의 키(secret key)가 서명과 서명 검증에 사용되므로 서버측(ID 제공자), 클라이언트측 모두 secret key를 소유해야 한다. 이로인해 secret key 교환을 위한 별도의 안전한 메커니즘이 요구된다. (참고로 JWT 서명, 발급할 때 마다 secret key가 생성되는것이 아닌 오직 하나의 키만 존재한다.)
HS256 방식을 사용하는 JWT가 적용된 앱이 있다고 가정하자. HS256 방식은 이 앱을 다운로드 후 로그인에 성공한 모든 사용자에게 별도의 보안 메커니즘을 통해 secret key를 전달해 줘야 한다. 관리자는 지속적으로 앱을 다운로드, 로그인을 성공한 사용자를 제어할 수 없으며, secret key가 해커에게 유출된다면 해커가 임의로 변조한 JWT를 서버측에서 서명 검증에 성공해버리는 이슈도 발생할 것이다.
참고로 내가 진행중인 프로젝트는 단순하게 클라이언트 측에서 JWT 서명을 검증할 필요는 없어 서버측에서만 secret key를 소유, 서명 검증을 진행하면 됐기 때문에 HS256 방식 그대로 적용하는것이 나아 보인다.
결론적으로 이 secret key를 사용하는 사람을 제어할 수 있으면 HS256 알고리즘, 없다면 RS256 알고리즘을 적용하면 된다.
RS256 알고리즘은 Apple 로그인으로 예를 들어보겠다.
아래는 Apple 로그인 적용 내용에 대한 포스팅이다.
https://hwannny.tistory.com/71
위의 그림 내 1, 2, 3을 보면 Apple ID Server (ID 공급자)는 사용자들에게 secret key를 발급하면서 발급 받은 사용자를 모두 제어할 수 없기 때문에 secret key 대신 사용자(Api server)에게 public key를 공개한다. 사용자는 클라이언트로 부터 인증 요청 헤더에 포함된 JWT(identity_token)를 Apple ID Server로 부터 얻은 public key 로 서명 검증 가능하게 한다. 그리고 private key는 Apple ID Server 만 소유하고 있기 때문에 해커가 JWT를 변조할 위험도 사라지게된다.
참고
https://stackoverflow.com/questions/39239051/rs256-vs-hs256-whats-the-difference
'🔐 Security' 카테고리의 다른 글
BCryptPasswordEncoder는 encode시(암호화시) 동일한 plain text(평문)에 대해서 왜 매번 다른 암호화된 값을 생성 할까? (0) | 2023.04.05 |
---|---|
OAuth 2.0 개념 정리 (7) | 2021.04.11 |
Spring API서버에서 Apple 인증(로그인 , 회원가입) 처리하기 (23) | 2020.07.09 |