본문 바로가기

공부기록/42 Seoul

[ft_server] SSL 인증서 작동 원리

여러 블로그에서 ft_server 과제에 필요한 Self Signed 인증서를 만들 때 아래 명령어를 입력하면 된다는 것을 알 수 있었다.

# openssl req -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/OU=Lee/CN=localhost" -keyout localhost.dev.key -out localhost.dev.crt

그런데 인증서를 왜 만들어야하는지도 모르겠고, openssl man 페이지에서 옵션 설명을 읽어봐도 무슨 소린지 모르겠어서 SSL 원리를 알아봤다. 생활코딩에 있는 강의로 공부했는데 핵심만 딱 공부할 수 있었다.

 

HTTPS와 SSL 인증서 - 생활코딩

HTTPS VS HTTP HTTP는 Hypertext Transfer Protocol의 약자다. 즉 Hypertext 인 HTML을 전송하기 위한 통신규약을 의미한다. HTTPS에서 마지막의 S는 Over Secure Socket Layer의 약자로 Secure라는 말을 통해서 알 수 있듯이

opentutorials.org

 

👩‍💻 개인적으로 정리한 내용 

 

대칭키 방식, 공개키 방식 개념 정리는 링크로 대체

https://gaeko-security-hack.tistory.com/123

 

SSL 인증서의 목적에는 크게 두 가지가 있다.

1. 클라이언트가 접속한 서버가 신뢰할 수 있는 서버임을 보장
2. SSL 통신에 사용할 공개키를 클라이언트에게 제공 (즉, 서버와 클라이언트 사이의 통신을 암호화)

1. 클라이언트가 접속한 서버가 신뢰할 수 있는 서버임을 보장

웹 브라우저(클라이언트)가 서버에 접속할 때, 서버는 제일 먼저 인증서를 제공한다. 이 인증서는 서버의 개인키(비밀키)로 암호화 되어있으며, 이 비밀키와 쌍을 이루는 공개키로만 복호화할 수 있다. 클라이언트는 해당 서버의 공개키를 이용해서 서버의 인증서를 복호화 한다. 복호화가 성공한다면, 신뢰할 수 있는 서버라는 것이 보장된다. 이게 전자서명의 원리이다.

 

2. SSL 통신에 사용할 공개키를 클라이언트에게 제공

SSL 인증서는 대칭키 방식과 공개키 방식을 혼합하여 사용한다. 공개키 방식은 속도가 느려서, 주고 받는 데이터를 모두 공개키 방식으로 암호화하면 비효율적이기 때문이다. 그럼 어떻게 두 방식을 혼합하여 사용할까?
간단히 요약하면, 클라이언트와 서버가 주고 받는 실제 정보는 대칭키 방식으로 암호화하고, 이때 사용한 대칭키는 공개키 방식으로 암호화해서 클라이언트와 서버가 공유한다.

서버와 클라이언트가 통신할 때, 보통 Handshake -> 전송 -> 세션 종료 의 단계를 거친다.

 

Handshake 의 과정만 자세히 정리해보면, 

 

(1) Handshake 시작단계에서 클라이언트와 서버가 서로에게 아래의 정보들을 공유한다. 

Client Hello Server Hello
  • 클라이언트에서 생성한 랜덤데이터
  • 클라이언트가 지원하는 암호화 방식 리스트
  • 세션 아이디
  • 서버 측에서 생성한 랜덤 데이터
  • 서버가 선택한 클라이언트의 암호화 방식
  • 인증서

(2) 클라이언트는 클라이언트에서 생성한 랜덤데이터와 서버에서 생성한 랜덤 데이터를 이용해 pre master secret 키 생성

(3) 클라이언트가 이 pre master secret 키를 서버의 인증서에 포함된 공개키로 암호화한 후 서버에 전송

(4) 서버는 이를 자신의 개인키로 복호화

(5) 이제 서버와 클라이언트 모두 pre master secret 키를 보유하고 있다.

(6) 서버와 클라이언트 모두 일련의 과정을 거쳐서 pre master secret 값을 master secret 값으로 만든다. master secret는 session key를 생성하는데 이 session key 가 실제 데이터를 암호화하는데 쓰이는 대칭키가 되는 것이다.

 


 

다시 본론으로 돌아와서, 그럼 Self Signed 인증서를 만들 때 어떤 것들이 필요할까?

서버 입장에서 인증서를 만드는 거니까 개인키, 공개키, 그리고 공개키를 담고 있는 인증서 파일이 필요하겠다.

원래는 아래와 같은 과정으로 인증서가 만들어진다.

  1. 개인키(.key)를 만든다.
    • openssl genrsa 활용.
  2. CSR (인증서명요청. Certificate Signing Request)을 만든다.
    • # openssl req -new -out <CSR 파일> -keyout <개인키 파일> -newkey rsa:<키 비트수>
    • 참고로 CSR안에는 공개키가 들어있는데 공개키는 명시적으로 만들지 않고 CSR 만들며 자동으로 생성되어 CSR안에 들어간다.
  3. 인증서(.crt)를 만든다.
    • Input으로 CSR을 명시적으로 넣어 인증서를 생성하는 방법이 있고,
    • CSR을 넣지 않고 암묵적 이용으로 인증서를 생성하는 방법이 있다. 👇
    • # openssl req -new -x509 -days <유효날수> -key <개인키> -out <인증서파일명>

제일 위에서 봤던 명령어는 이 과정을 한 줄로 끝내버리는 명령어였던 것이다 !

다시 보자

# openssl req -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/OU=Lee/CN=localhost" -keyout localhost.dev.key -out localhost.dev.crt

req  : 인증서명요청 또는 인증서를 만드는 커맨드

-newkey rsa:4096  : rsa 방식을 이용해 개인키와 인증서명 요청을 새로만든다. 4096 bit 사이즈의 키가 생성된다. 

-days 365  : 유효일수  

-nodes  : no des 를 줄인 것으로, 개인키를 비밀번호로 보호하고싶지 않을 때 사용. 이 옵션을 생략하면 매번 비밀번호 입력해야함.

-x509  : 이 옵션을 사용하면 인증서명요청 대신 Self Signed 인증서를 생성한다.

-subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/OU=Lee/CN=localhost"  :  인증서 안에 들어갈 정보를 명시해주는 부분 

-keyout <개인키 이름>  : -keyout localhost.dev.key

-out <인증서 이름>  : -out localhost.dev.crt

 


이제 이렇게 만든 인증서를 /etc/nginx/sites-available/default 에서 잘 설정해주면, 인증서를 성공적으로 적용할 수 있다 ! 

 

 

참조