구성정보 파일에서 민감하거나 중요한 값(ip, Password, JWT Token Secret Key 등) 들이 외부에 그대로 노출된다면 보안에 심각한 문제가 발생할 수 있다! 따라서 중요한 정보는 암호화 하는 과정이 필수적이다. Java Key Tool을 활용하여 비대칭키 방식의 암호화를 진행해보자.
그전에! 표준적으로 암호화에 사용되는 방식에 대해 간단하게 알아보자. 암호와 작업에는 보통 대칭키, 비대칭키 두 가지 방식을 사용하는데 이에 사용되는 공개키와 비밀키에 대해 알아보자.
데이터를 암/복호화하기 위해 같은 비밀키(대칭이되는 키)를 사용하는 방식을 대칭키 방식이라고 한다. 이 방식은 암/복호화에 동일한 비밀키를 사용하기 때문에 속도가 빠르며 효율적이다.
하지만 동일한 비밀키를 사용하기 때문에 상대에게 건내어주는 과정에서 탈취될 위험이 있다.
데이터를 암/복호화 하기 위해 서로 다른키를 사용하는 방식을 비대칭키 방식이라고 한다. 이 방식은
데이터의 암호화에는 비밀키 or 공개키 - (보통은 비밀키), 복호화에는 공개키 or 비밀키 - (보통은 공개키)를 사용하며 비밀키를 먼저 만들고, 여기서 공개키를 파생하여 한 쌍의 키를 만든다.
공개키를 공개하여 이를 통해 데이터를 암호화하게 하고, 복호화에는 개인키만 사용이 가능한 방식이다. 암호화에 어떤 키를 사용하던 (공개 or 비밀) 그 쌍(대응) 이되는 키는 노출이 되어서는 안된다!
만약 같은 쌍이 아닌 다른 키를 사용하려 한다면 암/복호화가 불가능하다.
대칭키 방식은 암/복호화에 동일한 키를 사용하기 때문에 수행하는 알고리즘이 간단하며 연산량이 감소한다. 따라서 대용량의 데이터를 암/복호화 처리할 때에는 대칭키 방식을 많이 사용한다고 한다!
대칭키/비대칭키에 대해 이야기하다보니 HTTPS 프로토콜이 생각이 나서 한 번 정리해보고 가려한다..
HTTPS 프로토콜에서는 비대칭키 암호화 방식과 대칭키 암호화 방식의 장점을 활용하여 하이브리드 형식으로 암/복호화를 진행한다. 앞서 서술했듯이 비대칭키 방식은 안전하지만 시간이 오래걸리는 단점이 있다.
따라서 대칭키 방식(세션키를 사용한)을 사용해 빠르게 데이터를 암/복호화 하며, SSL Handshake를 통해 전달하는 방식에 비대칭키를 사용한다.
SSL HandShake에 대해서 한 번 훑어보고 가자.
handshake란 악수라는 의미로, 브라우저와 웹 서버가 서로 암호화 통신을 시작할 수 있도록 신분을 확인하고, 필요한 정보를 서로 주고받는 과정이 악수와 비슷하여 붙여진 이름이다.
클라이언트(브라우저)가 웹 서버에 먼저 접속한다. 아래의 정보를 담아 해당 단계에서 보낸다.
웹 서버는 Client Hello에 응답하며 아래의 정보를 담아 클라이언트에게 보낸다.
클라이언트(브라우저)는 서버에서 제공받은 SSL 인증서가 올바른지 확인한다. 대부분의 브라우저에는 CA들의 정보와 CA가 만든 공개키가 이미 설치되어 있다. 내장된 CA 공개키로 암호화된 인증서를 복호화(비대칭키 방식) 한다.
복호화가 정상적으로 진행되었다면 CA가 발급한 것이 증명이 되는 셈이며, 제대로 진행되지 않았다면 브라우저에게 경고를 보낸다.
클라이언트 난수, 서버의 난수를 Server Hello 단계에서 전달받은 SSL 인증서에 포함된 서버의 공개키로 암호화 한다. 이것을 Pre-master-secret 이라고 하며 서버로 전송한다.
서버는 Pre-master-secret을 전달받아 서버의 비밀키(개인키)로 복호화 한다.
클라이언트와 서버는 Pre-master-secret을 master secret 으로 만들어 저장한다. 이 master secret을 사용하여 연결에 고유한 값을 부여하기 위한 Session Key(주고받는 데이터를 암호화할 대칭키)를 생성한다. 세션키는 일회성이다.
서버와 클라이언트는 정상적으로 SSL handshake를 완료하였다. 이제는 웹 상에서 Session Key를 통해 데이터를 암/복호화 하며 HTTPS 프로토콜을 통해 주고받을 수 있다. HTTPS 통신이 완료된 시점에서 서로에게 공유된 세션키를 폐기한다.
결과적으로 SSL Handshake의 과정에서는 비대칭키 전략을,
1. CA의 비밀키로 암호화된 SSL 인증서를 클라이언트의 CA 공개키로 복호화.
2. Pre-master Secret(클라이언트와 서버의 난수 조합)을 서버의 공개키로 암호화하고 서버에서는 비밀키로 복호화
데이터 암/복호화 및 전송에는 대칭키 전략을 사용하고 있다.
1. SessionKey를 통해 데이터 암/복호화
HTTPS의 통신 과정을 보면 SSL HandShake 과정이 모두 수립되어야 암호화된 데이터를 주고 받을 수 있다. 하지만 매번 handshake 과정을 반복하게 된다면 트래픽이 증가하는 상황에서 많은 지연시간과 비효율성이 발생할 수 있다.
이런점을 해결하기 SSL HandShake 과정을 개선하여 간소화 하는 방법이 2가지 있다고 한다!
최초의 통신 과정에서는 SSL HandShake 과정을 모두 거쳐야 한다.
클라이언트의 최초 접속시에는 Client Hello 메시지에 Session Id값이 없다. 서버에서 Server Hello 메시지에 Session Id를 포함하여 전달하게 되면 클라이언트는 이를 로컬에 저장한다.
클라이언트는 다음 HTTP 세션을 맺을 때 해당 Session Id를 사용하게 된다.
서버는 클라이언트가 전달한 Session Id 정보를 검증하고 다시 사용해도 되는 경우라면, Server Hello 메시지에 Session Id 값을 포함하여 전달한다.
클라이언트에서도 Session Id가 같은지 확인이 되면 다음의 과정들을 생략한다.
pre-master secret으로 master key를 다시 계산, Session Key를 생성하여 데이터의 암/복호화를 진행한다.
대략적으로 2 Step 정도 간소화 되며 트랜잭션이 많을수록 효율성이 증가한다고 한다.
최초의 통신 과정에서는 SSL HandShake 과정을 모두 거쳐야 한다.
우선, Ticket 메커니즘을 사용하려면 Client Hello 메시지의 확장 옵션부분에 값이 없는 Session Ticket을 서버에 전달함으로써 Session Ticket 메커니즘 지원함을 알려야 한다. (서버도 마찬가지)
서로 Session Ticket이 지원되는 것을 확인하고 나면 가장 마지막 단계에서 "New Session Ticket" 메시지를 클라이언트에게 전달한다 (Session Ticket은 서버만 알고 있는 키로 암호화 처리된다). 암복호화에 사용할 Master Key와 Cipher Suite 알고리즘이 포함되어 있다고 한다.
클라이언트는 저장된 "New Session Ticket" 메시지를 서버에 전달하며, 서버는 이를 복호화 하여 이전 세션에 대한 정보를 사용한다.
Session Id 방식은 서버에서 Session Id값을 모두 메모리에 기억하므로 서버 메모리 자원에 영향을 줄 수 있다고 한다!! 그래서 클라이언트가 New Session Ticket을 기억하도록 하는 Session Ticket 방식이 서버의 메모리 자원에 영향이 적다!!
참조문서
https://yozm.wishket.com/magazine/detail/1852/
https://withbundo.blogspot.com/2018/01/https-ssl-session-id-session-ticket.html~~