[Network] HTTPS 암호통신과정 살펴보기 (SSL/TLS 하이브리드 암호 시스템에 대해)
HTTP 약점
이 약점은 http만의 약점이 아니라 암호화하지 않은 프로토콜 모두에 해당한다.
1. 평문(암호화 x) 통신이기 때문에 도청 가능
같은 세그먼트 도청은 어렵지 않다. 패킷을 해석하는 패킷 캡처나 스니퍼라는 툴을 이용해 네트워크 상에 흐르고 있는 패킷을 수집하면 된다.
대안
- TLS같은 프로톨콜을 사용하여 통신을 암호화 시키는 방법이 있다.
- 콘텐츠 암호화를 유효하게 하기 위해서는 클라이언트와 서버가 콘텐츠의 암호화나 복호화 구조를 가지고 있어야 하므로 브라우저나 웹 서버에서는 어렵고 웹 서비스에서 주로 사용된다. (ex. jwt 토큰에 사용자 정보 암호화해놓고 통신하기)
2. 통신 상대를 확인하지 않기 때문에 위장 가능
HTTP를 사용한 요청이나 응답에서는 상대를 확인하지 않는다. 요청을 보낸 서버가 정말 URI로 지정된 호스트인지 알 방도가 없다.
대안
상대를 확인하는 증명서: TLS에서 증명서를 제공하기 때문에 상대를 확인할 수 있다. 증명서는 제 3자 기관(CA)에 의해 발행되는 것이기 때문에 서버나 클라이언트가 실재하는 사실을 증명한다.
3. 완전성을 증명할 수 없기 때문에 변조 가능
완전성이란 정보의 정확성을 가리킨다. 완전성을 증명할 수 없다는 것은 정보가 정확한지 아닌지를 확인할 수 없다는 뜻이다. 예로 공격자가 중간에 끼어들어 수신한 내용을 변조할 수 있다. (Man-in-the-Middle 공격)
대안
- PGP같은 프로그램으로 파일에 서명하는 방법이 있지만 확실한 방법은 아니다.
- HTTPS 사용 - TLS에는 인증이나 암호화, 다이제스트 기능을 제공한다.
HTTPS = HTTP + 암호화 + 인증 + 완전성 보호
이러한 문제를 해결하기 위해 HTTP에 암호화나 인증 등의 구조를 더해 HTTPS(HTTP Secure)이 등장했다.
HTTPS 안전성
- HTTP 내 사이트에 보내는 정보들을 제 3자가 못 보게 한다.
- 접속한 사이트가 믿을 만한 곳인지를 알려준다
SSL/TLS 프로토콜 (하이브리드 암호화 시스템)
HTTPS는 HTTP 통신을 하는 소켓 부분을 SSL/TLS이라는 프토토콜로 대체한 것이다. 즉, HTTP에 SSL/TLS를 입힌 것을 HTTPS라 한다.
- SSL은 넷스케이프가 내놓은 프로토콜로 SSL 3.0까지 개발되었다.
- 그러다가 IETF로 옮겨졌는데 그러면서 명칭이 TLS로 바뀌었다.
- SSL 3.0이 TLS1.0으로 책정되어 이후로 TLS1.1, TLS1.2, TLS1.3이 나왔다.
하이브리드 암호화 시스템 (공통키 + 공개키)
HTTPS는 공통키 암호 + 공개키 암호를 섞은 하이브리드 암호화 시스템을 사용한다.
공통키(대칭키) vs 공개키(비대칭키)
공통키 | 공개키 | |
대칭성 | 대칭키 (암호/복호 같은 키를 사용) | 비대칭키 (암호/복호 서로 다른 키를 사용) |
키 종류 | 공통키(common key) 클라이언트와 서버가 동일한 키를 사용한다 |
개인키(private key), 공개키(public key) 통신 대상은 두 개의 키를 지녀야 한다. |
장점 | 공개키 방식에 비해 계산속도가 훨씬 빠르다 | 공개키만 외부에 공개하면 되므로 외부 도청으로 부터 안전하다 |
단점 | 1. 공통키 제작과정에 서로 키를 공유해야하기 때문에 도청 위험이 있다 (키 탈취 문제) 2. 상대와 1대1로 키를 공유하기 때문에 통신 상대가 증가할수록 자원 소모가 심하고 관리가 까다롭다. |
공통키 방식에 비해 계산속도가 매우 느리다 |
암호 예시 | DES, AES | DH 키 교환(공개키 최초), RSA, DSA |
문제점 1: 공통키 암호 한계, 도청 위험
공통키가 속도도 빠르고 암호화된 통신이 가능해서 이것만 사용할 것 같지만 아니다. 암호화와 복호화에 하나의 키(공통키)를 같이 사용하는 방식이기 때문에 상대방에게 키를 넘겨줄 때가 취약하다. 그래서 도청할 수 없도록 네트워크 통신 자체를 암호화해서 안전하게 배송하기 해줘야 한다.
- 안전하게 배송하기 위해 필요한 방식이 바로 두 개의 키(비대칭키)를 사용하는 공개키 방식이다.
해결책 1: 공개키 암호로 도청 방지
TLS는 도청을 할 수 없도록 공개키 암호 방식을 사용한다.
- 공통키(대칭키) 한계: 서로 공유하다가 해커한테 걸리면 보안이 뚫릴 수도 있다.
공개키 암호방식은 두 개의 키(비밀키, 공개키)가 있다. 공개키는 누구에게나 공유해도 되지만 개인키는 누구에게도 알려지면 안된다. A가 Naver에게 메세지를 보낸다고 할때 공개키 암호방식을 사용하면 다음과 같다.
A(Client) → Naver(Server)
- A가 Naver의 공개키를 사용하여 메세지를 암호화하여 전송한다.
- Naver는 해당 암호화된 정보를 받아들여 자신의 비밀키로 복호화하여 메세지를 읽는다.
- Naver는 암호화는 공개키를 사용했고, 복호화는 비밀키를 사용했다. 따라서 Naver의 자신의 비밀키를 도난당하지 않는 이상 도청에 대한 위험은 없다
그런데 이러한 공개키 암호 방식은 속도가 매우 느리다. 메세지를 암호화하고 복호화하는데 많은 자원을 필요로 한다. 그래서 HTTPS는 공통키와 공개키를 섞어서 사용하기로 한 것이다.
- 공통키 암호로 사용되는 해쉬값(pre-master-secret)을 공개키 암호화해서 안전하게 서버에게 전송한다.
- 그렇게 안전하게 서로의 공통키를 생성하고나면 이제는 도청에 대한 위험없이 공통키 암호방식으로 안전하고 빠르게 통신을 이룰 수 있게 된다.
문제점 2: 통신 상대 검증이 안됨, 위장 위험
그런데 아직도 문제가 있다. 공개키를 받는데 C라는 사람이 중간에 Naver라고 위장하여 C자신의 공개키를 보낸다면 A는 아무것도 모른채 C를 Naver라고 굳게 믿고 암호 통신을 하게 된다.
해결책 2: 공개키 신원을 증명해주는 CA기관
공개키 암호에도 약점이 있는데 바로 공개키가 진짜인지 아닌지 모른다는 것이다. 그래서 C와 같은 위장꾼을 걸러내기 위해 CA(Certificate Authority) 인증기관이 존재한다. 이 과정에서는 공개키 방식이 사용된다.
CA 공개키 증명서 인증 방식
- 서버 운영자(Naver)는 CA 인증 기관에 공개키를 제출한다.
- CA는 인증기관의 비밀키로 서버의 공개키에 디지털 서명으로 공개키 증명서를 작성한다.
- 클라이언트 요청이 오면 서버는 클라이언트에게 공개키 증명서를 전송한다.
- 클라이언트는 서버와 통신할 때 공개키 증명서를 CA 공개키로 증명하고 공개키가 정말인지 확인한다.
- CA 인증 공개키는 브라우저(크롬, 파이어폭스, 엣지 등)에 내장되어 있다.
- CA 인증서는 크롬 설정 > 보안 및 개인정보 보호 > 보안 > 인증서 관리에서 확인이 가능하다.
- 클라이언트는 해당 서버 공개키로 데이터를 암호화하여 서버에게 전송한다.
- 서버는 자신의 개인키로 클라이언트가 보낸 메시지를 복호화하여 확인한다.
공개키 암호방식에서 공통키로 전환하기
클라이언트가 서버와 암호 통신을 하기 위해 어떤 과정이 이뤄지는지 살펴봤다. 서버는 CA기관에게 인증을 받아 HTTPS 통신이 가능함을 입증했고 클라이언트가 서버는 이젠 공통키를 생성하여 공개키 암호 방식에서 공통키 암호 방식으로 전환해야 한다.
- 안전한 서버인지 신원 확인되었으면 공개키 암호 방식을 이용해 서로의 공통키를 생성한다.
- 클라이언트와 서버가 공통키를 갖게 되면 이젠 비용 부담이 적은 공통키 방식으로 암호 통신을 이룬다.
대략적으로 이와 같이 전환을 하게 된다. 도청의 위험을 공개키로 커버하고 안전하게 공통키를 생성했으면 훨씬 속도가 빠른 공통키 암호방식으로 전환하는 것이다. handashake 통신 과정을 보며 더 자세히 살펴보자.
HTTPS handashke 통신 과정
위에서 대략적으로 암호화 통신 과정을 살펴봤다. 이제 어떤식으로 공통키을 생성하여 암호 통신을 이루어지는 더 자세히 살펴보자.
1. 클라이언트가 “Client Hello” 메시지를 송신하면서 TLS 통신을 시작한다.
메세지 내용
- 클라이언트가 제공하는 TLS 버전
- 암호 스위트(Supported Cipher Suite)로 불리는 리스트(사용하는 암호화 알고리즘이나 키 사이즈 등)
- client random number(32byte 난스) - 공통키(master-secret) 재료
- Session ID (if any)
2. 서버가 TLS 통신이 가능한 경우 “Server Hello” 메시지로 응답한다.
메세지 내용
- 클라이언트와 같이 TLS 버전
- 암호 스위트(Chosen Cipher Suite): 클라이언트가 제시한 내용에서 선택한 목록
- ex. TLS_RSA_WITH_AES_128_GCM_SHA256 : 키 교환 RSA, 대칭키 AES_128 GCM, Hash 알고리즘은 SHA256
- server random number(32byte 난스): 공통키(master-secret) 재료
- Session ID(reuse or new)
3. 서버는 클라이언트에게 “Certficate” 메세지를 송신한다.
- 해당 메세지에는 자신의 공개키 증명서가 포함되어 있다.
4. 서버가 “ServerHelloDone” 메세지를 송신하여 최초의 TLS 네고시에이션이 끝났음을 통지한다.
5. 클라이언트는 pre-master-secret을 생성하여 이를 서버 공개키로 암호화하여 “Client KeyExchage” 메세지를 보낸다.
- 클라이언트는 브라우저에 내장된 키를 통해 공개키 증명서를 뜯어서 서버의 공개키를 얻는다. 그래서 해당 공개키를 사용해 보낸 것이다.
6. 그렇게 서버와 클라이언트 서로 같은 master-seceret이라는 공통키를 제작한다.
master-seceret = client random number + server random number + pre-master-secret
- 만약 도청하는 사람이 있다면 노출된 값은client random number, server random number이다. pre-master-secret은 이미 합의된 암호 알고리즘(ex. RSA)을 사용했기 때문에 노출되지 않는다.
- 세 개의 값을 얻은 서버와 클라이언트는 각각 해쉬 암호(ex. SHA256)를 이용하여 master-secret 키를 생성한다.
- RSA 암호를 이용한 공통키 생성 방식 참고
7. 클라이언트는 “Change Cipher Spec” 메세지를 송신한다. 그리고 클라이언트는 “Finished” 메세지를 송신한다.
- "Change Cipher Spec" 메시지는 이 메시지 이후의 통신은 암호키를 사용해서 진행한다는 것을 나타낸다.
- "Finished"를 보내면서 통신이 끝났음을 알린다.
8. 서버도 마찬가지로 “Change Cipher Spec” 메세지를 송신하고 “Finished” 메세지를 송신한다.
9. 둘다 “Finished” 교환이 완료되면 이제는 TLS에 의해 접속이 확립된다.
- 따라서 이제부터는 공개키 방식 대비 속도가 빠른 공통키 암호 방식으로 통신하므로 클라이언트와 서버는 안심하고 통신이 이루어진다.
완전성 - 메세지 인증 코드(MAC; Message Authentication Code)
이 흐름에 추가로 메세지 인증 코드(MAC)라고 부르는 메세지 다이제스트를 덧붙일 수도 있다. MAC을 이용해서 변조를 감지할 수 있어 완전성 보호를 실현할 수 있다.
MAC은 해쉬 알고리즘을 사용해 원본 데이터를 일정한 길이의 암호화된 문자열로 변경한다. 해쉬 알고리즘(MD5, SHA-256 등)은 원본 데이터마다 일정한 결과값을 도출하며 원본 데이터가 변경되면 결과값 또한 달라지는 특성을 지닌다. 그리고 단방향이라서 해시값을 다시 원본으로 돌릴 수 없다.