안전한 웹을 위한 HTTPS
인터넷에서 귀중한 내 정보를 어디론가 전달하거나, 열람하는 경우가 많습니다. 예를 들면 포털 사이트에 내 ID와 비밀번호를 입력하고 로그인을 하거나, 거래 은행 웹 사이트에 들어가서 내 계좌 정보를 조회하는 경우 등이죠. 만약 인터넷에서 누군가가 이런 나의 중요 정보를 몰래 보거나, 내 카드 정보를 빼가거나, 악용한다면 인터넷으로 더 이상 안전한 거래를 할 수 없을 것입니다.
인터넷은 안전한 통신을 위하여 암호화라는 것을 합니다. 암호화란 일반적인 평문을 알아볼 수 없도록 암호화하여 암호문으로 만드는 과정입니다. 암호문을 상대방에게 전달하고, 상대방은 이를 다시 복호화하여 평문으로 열람할 수 있습니다. 이와 같은 과정을 웹 브라우저와 웹 서버에게 사용하는 대표적인 기술이 바로 HTTPS(Hypertext Transfer Protocol Secure)입니다. 인터넷 콘텐츠를 전달하는 TCP 프로토콜의 일종인 HTTP에 S(Secure) 기능을 더한 것이죠.
HTTPS는 SSL(Secure Socket Layer)/TLS(Transport Layer Security) 전송 기술을 사용합니다. 단어의 원어에서 알 수 있듯이, TCP, UDP와 같은 일반적인 인터넷 통신에 안전한 계층(layer)을 추가하는 방식입니다. 그리고 이 기술을 구현하기 위해 웹 서버에 설치하는 것이 SSL/TLS 인증서입니다. TLS는 SSL의 개선 버전으로, 최신 인증서는 TLS를 사용하지만 편의적으로 SSL 인증서라고 쭉 부르고 있습니다.
SSL 인증서 관련 프로세스에는 아래와 같은 보안 기술이 탑재되어 있습니다.
하나의 키(key)로 암호화/복호화를 수행하는 대칭키 암호화 방식
한 쌍의 키 페어(key pair)로 암호화/복호화를 수행하는 비대칭키 암호화 방식
통신 대상을 서로가 확인하는 신분 확인(authentication)
믿을 수 있는 SSL 인증서를 위한 디지털 서명(digital signature)
디지털 서명을 해주는 인증 기관(CA: Certificate Authority)
공개키를 안전하게 전달하고 공유하기 위한 프로토콜
암호화된 메시지의 변조 여부를 확인하는 메시지 무결성 알고리즘
따라서 SSL 인증서에 사용된 기술을 잘 이해하고 있다면, 웬만한 인터넷상의 보안 원리에 관한 기본적인 기술 토픽은 이해하였다고 말할 수 있습니다.
대칭키 암호화 방식(symmetric-key algorithm)이란, 하나의 키(key)로 평문을 암호화하고, 다시 암호문을 원해의 평문으로 복호화할 때 사용하는 방식입니다. 대문을 잠그는 자물쇠를 떠올려보면, 자물쇠를 잠근 열쇠만이 그 자물쇠를 다시 열 수 있습니다. 즉 잠그고 여는 것 모두가 하나의 열쇠를 사용합니다. 그렇지만 만약 내가 이 열쇠를 잃어버렸고, 누군가 내 집 주소를 아는 사람이 열쇠를 주었다면 어떤 상황이 될까요? 이렇듯 대칭키 암호화 방식은 키를 단 하나만 사용하는 간편함이 있지만, 키를 분실하거나 누군가에게 도난을 당한다면 내 암호문을 누군가가 복호화하여 볼 수 있다는 치명적인 단점이 있습니다.
공개키 암호화 방식(Public Key Cryptography)은 공개키, 개인키 이렇게 두 개의 키를 한 쌍(key pair)으로 각각 암호화/복호화에 사용합니다. 일반적으로 공개키로 암호화한 것을 개인키로 복호화합니다. 개인키를 먼저 만들고 여기서 공개키를 파생하여 한 쌍의 키를 만들기 때문에 key pair라 부르는 것입니다. 만약 같은 쌍이 아닌 다른 키를 사용하려 한다면 암호화/복호화가 불가능합니다.
공개키는 말 그대로 누구에게나 공개할 수 있는 키입니다. 위 그림 예제에도 영희의 공개키는 이미 철수에게 공개되어, 철수가 보유하고 사용할 수 있었습니다. 같은 맥락으로 철수의 공개키는 영희에게 공유되어, 영희가 철수에게 암호문을 전달할 때 사용될 것입니다. 따라서 공개키 암호화 방식은 사전에 안전하게 서로의 공개키를 나누어 받는 과정이 필요합니다.
이때 사용하는 대표적인 키 교환 알고리즘으로 RSA(Rivest – Shamir – Adleman)와 디피-할만(Diffie-Hellman) 알고리즘이 있습니다.
얼핏 들으면 보안에 사용하는 키를 공개적으로 나누어주는 것이 불안해 보일 수 있지만, 앞에서 말한 대로 짝에 해당하는 개인키 없이는 어차피 복호화가 불가능하기 때문에 상관없습니다. 내가 만든 공개키를 누군가 가져갔다 해도, 그것으로 만든 암호문을 가지고 있다고 해도 개인키 없이 복호화가 불가능하기 때문에 개인키는 아주 안전하게 보관되어야 합니다. 공개키 방식은 대칭키 방식에 비해 안전하지만, 계산 과정이 복잡하고 연산 도중 컴퓨터의 자원이 많이 사용하기 때문에 실제 IT 시스템에서는 공개키 방식과 대칭키 방식을 적절히 혼합하여 사용합니다.
SSL 핸드 셰이크(handshake) 과정
핸드 셰이크는 악수를 의미하는데, 통신을 하는 브라우저와 웹 서버가 서로 암호화 통신을 시작할 수 있도록 신분을 확인하고, 필요한 정보를 클라이언트와 서버가 주거니 받거니 하는 과정이 악수와 비슷하여 붙여진 이름입니다.
핸드 셰이크는 어떤 과정으로 이루어져 있는지 알아봅시다.
클라이언트) ① 클라이언트가 먼저 서버에 접속해서 말을 겁니다.(Client Hello)
내가 브라우저 주소창에서 blog.naver.com를 치면 내 브라우저는 네이버 블로그 웹 서버에 접속 시도합니다. HTTP는 TCP의 일종이니, TCP 연결을 위한 3-Way Handshake를 수행한 브라우저는 네이버 블로그가 HTTPS를 사용하는 것을 알게 된 브라우저는 다음 정보를 Client Hello 단계에서 보냅니다.
브라우저가 사용하는 SSL 혹은 TLS 버전 정보
브라우저가 지원하는 암호화 방식 모음(cipher suite)
브라우저가 순간적으로 생성한 임의의 난수(숫자)
만약 이전에 SSL 핸드 셰이크가 완료된 상태라면, 그때 생성된 세션 아이디(Session ID)
기타 확장 정보(extension)
cipher suite 이란, 보안의 궁극적 목표를 달성하기 위해 사용하는 방식을 패키지의 형태로 묶어놓은 것을 의미합니다. 여기서 보안의 목표란 다음과 같습니다.
안전한 키 교환
전달 대상 인증
암호화 알고리즘
메시지 무결성 확인 알고리즘
서버) ② 서버 또한 위의 인사에 응답하면서, 다음 정보를 클라이언트에 제공합니다.(Sever Hello)
- 브라우저의 암호화 방식 정보 중에서, 서버가 지원하고 선택한 암호화 방식(cipher sutie)
- 서버의 공개키가 담긴 SSL 인증서. 인증서는 CA의 비밀키로 암호화되어 발급된 상태입니다.
- 서버가 순간적으로 생성한 임의의 난수(숫자)
- 클라이언트 인증서 요청(선택 사항)
클라이언트) ③ 브라우저는 서버의 SSL 인증서가 믿을만한지 확인합니다.
대부분 브라우저에는 공신력 있는 CA들의 정보와 CA가 만든 공개키가 이미 설치되어 있습니다. 서버가 보낸 SSL 인증서가 정말 CA가 만든 것인지를 확인하기 위해 내장된 CA 공개키로 암호화된 인증서를 복호화해봅니다. 정상적으로 복호화가 되었다면 CA가 발급한 것이 증명되는 셈입니다. 만약 등록된 CA가 아니거나, 등록된 CA가 만든 인증서처럼 꾸몄다면 이 과정에서 발각이 되며 브라우저 경고를 보냅니다.
클라이언트) ④ 브라우저는 자신이 생성한 난수와 서버의 난수를 사용하여 premaster secret을 만듭니다.
웹 서버 인증서에 딸려온 웹 사이트의 공개키로 이것을 암호화하여 서버로 전송합니다. 서버 인증서에 공개키가 같이 딸려오는 부분이 이해가 어려우신 분들은 아래 디지털 인증서의 원리에 대한 글을 한번 보세요.
⑤ 서버) 서버는 사이트의 비밀키로, 브라우저가 보낸 premaster secret 값을 복호화합니다.
복호화 한 값을 master secret 값으로 저장합니다. 이것을 사용하여 방금 브라우저와 만들어진 연결에 고유한 값을 부여하기 위한 session key를 생성합니다. 세션 키는 대칭키 암호화에 사용할 키입니다. 이것으로 브라우저와 서버 사이에 주고받는 데이터를 암호화하고 복호화합니다.
⑥ 서버/클라이언트) SSL handshake를 종료하고, 드디어 HTTPS 통신을 시작합니다.
브라우저와 서버는 SSL handshake가 정상적으로 완료되었고, 이제는 웹상에서 데이터를 세션 카를 사용하여 암호화/복호화하며 HTTPS 프로토콜을 통해 주고받을 수 있습니다. HTTPS 통신이 완료되는 시점에서 서로에게 공유된 세션 카를 폐기합니다. 만약 세션이 여전히 유지되고 있다면 브라우저는 SSL handshake 요청이 아닌 세션 ID만 서버에게 알려주면 됩니다. 이 부분은 ①에서 언급되었습니다.
다만, Googling 해보시면 SSL 핸드 셰이크 과정에 대한 내용이 글마다 조금씩 다릅니다. 구현체마다 다양한 옵션을 가지고 있어서 그런 것인데, 원리는 같은 것이니 크게 신경 쓰지 않으셔도 됩니다.
SSL 인증서 과정에는 대칭키 방식과 공개키 방식 두 개 모두 사용되었습니다. 앞에서 설명했듯, 모든 웹 콘텐츠의 전달을 공개키 방식으로 한다면 웹 서버와 브라우저에 많은 부담이 되기 때문에 SSL Handshake 단계까지는 공개키 방식, 그 이후의 HTTPS 통신은 대칭키 방식을 사용하는 것입니다.
특정 웹 서버와 HTTPS 통신을 맺는 과정, SSL handshake 과정의 내용을 Wireshark로 캡처할 수도 있고, openssl 명령으로 간단하게 터미널과 주고받는 내용을 확인할 수 있습니다.
HTTPS는 안전한 데이터의 전달이 브라우저와 서버 사이의 인터넷 전달 구간에서 이루어지기 때문에 보안 채널(secure channel), 전송 보안(secure transit)이라고 부르기도 합니다. 개인 정보를 다루는 웹 사이트뿐만 아니라, 대부분의 클라우드 서비스들은 HTTPS를 사용하여 스토리지 파일 업로드/다운로드, 데이터베이스의 CRUD 작업, 미디어 서비스의 스트리밍 전달, REST API 호출 등을 하기 때문에 HTTPS 적용 방법을 이해하기 위한 SSL handshake는 매우 중요한 지식이라 할 수 있습니다.
HTTPS는 웹에서 보안을 적용하기 위한 가장 기본적인 단계이고, 이것으로 모든 보안성이 완벽하게 지켜졌다고 할 수 없습니다. 예를 들면, 웹 서버가 해커의 다양한 공격에 의해 루트 권한을 탈취당했다면 모든 기밀 데이터를 열람할 수 있는 권한이 넘어갈 수도 있습니다. 또한 HTTPS는 전달 구간에 대한 보안 기술인데, 전달 구간 중간에 해커가 중간자 공격(Man in the middle attack)을 수행할 수 있는 취약점이 있다면 HTTPS는 유지되지만 전달하는 내용은 고스란히 노출되기 때문입니다.
따라서 인스턴트 메시징 서비스와 같이 개인과 개인 혹은 그룹 간 대화, 민감한 개인 정보 등의 전달에서는 HTTPS를 적용하면서도 종단 간 암호화 기술(E2E: End-to-End Encryption)을 추가적으로 적용하여 HTTPS가 무력화되어도, 노출된 데이터는 암호화를 유지하여 해커가 읽을 수 없도록 하는 것이 일반적인 추세입니다.