본문으로 바로가기

HTTPS와 SSL의 작동 구조

category 개발/인프라, CS 2020. 12. 30. 21:38
이 글에서는 생활코딩의 HTTPS와 SSL인증서 의 내용을 일부 인용하고 있습니다.

HTTP와 HTTPS

HTTP는 Hypertext Transfer Protocol의 약자로 Hypertext인 HTML을 전송하기 위한 통신 규약을 의미한다. HTTPS에서 'S'는 Over Secure Socket Layer의 약자로 보안이 강화된 HTTP라는 의미이다. HTTP는 웹 브라우저가 웹 서버와 통신하기 위해 TCP 통신을 개찬하며 이로인해 클라이언트(브라우저)와 서버(웹 서버)가 평문 또는 암호화된 데이터를 서로 교환할 수 있게 된다.

 

HTTP는 암호화되지 않은 방식으로 데이터를 전송하기 때문에 네트워크 상에 잠복하고있는 해커(또는 봇)가 클라이언트와 서버간에 교환되는 메시지를 쉽게 감청할 수 있게 된다. 이러한 해킹 기법을 스니핑이라고 부른다. 스니핑은 세션 하이재킹 이라고도 부르는데 주로 SSL로 암호화된 HTTPS가 아닌 하이재킹에 취약한 HTTP서버등을 노린다. 이 글에서는 스니핑에 대해서 설명하고 있지 않으니 넘어가도록 하겠다. 이러한 스니핑에 대응하기 위해 나온것이 암호화된 데이터를 네트워크상에서 주고받는 HTTPS이다.

SSL

SSL인증서는 클라이언트와 서버간의 통신을 제 3자가 보증해주는 전자 문서이다. 클라이언트가 서버에 접속함과 동시에 서버는 클라이언트에게 이 인증서를 전달하고 클라이언트는 해당 인증서가 유효한지(신뢰할 수 있는지) 검증 후 다음 절차로 넘어가게 된다. SSL과 SSL인증서를 이용했을때의 이점은 아래와 같다.

 

  • 통신 내용이 공격자에게 탈취당하더라도 암호화되어있기 때문에 정보 노출을 막을 수 있다
  • 클라이언트가 접속하려는 서버가 신뢰할 수 있는 서버인지 판단할 수 있다
  • 통신 내용의 악의적 변조를 방지할 수 있다.

SSL의 암호화 종류

SSL의 핵심 기능은 암호화다. SSL는 보안과 성능상의 이유로 두가지 암호화 기법을 혼용해서 사용하고 있는데 SSL의 작동 구조를 제대로 이해하기 위해서는 이 암호화 기법들에 대한 이해가 필요하다. 이 암호화 기법에 대한 이해가 동반되야만 SSL이 어떻게 서버를 인증하고 안전하게 데이터를 교환할 수 있는지에 대해서 알 수 있게된다. 먼저 가장 널리쓰이는 암호화 기법중 하나인 대칭키 암호화 방식에 대해서 알아보겠다.

대칭키 암호화

암호를 만드는 행위인 암호화의 과정에서 사용하는 비밀번호를 키(key)라고 부른다. 이 키의 값에 따라 암호화된 결과값이 달라지기 때문에 키를 모르면 암호를 푸는 행위인 복호화를 할 수 없다. 즉, 암호화 과정에서 'password'라는 키값을 사용했다면 복호화를 할때도 'password'라는 값을 입력해야 한다는 것이다. 이런 키를 필요로 하는 암호화 알고리즘들중 대칭키에 사용되는 암호화 알고리즘은 DES, 3-DES, AES, SEED, ARIA, MASK등이 있으며 대칭키는 동일한 키로 암호화와 복호화를 같이 할 수 있는 암호화 기법을 의미한다.

echo 'this is the plain text' > msg.txt;
openssl enc -e -des3 -salt -in msg.txt -out msgEncrypted.bin;

위 명령은 MacOS 10.15.7 버전의 터미널에서 실행되었으며 의미는 아래와 같다.

 

  • enc -e -des3 : des3 알고리즘으로 암호화
  • -in msg.txt -out msgEncrypted.in : msg.txt파일을 암호화 한 결과값을 msgEncrypted.bin파일에 저장
openssl enc -d -des3 -in msgEncrypted.bin -out msgDecrypted.txt;

위 명령은 -enc -d 옵션으로 msgEncrypted.bin파일을 msgDecrypted.txt파일로 복호화 하겠다는 의미이다.

공개키 암호화

