1. HTTPS 사용하는 이유
오늘날 많은 사용하자가 이용하는 사이트에서 http를 사용하는 경우는 거의 없다(http가 무엇인지는 알겠지? 웹 서버 자원에 대한 응답-요청을 위해 사용하는 프로토콜이다). 네이버를 가도, 구글을 가도 URL schema를 확인하면 모두 "https"가 가장 앞에 붙어있다. 일부러 http://라고 맨 앞에 붙여도 다시 https:// 프로토콜을 사용하는 주소로 리다이렉트 될 뿐이다. HTTPS는 HTTP에 Security의 S가 추가된 프로토콜로써, 조금 더 secure한 HTTP 통신을 지원하는 프로토콜이다. 뭐 대충 알겠지만, 왜 HTTPS가 선호될까?
1) HTTP는 보안에 취약
http는 평문 통신이다. 클라이언트와 서버가 데이터를 주고받을 때 별다른 암호화를 하지 않는 raw 데이터로 통신한다는 뜻이다. 전송 과정의 패킷을 까면 평문 메세지가 그대로 노출된다. 아이디와 비밀번호가 담긴 로그인 폼 정보를 패킷 전송과정에 참여하는 모두가 읽을 수 있는 환경에 보내는 것은 상당히 위험하다.
또한 공격자가 응답/요청 과정에 있는 패킷을 탈취해서 malfunction 데이터를 추가할 수도 있는데, 이를 받은 서버나 클라이언트는 이게 정말로 상대방이 보낸 pure data가 맞는지 알지 못한다. 서버로부터 신뢰할 수 없는 데이터를 받는다는 뜻이다.
2) 검색 엔진의 가산점
가장 대표적인 검색 엔진인 구글의 경우, https 프로토콜을 지원하는 사이트의 경우 검색 엔진 상위에 노출될 수 있도록 해당 사이트에 가산점을 부여한다. PV를 올려 광고수익을 얻어야 하는 대부분의 인터넷 사이트들은 이런 검색 엔진의 검색 결과 상위에 노출될 수 있도록 https를 지원한다.
물론 https를 지원하는 사이트가 청렴하고 신뢰성 높은 자료만을 이용한다거나 그러는 것은 아니다. 하지만 보안성이 높고
2. TLS / SSL : 4계층과 3계층 사이에 추가
HTTPS 프로토콜을 이용하면, 통신 데이터를 프로그램이 직접적으로 이용할 수 있도록 하는 4계층과 전송 계층인 3계층 사이에 보안 관련 작업이 일어나는 계층이 추가된다. 이를 Secure Sockect Layer의 약자로 "SSL"이라 부른다. TLS는 Transport Layer Security의 약자로 SSL의 업그레이드된 보안 프로토콜이다. [오늘날 https에서 사용되는 보안 프로토콜]은 엄밀히 말하자면 TLS지만, 관습적으로 SSL이라고 부르기도 하는 모양이다. 그러나 정확한 용어 사용을 지향하기 위해 TLS라고 부르겠다.
HTTP와 HTTPS의 차이를 단적으로 보여주는 그림이다. 기존의 평문 통신을 암호화 레이어를 추가해 암호화 통신으로 바꾸는 과정(레이어)이 추가된 모습이다.
TCP 연결을 위해 3-way handshake가 일어난 직후, 서버와 클라이언트간 TLS 연결 역시 확보하기 위해 TLS handshake가 일어난난다. 해당 과정이 어떻게 구현되는지 과정을 살펴보자.
3. HTTPS
1) 대칭키와 비대칭키
- 대칭키 (symmetric key) : 암호화(encryption)와 복호화(decryption)에 같은 키가 사용된다. 빠른 암호화 및 복호화가 가능하지만, 대칭키가 노출되면 참사가 일어난다.
- 비대칭키 (asymmetric key) : 암호화와 복호화에 다른 키가 사용된다. 보통 암호화에 사용하는 키를 공개 키(public key), 복호화에 사용하는 키를 개인 키 혹은 비밀 키(private key)라고 한다. 보통 공개 키는 말 그대로 모두가 볼 수 있게 public으로 열어놓고, 개인 키는 소유주만이 가지고 있다 공개 키로 암호화된 데이터를 복호화할 때 사용한다. 공개 키로 암호화한 것은 개인 키로만 복호화할 수 있고, 비밀 키로 암호화한 것은 공개 키로만 복호화할 수 있다. 공개 키는 전송할 데이터를 암호화할 목적으로, 개인 키는 데이터의 무결성 및 신원확인을 위한 목적으로 주로 사용한다. 대칭키보다 암호화/복호화 과정이 느리다.
비대칭키를 이용한 암호 통신 과정은 간단하다. A와 B가 통신을 한다 가정하자. B는 자신의 공개 키를 세상에 공개한다. A는 공개된 B의 공개키로 자신이 보낼 데이터를 암호화한다. B의 공개키로 암호화된 데이터는 B의 개인 키로만 복호화할 수 있기 때문에, B가 개인 키를 어디 흘리지 않는 한 A가 암호화한 데이터는 오로지 B만 복호화할 수 있다.
그치만 비대칭키를 이용한 암호화/복호화는 느리다. HTTP 통신을 하면서 얼마나 많은 데이터를 암호화 해야 하는데, 모든 데이터를 일일이 공개키로 암호화하고 있으면 컴퓨터 리소스를 암호화에 필요 이상으로 소모하게 된다. 따라서 대칭키를 사용하는게 좋지만, 또 통신 참여자 둘만 공유하는 대칭키를 형성하기란 쉽지 않다. 대칭키를 전송하는 과정에서 또다른 공격이 있을 수 있기 때문이다. 암호화에 사용할 대칭키를 평문으로 보낸다면... 우리집 비밀번호를 이마에 써붙이고 다니는 것이나 마찬가지이다.
각각의 장단점을 취하기 위해 비대칭키 암호화를 이용한 대칭키 공유하는 방법이 사용된다. '실제 데이터 암호화에 사용할 대칭키'를 공유하기 위해 대칭키 자체를 비대칭키로 암호화해서 상대방에게 전송하는 것이다.
2) CA(Certificate Authority)
설마 위의 설명을 보고 완벽하겠군! 하고 생각한건 아니길 바란다. 아래 상황에선 어쩔거냐?
클라이언트 A와 서버 B가 비밀 통신을 하려고 한다. A는 암호화에 사용할 대칭키를 만들었다. 이 대칭키를 암호화해서 B에게 보내기 위해 B에게 공개키를 요구한다. B는 자신의 공개키를 A한테 보내주려고 하는데!!!!
중간에 나쁜놈 C가 패킷을 갈취해서 B의 공개키를 자신의 공개키로 바꿔서 다시 A에게 보내줬다.
아무것도 모르는 A는 받은 C의 공개키가 B의 공개키라고 철썩같이 믿어서 C의 공개키로 대칭키를 암호화한 뒤 전송한다. C는 A가 보낸 패킷을 갈취해서 자신의 개인 키로 복호화해 대칭키를 얻어냈다. 대칭키가 노출되는 참사가 일어나고 말았다..
여기서 문제의 시작은 A가 공개 키랍시고 받은 키가 실제 B의 공개키가 아니었다는 부분이다. 말하자면 데이터의 무결성이 흠집난 것이다. 지금 받은 공개키 데이터가 B의 것이 확실한지, 신뢰할 수 있는 근거가 필요하다. 이 때 등장하는 것이 CA, certificate authority이다.
CA는 공식 인증 기관이다. 신뢰할 수 있는 자신의 공개 키를 사전에 네트워크 세상에 공개한다. 우리가 http 통신에 주로 사용하는 브라우저에는 CA의 공개키가 내장되어있다. CA가 암호화한 데이터가 CA의 공개키로 복호화된다면, 해당 데이터는 CA가 보증한 데이터가 된다. 따라서, CA에게 인증받았다는 것을 증명하기 위해 서버는 CA의 개인키로 암호화된 인증서를 사이트 앞에 걸어놓는다.
CA는 자신에게 인증서를 요청한 서버에게 인증서를 발급하는데, 과정을 살펴보자.
- 서버는 CA에게 자신의 정보와 공개 키를 제출한다.
- CA가 심사를 마치고, 해당 정보를 자신의 비밀 키로 암호화해 인증서를 발급한다. 이 과정을 CA의 전자서명이라고 부르기도 한다.
- 서버가 해당 인증서를 사이트 앞에 걸어놓는다.
- 서버에 요청을 보내려는 클라이언트는 서버 앞에 걸린 인증서를 해당 CA의 공개키로 복호화한다. (공개키는 브라우저에 내장되어 있다는 것을 상기하자)
- 이렇게 받게된 서버의 공개키는 CA에게 인증받은 신뢰할 수 있는 공개키이다.
이것이 '대칭키를 사용하기 위한 공개키를 신뢰하기 위한 인증서의 발급과정'이다. (어렵다)
3) 과정 정리
TCP handshake가 일어난 직후, TLS handshake를 통한 대칭키 공유 과정을 CA의 과정을 포함해서 살펴보자. 클라이언트 A, 서버 B, 인증기관 C가 협업한다.
- HTTPS를 지원하고자 하는 서버 B는 C에게 인증서를 요청한다. B의 사이트 정보와 B의 공개키를 제출한다.
- C는 B가 제출한 정보를 심사한 후, 해당 정보를 자신의 개인 키로 암호화하여 인증서를 제작하여 B에게 돌려준다.
- B는 C로부터 받은 인증서를 사이트 앞에 내건다. // 여기까지가 사전 준비!
- A가 B에 HTTPS 접속 요청을 한다.
- A는 B 사이트에 걸린 인증서를 받는다.
- A의 브라우저가 내장된 CA의 공개키로 인증서를 복호화하여 B의 공개키를 얻는다.
- A는 대칭키 생성에 필요한 데이터를 B의 공개키로 암호화하여 B에게 보낸다.
- A와 B는 방금 공유한 데이터를 바탕으로 대칭키를 생성한다. 이 대칭키를 토대로 서로가 통신한다.
만화는 그냥 가져와봤다. 나름 만화라고 그래도 보기 편하다.
전반적인 과정은 위와 같지만, 조금만 더 자세히 파고들어보자.
각 화살표를 위에서부터 1~6번이라고 하자.
- TCP 3-way handshake 과정의 첫번째, 클라이언트의 SYN=1 세그먼트 전송
- 두번째로 서버의 SYN, ACK=1 세그먼트 전송
- 클라이언트의 SYN=1로 3-way handshake 종료, TLS handshake 시작. ClientHello : 클라이언트의 TLS 버전, 클라이언트가 지원하는 암호 프로토콜의 목록, 클라이언트의 무작위 문자열이 포함
- ServerHello : 서버의 인증서, 서버가 선택한 암호 프로토콜, 서버의 무작위 문자열을 담아 전송
- 클라이언트의 작업
- Certificate : 클라이언트가 내장된 CA로 서버의 인증서 복호화 및 서버 인증. 서버의 공개키 얻음
- ChangeCipherSpec : 클라이언트가 대칭키 생성에 필요한 예비 마스터 암호 생성 후 서버의 공개키로 암호화 후 전송
- ChangeCipherSpec / Finished : 3번의 무작위 문자열, 4번의 무작위 문자열, 5번의 예비 마스터 암호를 통해 서버와 클라이언트가 대칭키 생성. 서로 완료 메세지를 생성된 대칭키로 교환 뒤 안전한 대칭키가 생성되었음을 확인
REFERENCE
https://www.cloudflare.com/ko-kr/learning/ssl/what-happens-in-a-tls-handshake/
https://steady-coding.tistory.com/512