*HTTP over Secure Socket Layer*
웹에서 자주 사용되는 HTTP는 다음과 같은 이유로 보안점이 취약하다
HTTP 메세지는 요청과 응답의 내용이 그대로 노출된 체로 통신이 이루어 지는데, 도청 가능한 TCP/IP 네트워크를 사용하다 보니, 로그인을 하기 위해 사용자가 비밀번호를 입력하면, 요청한 HTTP메세지에 도청가능한 체로 통신이 이루어 진다는 뜻이다.
HTTP를 사용하여 통신하는 경우, 이 메세지가 어디서 왔는지 혹은 신뢰할 수 있는 클라이언트나 서버인지를 확인 할 수 없다. http://www.royce.com이라는 주소에 신뢰할 수 없는 클라이언트를 포함하여 여러 요청이 들어오는 경우, 해당 주소로 이어진 서버입장에서는 구별할 수가 없다.
HTTP를 사용한 통신은 통신과정 중에서 수정이나 변조될 수 있다.
이러한 보안 취약점을 해결하고 HTTP를 이용하기 위해 HTTPS가 등장하였다.
Secure Socket Layer
HTTPS는 HTTP에서 TCP로 통신하는 과정과 달리, 중간에 SSL(TLS)라는 보안 계층을 통해 TCP로 통신하게 된다. 이 때 SSL을 사용함으로써 암호화와 증명서, 안정성 보호등의 기능을 제공받고 사용할 수 있다.
SSL가 개발된 뒤 발전하여 표준화 기구인 IETF의 관리로 변경되면서 TLS라는 이름으로 바뀌었다.
TLS 1.0은 SSL 3.0을 계승한다.
하지만 TLS라는 이름보다 SSL이라는 이름이 훨씬 많이 사용되고 있다.
SSL의 동작과정을 이해하기 전에 대칭키와 공개키에 대한 이해가 필요하다.
암호화할 어떤 데이터 혹은 문서에 대해 암호화하는 키와 복호화 하는 키가 동일한 방식을 대칭키(공통키)라고 한다.
다음과 같은 예시를 보자.
#텍스트 내용이 "Hello, Royce"인 `beforeEnc.txt`파일을 생성하고,
echo 'Hello, Royce' > beforeEnc.txt;
#-des3방식으로 beforeEnc.txt파일을 암호화 한 뒤 afterEnc.bin으로 생성
openssl enc -e -des3 -salt -in beforeEnc.txt -out afterEnc.bin;
이때, 암호화를 실행하는 단계에서 키를 설정해야 한다.
#확인
cat afterEnc.bin
#Salted__OOy /��t��
# �P)���~�%
잘 암호화가 된 것을 알 수 있다.
이제 암호화된 afterEnc.bin
을 복호화 할려고 한다면, 암호화 하는 단계에서 설정한 키를 동일하게 입력하면 복호화 할 수 있다.
#afterEnc.bin 복호화
openssl enc -d -des3 -in afterEnc.bin -out afterDec.txt;
cat afterDec.txt
#Hello, Royce
이렇게 암호화하는 키와 복호화 하는 키가 동일한 방식을 대칭키라고 한다
하지만, 여기서 문제는 복호화 하는 대상이 키가 없는 경우 전송해주어야 하는데, 이 키는 암호화 되어 있지 않다. HTTP를 통해 통신을 하는경우, 요청을 암호화 한뒤 요청을 수용하는 서버는 해당 키가 없기 때문에 복호화를 위해 키도 함께 전송한다면 복호화키가 노출될 수 있다.
이러한 이슈를 해결하기 위해 공개키 방식이 등장했다.
암호화 대상에 대해 하나의 키만 가지는 대칭키와 다르게 공개키 방식은 두개의 키를 가진다. 공개키와 비공개키(개인키)를 가지며 공개키는 타인 누구에게나 제공해도 괜찮다.
공개키로 암호화를 하고, 비공개키로 복화하를 하는 것이다. 이러한 방식은 키를 전송해줄 필요가 없기 때문에 비교적 안전하다. 비공개키만 노출되지 않는다면 말이다.
#private.pem이라는 비공개키를 생성(1024bit)
openssl genrsa -out private.pem 1024;
#비공개키에 대한 공개키 생성
openssl rsa -in private.pem -out public.pem -outform PEM -pubout;
echo 'Hello, Royce' > beforePem.txt
#beforePem.txt를 생성한 공개키로 암호화
openssl rsautl -encrypt -inkey public.pem -pubin -in beforePem.txt -out afterEnc.ssl;
cat afterEnc.ssl;
#ɖo�~�g�>��f�Y�V?]ؤ�G��mZ�
# `�M-:ա�YY�]��4ӵ~�{�����+M�����9)�O���AQǃ�pvl��9�ٿ�|h��8�YO`�U0��g_h+9T�Qe&%
#비공개키로 복호화
openssl rsautl -decrypt -inkey private.pem -in afterEnc.ssl -out decrypted.txt
cat decrypted.txt
#Hello, Royce
비대칭키를 사용하면 더 안전하게 암호화하여 통신이 가능할 것 같지만, 대칭키에 비해 느리고 컴퓨팅 부하가 더 높다는 단점이 있다.
현재는 대칭키와 비대칭키를 적절히 섞어 사용하고 있다고 한다.
그리고 CA의 등장으로 이어지는 단점이 하나 있는데, 암호화된 공개키가 진짜인지 아닌지 증명하기 어렵다는 것이다. 비공개키에서 제공한 키가 아닌 다른 공개키로도 암호가 가능하며, 비공개키를 가진 서버에게 언제든지 복호화 요청을 보낼 수 있는 가능성이 존재한다.
그래서 CA가 등장하였다.
Certificate Authority
앞선 공개키의 문제점을 해결하기 위해 다음과 같은 역할이 필요하다
엄격한 심사를 거쳐 선정된 CA(인증기관)에서 담당한다.
우선 서버에서 사용할 CA에 서버 공개키를 제출한다.
CA에선 서버의 공개키를 암호화 한 뒤 인증서와 함께 서버에 보내준다.
이제 암호화 된(by CA의 비밀키) 서버의 공개키를 담은 인증서를 요청하는 클라이언트에게 보낸다.
인증서를 받은 클라이언트는 이미 설치된 CA의 공개키를 사용해서 서버의 공개키를 복호화한다.
통신을 통해 받는 것은 위험도가 높기에 브라우저(클라이언트)는 보통 주요 CA의 공개키를 사전에 내장하고 있다.
이 때 복호화가 잘 된다면 인증 기관이 발급한 인증서라는 것과 실제 서버의 공개키라는 것을 알 수 있고, 이는 신뢰할 수 있는(CA에 의해) 클라이언트임을 알 수 있다.
HTTPS로 통신을 하기 위해서는 아래와 같이 클라이언트 - 서버
가 악수(HandShake)
과정을 거치게 된다.
Client Hello 메세지(랜덤 메세지)
를 서버에게 보내면서 SSL 통신이 시작 된다.Server Hello 메세지(랜덤 메세지)
로 응답하여 통신 가능하다는 것을 알리고, 서버가 Certificate(인증서)를 클라이언트에게 전송한다. Client Hello(랜덤 메세지)
와 서버에서 클라이언트로 응답한 Sever Hello(랜덤 메세지)
를 조합하여 Pre-Master-Secret-Key
를 만든다.Pre-Master-Secret-Key
는 클라이언트와 서버 사이에 사용될 공통키이다.)Pre-Master Secret Key
를 암호화 한 후에 서버로 보낸다.Pre-Master-Secret-Key
를 자신의 비밀키로 복호화 한다.Pre-Master-Secret-Key
라는 공통키
를 가졌기 때문에 이후 통신에는 대칭키(공통키)
방식으로 사용해서 통신할 수 있게 되었다.