TLS Basics

Dongmin Lee·2023년 6월 28일
0

Kubernetes

목록 보기
2/10

1. Symmetric Encryption

사용자가 은행 웹사이트에 접속하여 아이디와 비밀번호를 입력하여 로그인을 할 때, 일반 텍스트 형식으로 전송된다. 따라서 해커가 네트워크 트래픽을 탐지하면 아이디와 비밀번호를 쉽게 추출해 사용자의 은행 계좌를 해킹할 수 있다.

그래서 보통은 전송되는 데이터를 임의의 숫자와 알파벳으로 이루어진 shared key(or symmetric key)라는 것으로 암호화한다.

데이터에 임의의 숫자와 알파벳을 추가하고 인식할 수 없는 포맷으로 암호화하는 것이다.

이제 데이터를 서버로 보내면 탐지하고 있던 해커가 데이터를 얻지만 아무것도 할 수 없다. 마찬가지로 서버도 데이터를 받았지만 아무것도 알 수 없다.

앞서 이용했던 shared key 없이는 데이터를 해독할 수 없으니 shared key의 복사본도 서버로 보내서 서버가 메시지를 해독하고 읽을 수 있게 해야 한다. 하지만 shared key도 같이 네트워크로 전송되면 해커도 탐지하여 데이터를 해독할 수 있다.

지금까지 살펴본 방식을 대칭 암호화(Symmetric Encryption)라고 부른다. 암호화 방식 중 하나이고, 암호화한다는 점에서 안전하지만, 데이터를 받는 쪽에서도 같은 shared key를 사용해야 하기 때문에 해커가 shared key에 알고 데이터를 해독할 위험이 있다.

그래서 나온 것이 비대칭 암호화이다.

2. Asymmetric Encryption

비대칭 암호화 방식은 public key와 private key를 사용한다. 때로 public key를 public lock으로 표현하기도 한다.

이제 public key와 private key을 사용해보자.

먼저, SSH 접속을 보안하는 사례를 살펴보자. 우리는 터미널에서 아래의 명령어를 이용하여 public key와 private key를 만들 수 있다.

$ ssh-keygen

$ ls
id_rsa   id_rsa.pub

id_rsa는 private key이고, id_rsa.pub은 public key이다.

마무리로 서버에 /.ssh/authorized_keys 경로에 public key를 추가한다. 이제 private key를 통해 SSH로 서버에 접속할 때, 서버에 있는 public key를 통해 접속할 수 있다.

다시 은행 웹사이트 사례로 가보자. 먼저 서버에서 public key와 private key를 만든다.

# Create private key
$ openssl genrsa -out my-bank.key 1024

# Create public key
$ openssl rsa my-bank.key -pubout > my-bank.pem

이후에 사용자가 HTTPS를 통해 웹 서버에 처음 접속하면 서버에서 public key를 보낼 것이다. 당연히 해커는 모든 트래픽을 탐지하고 있어서 public key의 복사본을 가지고 있다.

사용자의 브라우저는 서버에서 제공된 public key를 이용하여 사용자의 shared key를 암호화한다. 그리고 암호화된 shared key를 서버로 보낸다.

최종적으로 해커도 서버와 똑같이 서버의 public key와 서버의 public key로 암호화된 shared key를 가지고 있다.

서버는 서버의 private key로 메시지를 해독하고 shared key를 얻는다. 반대로 해커는 서버의 public key로 암호화된 shared key를 풀 수 있는 서버의 private key가 없기 때문에 메시지에서 얻을 수 있는 shared key를 얻을 수 없다.

이제 shared key를 이용하여 암호화해서 서버로 보내면 서버에서 암호화된 shared key를 해독하여 사용할 수 있다.

3. Certificate

다시 해커는 사용자 계정을 해킹할 새 방법을 찾고 있다. 그래서 은행 웹사이트와 똑같은 웹사이트를 만든다. 그리고 똑같이 해커의 서버에서 public key와 private key를 만들고, 네트워크를 조정하여 은행 웹사이트로 접근하면 해커가 만든 웹사이트로 보내진다.

사용자가 웹사이트 주소에 접근하면, 해커의 서버에서 public key를 보낸다. 동일한 방식으로 그 key로 shared key를 암호화하고, 암호화된 shared key가 해커의 서버에 보내진다. 이로써 해커는 shared key를 이용하여 사용자의 정보를 빼낼 수 있다. (그리고 화면에는 해킹되었다는 표시가 뜰 수도..)

우리는 서버에서 받은 public key가 진짜 은행 서버에서 나온 key인지 어떻게 알 수 있을까? 그래서 나온 것이 서버에서 public key를 보낼 때 단지 public key를 보내는 것이 아니라 public key를 가진 인증서(Certificate)를 보내는 것이다.

인증서는 어디서 발급되었는지에 대한 정보를 갖고 있다. 해당 서버의 public key, 서버의 위치 등이 있다.

Certificate:
	Data:
    	Serial Number: 420327018966204255
	Signature Algorithm: sha256WithRSAEncryption
    	Issuer: CN=Kubernetes
    	Vaildity
        	Not After: June 28 13:41:28 2023 KST
        Subject: CN=my-back.com
        Subject Alternative Name:
        	DNS: myback.com, DNS: i-bank.com, DNS: we-bank.com
        Subject Public Key Info:
        	00:b9:b0:55:24:fb:a4:ef:77:73:7c:9b