대칭키 암호화 방식에는 단점이 있는데 이는 암호화된 데이터를 주고받는 주체간에 대칭키를 전달하는것이 위험하다는 것이다. 만약 대칭키가 유출됬을 경우 이를 획득한 공격자는 탈취한 데이터를 복호화시킬 수 있기 때문에 암호가 무용지물이 되고만다. 이런 이유로 나온 암호화 방식이 바로 공개키 암호화 방식이다.

 

공개키 방식은 A와 B. 두개의 키를 갖게 된다. A키로 암호화를 하면 B키로 복호화가 가능하고, B키로 암호화를 하면 A키로 복호화가 가능한 방식이다. 이에서 착안해 두 키중 하나를 비밀키(private key), 나머지를 공개키(public key)로 지정한다. 비공개키는 자신(웹 사이트의 경우 백엔드 API를 제공하는 웹서버가 이에 해당된다)만이 가지고 있고 공개키를 타인에게 제공한다. 공개키를 제공받은 타인은 이를 이용해서 보내고자 하는 데이터를 암호화 시킨 후 전송한다. 그렇게 암호화된 데이터를 전달받은 비밀키의 소유자는 해당 키를 이용해서 암호호된 데이터를 복호화시킨다.

 

이 방식이 강력한 이유는 만약 악의적 공격에 의해 공개키가 유출된다고 해도 비공개키를 모르면 데이터를 복호화할 수 없기 때문이다. 네트워크상에서의 탈취를 방지하는것이 아닌 데이터를 탈취당하더라도 키가 없이는 해독이 불가능한 구조(공개키로 암호화는 가능하지만 복호화는 불가능하기 때문)로 데이터를 주고받는것이기 때문에 기존의 평문방식으로 데이터를 전송하던 HTTP에 비해서 더 높은 보안 수준을 가지게 된다.

 

이방식은 이렇게 응용할 수도 있다. 비밀키의 소유자는 해당 키를 이용해서 암호화시킨 데이터를 공개키와 함께 전송한다. 그렇게 전송된 데이터를 전달받은 사람은 동봉된 공개키를 이용해서 암호화된 데이터를 복호화한다. 이 과정에서는 공개키와 데이터를 아무런 대비방책도 없이 그대로 전송되기 때문에 공격자는 쉽게 정보를 탈취하고 복호화가 가능하다. 그럼에도 불구하고 이런 방식으로 통신하는 이유는 무엇일까? 이유는 바로 이 방식은 데이터를 보호하는것이 목적이 아니기 때문이다. 암호화된 데이터를 공개키로 복호화 할 수 있다는것은 초기 데이터가 공개키와 쌍을 이루는 비밀키에 의해 암호화 되었다는것을 증명한다. 즉, 오히려 누구든지 접근할 수 있도록 허용한 공개키가 데이터를 제공한 사람의 신원을 보장해주게 되는것이다. 이러한 것을 전자 서명이라고 부른다.

 

이해를 돕기위해 실습을 진행하도록 하겠다. 이번에 사용할 공개키는 RSA방식의 공개키이다. 아래 명령은 private.pem이라는 이름의 비밀키를 생성한다. 키의 길이는 1024bit 길이를 가지며 이 숫자가 높을수록 안전하다.

openssl genrsa -out private.pem 1024;

다음 명령은 private.pem이란 비밀키에 대한 public.pem이라는 공개키를 생성한다. 이 공개키를 데이터를 전송하려는 상대에게 전달하면 된다.

openssl rsa -in private.pem -out public.pem -outform PEM -pubout;

그럼 공개키를 전달받은 사람의 입장에서 비밀키를 가지고 있는 측에 데이터를 전송하는 상황을 상정해보자. 아래 명령은 'code name 007'이라는 문자열을 담은 file.txt를 생성하고 이를 암호화를 거쳐 전송한다.

echo 'code name 007' > file.txt
openssl rsautl -encrypt -inkey public.pem -pubin -in file.txt -out file.ssl;

file.txt는 RSA방식으로 암호화되고 이에 사용된 공개키가 바로 public.pem이다. 해당 작업을 통해 암호화된 데이터인 file.ssl이 생성되고 이를 상대측(비밀키 소유자)에 전송한다. 아래는 전달받은 file.ssl을 비밀키인 private.pem을 사용해 복호화시켜 decrypted.txt로 만들어내는 명령이다.

openssl rsautl -decrypt -inkey private.pem -in file.ssl -out decrypted.txt

이와같이 비밀키와 공개키는 서로에 의해서만 복호화될 수 있다. 이 특성으로 인해 A키로 복호화되는 데이터는 오직 B키로만 암호화할 수 있다 -> 이 데이터는 A키로 복호화되므로 데이터를 전송한 서버측은 믿을 수 있다. 라는 확실한 증거를 얻을 수 있게 되므로 서버가 단 하나뿐인 비밀키를 소유하고 있으며 인증되었음을 증명할 수 있게 되는것이다.


