https의 원리를 정확히 알고 계시나요?
최근 대부분의 웹사이트는 HTTPS를 사용한다. 간단한 이벤트 페이지조차 예외가 아니다. 그만큼 보편적으로 사용되고 있는 것이 바로 HTTPS이다. 하지만 면접에서 HTTPS에 대해 물으면, 대다수의 지원자가 제대로 설명하지 못한다. 대충 개념만 아는 경우가 많다.
이번 기회에 HTTPS에 대해서 명확하게 알아보고자 한다. 프로토콜 구현 수준까지 정확하게 알기는 어렵지만, 최소한 SSL/TLS가 어떻게 인증을 처리하고 암/복호화를 하는지 이해할 필요는 있다.
HTTPS는 HTTP 프로토콜에서 암호구간(SSL/TLS)을 얹은 프로토콜이다. 클라이언트는 HTTP를 통해 요청 을 보낼 때 3-way 핸드셰이크를 통해 TCP 연결을 맺은 후에 데이터를 전송한다. 이 연결로 전송되는 데이터는 평문이다. 즉, 누구든 중간에서 네트워크 패킷을 가로채서 읽을 수 있다. 카드번호를 입력한다면 누군가 쥐도 새도 모르게 카드를 도용할 수 있다는 의미이다.
HTTPS는 이러한 데이터를 암호화하여 보내기 위해 보안 조치를 추가한다. 인증서를 통해 서버의 진위를 확인하고, 서로가 함께 알 수 있는 암호화 키를 사용하여 데이터를 보호한다. 사이트가 HTTPS를 사용하는지는 쉽게 알 수 있다. HTTPS로 통신하는 웹사이트를 접속하면 주소창에 자물쇠 표시가 나온다. 이는 여러분의 데이터가 암호화되어서 서버로 전달된다는 의미이다.
지금부터는 HTTPS가 어떻게 데이터를 안전하게 보호하는지 알아보고자 한다.
SSL/TLS 핸드셰이크 과정의 전체 흐름은 다음과 같다.
SSL/TLS는 응용계층(HTTP)과 전송계층(TCP) 사이에서 동작한다. 다만, SSL/TLS 핸드셰이크에 필요한 연결을 생성하기 위해 TCP 3-way 핸드셰이크를 진행한다. 서버와 클라이언트 간 TCP 연결이 맺어지고 나면, 아래와 같은 패킷 전달을 통해 암호화 통신 준비를 시작한다.
| SSL/TLS 핸드셰이크 과정
1. 먼저 클라이언트는 Client Hello 단계에서 사용가능한 암호화/해시 알고리즘과 random 값을 전달한다. random값은 추후 공통키를 만드는 과정에서 사용된다.
2. 서버는 전달받은 암호화/해시 방식 중 우선순위가 높은 옵션을 선택해서 이를 클라이언트에 전달한다. 이때 서버도 random값을 하나 만들어서 전달한다. 이로써, 클라이언트와 서버 모두 2개의 random 값을 보유하게 된다.
3. 서버는 자신을 증명하기 위해서 서버 인증서를 전달한다. 이때, 사전에 인증기관(CA)으로부터 받은 디지털 서명을 함께 전달한다. 이는 자신의 인증서가 위조되지 않았음을 증명하기 위함이다. 클라이언트는 공개된 Root CA의 퍼블릭 키를 통해 디지털 서명을 복호화한다. 복호화가 가능하면 해당 인증서는 공인된 기관으로부터 인증받은 인증서임을 확신할 수 있다. 검증이 끝났으니, 클라이언트는 해당 인증서에 적인 Public키를 믿고 사용할 수 있다.
4. 서버는 자신이 보낼 정보를 모두 보냈음을 알린다.
5. 클라이언트는 암호화에 사용할 키를 만들기 위한 재료를 생성한다. 이를 Pre Master Secret이라고 한다. 클라이언트는 임의로 만든 Pre Master Secret를 서버의 Public키로 암호화하여 서버에 전달한다. 서버는 자신의 Private키를 통해 Pre Master Secret를 추출할 수 있다.
6~9. 서버와 클라이언트는 Pre Master Secret과 이전에 주고받았던 random 값을 통해 Master Secret을 생성한다. 이 Master Secret으로 Session 키와 MAC 키를 생성한다. 이제부터는 이 공통키를 사용하자고 서로 마지막 확인을 한다.
위 작업이 끝나면 클라이언트는 패킷을 보낼 때 암호화 과정을 진행한다. 먼저, MAC키를 통해 데이터의 MAC 값을 구한다. 이는 데이터가 변조되었는지 확인하기 위함이다. 이후 MAC값과 데이터를 Session키로 암호화한다. 암호화된 데이터를 헤더와 함께 서버로 전달한다.
서버는 Session키를 통해서 데이터와 MAC값을 추출한다. 데이터를 자신의 MAC키로 MAC값을 계산하고, 이를 클라이언트로부터 받은 값과 비교한다. 만약 MAC 값이 같다면 데이터가 변조되지 않았다는 의미이다. 검증을 마치면 데이터를 애플리케이션으로 올려 보낸다.
우리가 HTTPS로 구성된 웹사이트를 접속하면 위의 과정이 순식간에 진행된다. 보이지는 않지만 이러한 복잡한 과정 덕분에 우리의 데이터를 안전하게 보호할 수 있다.
SSL/TLS 핸드셰이크는 대칭과 비대칭 키 암호화 방식을 혼합한 하이브리드 방식을 사용한다. 그 이유를 알아보기 전에 대칭과 비대칭 키 암호화 방식의 차이에 대해 알아보자.
대칭 키 암호화 방식은 서버와 클라이언트가 동일한 키를 사용하는 암호화 방식이다. 클라이언트는 암호화키를 사용하여 데이터를 암호화하고, 암호화된 데이터와 키를 서버에 전달한다. 서버는 암호화된 데이터를 전달받은 키로 복호화한다. 마치 엑셀파일을 비밀번호로 암호화하고, 비밀번호를 알려주는 것과 같다. 간편한 방식이지만, 키를 전달하는 과정에서 제삼자에게 노출될 수 있다. 따라서 대칭 키 암호화 방식을 사용하기 위해서는 키를 안전하게 전달할 수 있는 방안이 필요하다.
비대칭 키 암호화 방식은 암호화와 복호화에 서로 다른 키를 사용하는 방식이다. 대표적인 예가 인증서이다. 서버는 Public키와 Private키 쌍을 만든다. Private키는 자신이 소유하고, Public키를 만천하에 공개한다. 클라이언트는 서버의 Public키를 사용하여 데이터를 암호화하고, 이를 서버에 전달한다. 이때 별도의 키를 전달할 필요는 없다. 서버는 자신의 Private키로 복호화를 진행한다. 참고로, Private키로 암호화하고 Public으로 복호화하여 사용자를 인증하는 디지털서명도 비대칭 키 암호화의 좋은 예이다.
비대칭 키 암호화 방식은 복호화에 필요한 키가 공개되지 않기에 안전하다. 하지만 과정이 복잡하여 처리 속도가 느립니다. 이는 Public키와 Private키의 조합을 검증하기 위한 수학적 계산이 생각보다 많은 부하를 발생시키기 때문이다.
SSL/TLS 핸드셰이크에서는 위의 2가지 방식을 혼합하여 속도와 보안을 동시에 챙겼다.
먼저, 속도를 높이기 위해서 데이터 암/복호화는 공통키(대칭키)를 사용한다. 앞선 그림에서 Session키와 MAC키가 바로 대칭키이다. 하지만 대칭키를 그냥 주고받으면 위험하기 때문에, 대칭키를 만들기 위한 재료를 보낼 때 비대칭 키 암호화 방식을 사용한다. 클라이언트가 Pre Master Secret을 보낼 때 Public키로 암호화하는데, 이게 비대칭 키 방식이다.
요약하자면, SSL/TLS는 비대칭 키 암호화 방식을 사용하여 공통키의 재료를 전달하고, 공통키를 각자 만들어 데이터를 암호화하는 데 사용한다.
앞서 설명한 비대칭 키 암호화 방식 중 대표적인 예가 바로 인증서이다. 인증서는 서버가 자신을 증명하기 위해서 발급한 문서이다. 마치 명품에 들어있는 보증서와 같은 개념이라고 볼 수 있다.
여러 서버가 자신이 구글 서버라고 주장한다고 가정해 보자. 똑같은 웹사이트를 띄워주면 사용자를 이를 검증할 방법이 없다. 하지만 구글은 자신의 서버에 설치된 인증서를 통해 자신을 증명할 수 있다. "가짜 구글 서버"는 인증서가 없기 때문에 증명할 길이 없다.
하지만 인증서가 진짜라는 보장은 없다. 인증서도 마음만 먹으면 위조가 가능하다. 따라서 누군가 사용자를 대신해서 진짜 구글서버의 존재를 검증해주어야 한다. 그 존재가 바로 인증 기관(CA, Certificate Authority)이다. 인증 기관은 우리가 믿어도 된다고 합의한 공식 기관들이다. 대표적으로 DigiCert, Let's Encrypt 등이 있다.
구글은 자신이 진짜임을 증명하기 위한 인증서를 인증 기관을 통해 발급받는다. 이때 인증기관은 인증서를 해시한 다음 Private키로 암호화하여 디지털 서명을 만든다. 서버는 인증서 정보와 함께 디지털 서명을 클라이언트에 전달한다. 클라이언트는 디지털 서명을 인증 기관의 Public키로 복호화한다. 그러면 해시값이 나오는데, 이를 인증서를 해시한 값과 비교한다. 만약 두 값이 일치하면 위조되지 않았다는 의미이다. 비로소 진짜 구글 서버를 가려낸 셈이다.
위의 과정을 통해 진짜 인증서임을 확인하면 그 안에서 서버의 Public키를 찾을 수 있다. 해당 Public키를 통해 Pre Master Secret을 암호화하는 것이다. 인증 기관의 Public키랑 서버의 Public키는 다르기 때문에 과정을 정확히 이해해야 한다.
HTTPS는 서버의 진위를 검증하고 안전하게 데이터를 주고받기 위한 프로토콜이다. 설령 개인정보 유출 위험이 없다 하더라도, 서비스를 운영한다면 HTTPS 사용을 권장한다. 최근에서는 사설 네트워크 상에서도 HTTPS를 주로 사용하는 추세이다. 어느 네트워크 구간에서든 안전하게 통신하기 위함이다.