모든 인증서에는 이름이 있고, 인증서를 발급하는 사람이나 대상이 매우 중요하다. ID를 검증하도록 도와주기 때문이다.

하지만 이런 인증서는 누구나 만들 수 있다. 구글이라고 하면서 직접 생성할 수도 있다.

해커도 동일하게 인증서를 발급했다고 해보자. 인증서가 진짜인지 어떻게 확인할까? 일반적으로 인증서를 생성했다면 직접 서명해야 한다. 하지만 해커도 복사하여 가짜 서명을 할 수 있다.

그럼 사용자의 브라우저가 신뢰할 수 있는 합법적인 웹 서버 인증서를 어떻게 만들까? 그래서 나온 것이 인증서에 서명하고 유효성을 확인해주는 인증 기관(Cretificate Authority, CA)이다.

동작하는 방식은 순서대로 아래와 같다.

  1. Certificate Signing Request(CSR) 생성 - 은행
  2. 인증서 유효성 검사 - 인증기관
  3. 서명된 인증서 생성 및 전송 - 인증기관

먼저 private key를 이용하여 Certificate Signing Request(CSR)을 생성한다.

$ openssl req -new -key my-bank.key -out my-bank.csr -subj "/C=US/ST=CA/O=MyOrg, Inc./CN=mydomain.com"

이후에 인증 기관으로 보내면 인증 기관에서 유효성 검사 후, 인증서에 서명해서 다시 보내준다.

해커도 같은 방법으로 인증서에 서명을 받으려고 하지만 인증서 유효성 검사 단계에서 실패한다.

이제 사용자의 브라우저에는 신뢰할 수 있는 CA가 서명한 인증서가 있다. 그렇다면 CA 자체가 합법적이라는 것을 사용자의 브라우저가 어떻게 알까?

인증 기관에서도 public key와 private key가 존재한다. 인증 기관은 인증서에 서명할 때 private key를 사용한다. 그리고 모든 브라우저에는 인증 기관의 public key를 이용하여 인증 기관이 직접 서명한 인증서임을 확인한다.

4. Summary

이제 모든 과정을 정리해보자. 메시지를 암호화하려면 public key와 private key로 비대칭 암호화를 해야 한다.

  1. 서버 관리자: public key와 private key로 서버 SSH 연결을 보안한다.
  2. 서버: private key를 만들어서 인증 기관에 CSR을 보낸다.
  3. 인증 기관: 가지고 있는 public key와 private key 중에 private key로 CSR에 서명한다.
  4. 인증 기관: 서명된 인증서를 서버로 보낸다.
  5. 서버: public key가 포함된 서명된 인증서로 HTTPS 트래픽을 확보한다. (HTTPS로 웹사이트 보호)
  6. 서버: 서명된 인증서로 웹 어플리케이션 프로그램을 구성한다.
  7. 사용자의 브라우저: 최초로 웹 어플리케이션 프로그램에 접속하여 인증 기관의 public key 복사본을 가지고 있는다.
  8. 서버: 웹 어플리케이션 프로그램에 접속할 때마다 서버는 모든 사용자에게 public key를 가진 인증서를 보낸다.
  9. 사용자의 브라우저: 인증서를 읽고 인증 기관의 public key를 사용하여 서버의 public key에 대해 유효성 검사를 진행한다.
  10. 사용자의 브라우저: 유효성 검사가 끝나면 shared key를 서버의 public key로 암호화하여 서버로 보낸다.
  11. 서버: 서버의 private key로 shared key를 회수한다.
  12. 이제 사용자의 브라우저와 서버가 통신할 준비가 되었다. 끝.

여기서 한가지 확인해야할 것은 클라이언트는 서버의 유효성을 확인할 수 있었지만, 서버는 클라이언트인지 해커인지 확실히 알 수 없다. 서버는 어떻게 확인할 수 있을까? 사용자의 브라우저에서도 public key와 private key를 만들면 된다. 본인 확인을 위해 서버와 동일하게 클라이언트도 private key를 이용하여 CSR를 생성한다. 이후에 인증 기관에 보내서 public key를 가진 서명된 인증서를 받는다. 마지막으로 받은 인증서를 서버로 보내서 클라이언트의 유효성을 확인한다.

모든 key를 정리해보자.

  • 서버 관리자: private key, public key
  • 웹 서버: private key, public key
  • 인증 기관: private key, public key
  • 사용자의 브라우저: private key, public key

지금까지 살펴본 모든 인프라를 Public Key Infrastructure(PKI)라고 부른다.

끝으로, crtpem 확장자에 대해 알아보자. 일반적으로 public key를 가진 인증서는 crt이나 pem 확장자로 쓰인다. 위에서 살펴봤던 사례에서 서버와 클라이언트 모두 crt이나 pem 확장자인 파일을 가지고 있었다.

  • server.crt or server.pem
  • client.crt or client.pem

그리고 private key는 keypem 확장자로 쓰인다.

  • server.key or server-key.pem
  • client.key or client-key.pem

Private key는 항상 key라는 단어가 붙어있다.

0개의 댓글