SSL 인증서

위에서도 설명했지만 이제 우리는 대칭키와 공개키의 구조에 대해 알고있기 때문에 SSL 인증서의 작동 구조에 대해 이해할 수 있게 되었다. 인증서의 기능은 크게 두가지로 나누어진다.

 

  1. 클라이언트가 접속한 서버가 신뢰할 수 있는 서버임을 보장한다
  2. SSL 통신에 사용할 공개키를 클라이언트에게 제공한다

인증서의 역할은 클라이언트가 접속한 서버가 의도한 서버인지 보장하는 역할을 한다. 이 역할을 하는 기업들이 있는데 이를 CA(Certificate Authority)라고 부른다. CA는 신뢰성이 보장된 공인기업만이 참여할 수 있으며 SSL을 통해 암호화된 통신을 제공하려는 서비스는 이러한 CA를 통해서 인증서를 구입해야 한다.

SSL 인증서의 내용

SSL 인증서에는 다음과같은 정보가 들어있다.

 

  1. 서비스의 정보(CA 발급처, 서비스 도메인 등)
  2. 서버측 공개키(공개키 정보, 공개키의 암호화 방법)

1번은 클라이언트가 접속한 서버가 의도한 서버가 맞는지에 대한 내용이고 2번은 서버와 통신할때 사용할 공개키와 암호화 방법이 들어있다. 서비스의 도메인, 공개키와 같은 정보는 초기에 CA에게서 인증서를 구입할때 제출해야 하는 항목이다. 위의 정보는 CA에 의해서 암호화 된다. 이때 사용하는 암호화 기법이 바로 공개키 방식으로 CA는 자신의 비공개키로 서버의 인증서를 암호화하는것이다.

브라우저의 숨겨진 역할, CA 판별

브라우저는 내부적으로 CA의 리스트를 파악하고 있어 공인 CA인지 아니면 인증되지 않은 사설 CA인지 판단할 수 있다. 또한 리스트와 함께 각 CA의 공개키를 이미 가지고 있다.

SSL 인증서가 서버를 보증하는 방법

웹 브라우저가 서버에 접속한 후 아래와 같은 과정이 진행된다.

 

  1. 서버가 브라우저측에 인증서를 제공한다 -> 브라우저는 해당 인증서를 발급한 CA가 자신이 알고있는 CA의 리스트가 있는지 확인한다
  2. 확인결과 공인 CA가 맞을경우 -> 브라우저에 내장된 해당 CA의 공개키를 이용해 인증서를 복호화 한다(이는 해당 인증서가 CA의 비공개키에 의해 암호화된것을 의미한다)
  3. 인증된 서버임이 확인되고 해당 서버를 브라우저는 안전하다고 보증한다

이는 인증서가 서버의 신뢰성을 인증하는 방법이였다. 그렇다면 복호화된 인증서에 포함된 서버의 공개키는 언제 사용될까?

SSL 통신의 단계

클라이언트와 서버가 통신할때는 내부적으로 3개의 단계가 있다.

 

  1. 악수
  2. 전송(세션)
  3. 세션종료

SSL은 데이터를 전송하기 위해 공개키와 대칭키를 혼합해 사용한다. 대칭키의 키는 공캐키로, 실제 데이터는 대칭키로 통신하는 방식이다.

1. 악수(Handshake)

클라이언트와 서버, 컴퓨터와 컴퓨터는 데이터를 주고받기 전에 먼저 악수(handshake)라는 행위를 한다. 이 과정을 통해 상대방이 존재하는지와 데이터를 주고받기 위해 어떤 방법을 택해야 하는지 파악하게 된다.

  대칭키 공개키
비용 낮음 높음
보안성 낮음 높음

공개키는 보안성이 높지만 연산하는데 있어 시간과 자원을 많이 소모하기 때문에 매번 사용하기에는 브라우저의 처리 속도등의 문제때문에 사용하기 어렵다. 그렇다고 대칭키를 사용하자니 암호화와 복호화에 같은 키를 사용하기때문에 유출되는 순간 모든 데이터의 복호화가 가능해진다. 그래서 SSL에서는 두 암호화 방식의 장점을 혼합한 방식을 사용한다. 아래는 악수(handshake)단계에서 클라이언트와 서버가 통신하는 과정이다.

 

  1. 클라이언트가 서버에 접속한다
    1. Client Hello라는 신호를 서버측에 보낸다
    2. 클라이언트 측에서 생성한 랜덤 데이터를 서버측에 보낸다
    3. 클라이언트에서 지원하는 암호화 방식을 보낸다
    4. 악수(handshake)를 이미 했다면 기존 세션을 재활용하기로 하는데 이때 연결에 사용될 식별자를 서버측에 보낸다
  2. 서버는 Client Hello에 대한 응답으로 Server Hello를 하게된다.
    1. 서버측에서 생성한 랜덤 데이터를 저장한다
    2. 클라언트 측에서 전달한 암호화 방식중 서버측에서도 지원하는 방식을 채택해 클라이언트로 보낸다. 이로써 암호화 방식에 대한 협의가 중단되고 서버와 클라이언트는 이 암호화 방식으로 데이터를 교환하게 된다
    3. 인증서를 클라이언트 측에 보낸다
  3. 클라이언트는 서버의 인증서가 CA에 의해서 발급된 것인지를 확인하기 위해서 클라이언트에 내장된 CA 리스트를 확인한다. CA 리스트에 인증서가 없다면 사용자에게 경고 메시지를 출력한다
  4. 인증서가 CA에 의해서 발급된 것인지를 확인하기 위해서 클라이언트에 내장된 CA의 공개키를 이용해서 인증서를 복호화한다. 복호화에 성공했다면 인증서는 CA의 개인키로 암호화된 문서임이 보증된 것이다. 이로인해 인증서를 전송한 서버를 믿을 수 있게 되었다.

    클라이언트는 2번에서 받은 서버의 랜덤 데이터와 클라이언트의 랜덤 데이터를 조합해 pre mater secret이라는 키를 생성한다. 이때 사용되는 암호화 기법은 대칭키 알고리즘으로 뒤에서 알아볼 세션 단계에서 데이터를 주고받을때 암호화를 위해 사용될것이다. 여기서 문제는 이 pre master secret값을 어떻게 서버로 전달할 것인가이다. 이때 사용하는 방법이 바로 공개키 방식이다. CA의 공개키로 복호화된 인증서에는 서버측 공개키가 들어있다. 이 공개키를 이용해서 pre master secret값을 암호화시킨 후 서버로 전송하면 안전하게 전달할 수 있다
  5. 서버는 클라이언트가 전송한 pre master secret키를 인증서에 연동된 비밀키로 복호화시킨다. 이로써 서버와 클라이언트 모두 pre master secret키를 공유하게 되었고 해당 키는 조정을 거쳐 master secret키로 변환된다. master secret키는 session key값을 생성하는데 해당 키를 사용해 서버와 클라이언트는 데이터를 대칭키 방식으로 암호화시킨 후 주고받는다. 이렇게 세션키는 서버와 클라이언트 모두 공유하게 되었다
  6. 클라이언트와 서버는 악수(handshake)단계가 끝남을 서로에게 알린다

2. 세션(Session)

세션은 실제로 클라이언트와 서버가 데이터를 주고받는 단계로 이 단계에서는 session key값을 이용해서 대칭키 방식으로 암호화 한다. 그대로 공개키 방식을 사용하지 않고 대칭키 방식을 사용하는 이유는 위에서도 말했다시피 공개키보다 대칭키 방식이 더 비용이 적게 들기 때문이다.

 

이제 클라이언트와 서버는 SSL 인증서를 사용해 서로만이 알고있는 키인 session key값이 생겼고 이는 더이상 위험하게 네트워크상에서 키를 이동시킬필요가 없다는것을 의미한다. 악수(handshake)가 종료된 후에는 데이터를 대칭키 방식을 활용해 암호화시키며 이때 사용되는 비밀번호가 바로 session key값이다. SSL 인증 과정을 정리하자면 아래와 같다.

 

  1. 서버가 브라우저측에 인증서를 전달한다
  2. 브라우저는 인증서의 효용성을 검사한다
  3. 악수(handshake)과정을 거쳐 클라이언트와 서버 모두 session key값을 가진다
  4. 해당 키값을 사용해 대칭키 방식으로 암호화시킨 데이터를 주고받는다

3. 세션종료

데이터의 전송이 끝나면 서로에게 통신이 끝났음을 알려주고 암호화에 사용한 session key를 폐기한다.

'개발 > 인프라, CS' 카테고리의 다른 글

HTTP Method란?  (0) 2021.03.14
Linux/Git/Docker 명령어 + Docker Image로 만드는 웹서버  (0) 2021.01.23
DNS는 어떻게 작동하는가?  (0) 2020.12.28
AWS EC2 웹서버 설치하기  (0) 2020.02.13
우분투 서버 명령어  (0) 2020.01.18