[컴][웹] HTTPS 와 SSL 암호화에 대한 간단한 설명

https 동작 / https 동작 방식 / https 는 어떻게 동작하나?  / ssl 증명서 / 증명서 역할 / 증명서를 사용하는 방법 / https 설명 / 암호화 통신


TLS 1.3

TLS1.3 에 대한 내용을 실제 packet 의 내용을 보여주면서 잘 설명한다.

SSL 동작

이제부터 글은 ref. 1의 내용을 대부분 가져왔다. 조금의 각색등이 있지만, 대체적인 줄기는 ref. 1 의 내용이다. 좀 더 자세한 이야기는 ref. 1 을 참고하도록 하자.

ssl 에서 처음 handshake 를 하면서 하는 일

  1. 서로가 자신이 원하던 server 이고, server도 자신이 허락한 client 인지를 알게 된다.
  2. 서로 어떤 암호를 써서 통신할 것인지 정한다.
  3. 이 암호 알고리즘에 필요한 key를 주고 받는다.



Hello

client 에서 ClientHello message 를 server 로 보낸다. server 가 client 로 SSL connection 을 맺는데 필요한 정보를 같이 보내준다.

이 message 에서 SNI server name indicator 가 쓰인다.[ref. 4] 위 그림에서도 알 수 있지만, server name 이 plain text 로 날라가게 된다. 그래서 이 부분에 대한 enrtypt 를 추진하고 있다.(참고)

이에 대한 응답으로 서버가 ServerHello message 를 클라이언트에 보내는데, 이 때는 client 가 보낸 SSL connection 과 관련된 정보(알고리즘, SSL ver., etc.)를 기반으로 client 에서 서버로 암호화된 정보를 보내는 데에 필요한 정보를 주게 된다.

         ClientHello + SSL connection 에 필요한 정보(algorithm, ssl version,..)
client ------------------------------------------------------------------------------> server
         ServerHello + ssl connection 에 필요한 정보
        <-----------------------------------------------------------------------------


증명서(Certificate) 교환

이렇게 접속이 되면, 이제 server 는 client 에게 자신이 누구인지 알려준다. 이 때 사용하는 것이 SSL certificate 이다.
그러면 client 가 이 certificate 을 보고 판단을 한다. 이 certificate 을 내가 믿을 지, 또는 이 certificate 이 여러 CAs(Certificate Authorities) 중 한곳에서 verified, trusted certificate 인지 확인하는 작업을 한다.
이 때 서버도 마찬가지로 client 에게 certificate 을 요구할 수 있다.

키 교환

server 랑 client 가 data 를 암호화해서 주고받을 때 사용하는 암호화 알고리즘은 symmetric algorithm을 사용하게 된다. 이것은 이미 Hello 부분에서 결정된다. symmetric algorithm 은 암호화와 복화화에 같은 key 를 사용한다.
이 key 를 양쪽에서 사용하겠다고 동의해야 하는데, 이 때 서버의 public/private key 를 이용해서 asymmetric encryption 이 사용된다.


증명서

내 컴퓨터에서 다른 서버로 접근해서 그 서버에게 증명서를 받았을 때 그 증명서가 믿을 수 있다고 확신하는 방법은 아래 2가지가 있다.
  1. 내가 가지고 있는 "믿을 수 있는 SSL certifiacates list" 에 있는 증명서인 경우
  2. 내가 가지고 있는 "믿을 수 있는 SSL certifiacates list" 에 있는 증명서의 관리자에 의해 믿을 수 있다고 증명되는 경우

브라우저를 깔면 "믿을 수 있는 SSL certificates from CAs" 이 같이 깔린다. 이 인증서를 볼 수 있고, 여기에 추가할 수도 있고, 내용을 지울 수도 있다. 이 certificate 이 아주 믿을만한 조직에 의해 통제된다.
만약 서버가 이 certificate list 에 있는 certificate 을 제공한다면 그것을 믿을 수 있다고 판단한다.
ref. 2 을 보면 firefox 는 자체적으로 이 list 를 가지고 있고, chrome 이나 IE 는 Windows 의 certificate repository 를 이용한다고 한다.
ref. 3 에 보면 chrome 도 자체적으로 CRLset 을 가지고 있으면, OCSP 는 전혀 이용하지 않는다고 한다.

이 certificate 이 믿을 수 있는지 점검하는 방법을 local 에 의존하지 않고, CA server 를 사용하기도 하는데, 이것에 대한 protocol 이 OCSP 이다.

2번째는
만약 내가 서버에 접속해서
"네가 '홍길동'이냐"
고 물어보면, 서버가
내가 "홍길동"이고, "전우치가 나를 신뢰하지" 
라고 했다고 하자. 그러면 나는 다시 "전우치"에게 가서
"홍길동 이라는 녀석이 얘기하길 네가 홍길동을 신뢰한다고 했는데 맞느냐?" 
라고 물을 것이다. 이 때 "전우치" 가
"그래 내가 홍길동을 신뢰해" 
라고 한다고 해도 나는 그 홍길동이 내가 접속한 서버인지, 아님 다른 서버인지 알 길이 없다. 그래서 digital signature 가 필요하다.


Digital signature

SSL certificate 은 public/private key 를 가지고 있다. 이것을 이용해서 client 와 server 가 통신에 사용할 symmetric 암호화의 key 를 교환하게 된다.
서버가 클라이언트에게 자신의 public key 를 보내게 되면, client 가 이 public key 를 가지고 symmetric 암호화에 사용할 key(symmetric key 라고 하자.) 를 암호화해서 server 로 보내게 된다.
그러면 서버는 자신이 가진 private key 로 decrypt 해서 key 를 얻게 된다.

digital signature 에서도 이런 방법이 쓰인다. 그런데 반대의 의미로 쓰인다. server 가 가지고 있는 "SSL certificate 에 어떤 믿을만한 기관이 이 SSL certificate 은 내가 보증한다. 라는 식으로 표시"를 해주게 되는데, 이 것이 digital signature 이다.
이 때 이 믿을만한 기관이 이 표시를 자신의 private key 를 사용해서 encrypt 시켜서 SSL certificate 에 붙이게 된다. 그리고 public key 는 SSL certificate 에 그냥 붙어 있다. 그러면 이 SSL certificate 을 확인하려는 client 가 public key 로 이 문서를 확인해서 이 certificate 이 그 기관에서 인증한 것이 맞구나 라고 확인할 수 있게 된다.


한계


근데, SSL certificate 은 누군기 쉽게 훔쳐다 쓸 쑤 있다. 근데 가져가서 자신이 "홍길동" 인척을 해도 결국 symetric key 를 주고받을 때 client  에서 certificate 에 있는 public key 로 암호화해서 던져주는데 이걸 decrypt 할 private key가 없다.

진짜 문제는 다른 유명기관의 certificate 을 조작해서 자신의 private/public key 를 이용해서 새롭게 certificate 을 만들어서 사용하면 문제가 될 수 있다.


SSL 증명서(Certificate)에 들어있는 내용
  • 소유자의 이름
  • 이 소유자의 도메인
  • certificate 의 public key
  • 디지털 사인
  • certificate 의 유효 기간 정보

이외에도 디테일하게 여러 경우들에 대한 처리가 있다고 이야기한다. 그런 부분은 google 에게 물어보자.^^;




안드로이드 개발자 페이지의 SSL 내용


안드로이드 개발자 페이지의 내용을 번역했다. 참고하자.

일반적인 SSL 사용 시나리오
서버는 private key + public key 를 갖고 있는 인증서(certificate)로 설정되어 있다.

SSL client 와 서버사이의 handshake 를 할 때, 서버는 자신이 가진 인증서를 public key 로 암호화를 한다. 이것이 서버가 private key 를 가지고 있다고 증명해 주는 역할을 한다.

그러나 누구나 자신만의 인증서와 private key 를 만들 수 있다. 그래서 단순히 handshake 만으로는 서버를 증명해 줄 수 없다. 단순히 서버가 인증서의 public key 와 matching 되는 private key 를 알고 있다는 정도만 파악할 수 있을 뿐이다.

이 문제를 해결하는 한가지 방법은 client 가 client 자신이 믿을 수 있는 인증서의 목록을 갖고 있게 하는 것이다.

만약 인증서가 client 가 가지고 있는 인증서목록에 없으면 서버는 믿을 수 없게 되는 것이다.

이 간단한 방법은 여러개의 단점을 갖는다. 서버들은 시간이 지남에 따라 더 강력한 키로 업그레이드 할 수 있어야 한다. 불행히도, 서버 인증서가 바뀌면 지금은 클라이언트가 업데이트 돼야 한다.

이것은 특히 서버가 앱 개발자를 컨트롤 할 수 없으면 더 문제가 된다. 예를 들면 서드파티(3rd party) 웹서비스가 서버라면 client 는 웹브라우저나, 이메일 앱등이 되는 것이다.

이런 문제때문에, 서버들은 일반적으로 잘 알려진 발행기관들(issuers)로 부터 인증서를 가지고 와서 서버를 설정한다. 이 잘 알려진 발행기관이 Certificate Authroties(CAs) 가 된다.
호스트 플랫폼(안드로이드, 윈도우즈 같은 OS 를 생각하면 될 듯 하다.)은 일반적으로 그들이 신뢰하는 잘 알려진 CA들의 리스트를 갖고 있다. 안드로이드 4.2(젤리빈)에서, 안드로이드는 100 개가 넘는 CA들을 가지고 있다. 그리고 이들은 매 release 마다 update 된다.

서버도 비슷하다. CA 는 인증서와 private key 를 갖고 있다. 서버를 위해 인증서를 발행할 때, CA 는 서버의 인증서를 그들의 private key 로 sign 해준다. 클라이언트는 “플랫폼이 알고있는 CA” 에 의해 발행된 인증서를 서버가 가지고 있다는 것을 확인할 수 있다.

근데 이것도 문제가 하나 있는데, 그것은 이 CA 들이 발매한 인증서를 A라는 서버에서 쓸 수도 있고, B라는 서버에서도 사용할 수 있다. 이 경우에 클라이언트는 자신이 접속하는 서버가 A 인지 B 인지 알 수 없다. 즉, 어떤 나쁜 서버가 인증서만 가지고 있을 수도 있는 상황이 생길 수 있다. 그래서 서버를 구분짓기 위해 특정이름을 넣는다. 예를 들면 whale.com 또는 *.whale.com 이런식으로 말이다.

아래 명령으로 예를 확인해 볼 수 있다. issuer 는 발행한 기관(CA) 이며, subject 는 그 서버 이름 정보를 가지고 있다.

$$ openssl s_client -connect wikipedia.org:443 | openssl x509 -noout -subject -issuer
subject= /serialNumber=sOrr2rKpMVP70Z6E9BT5reY008SJEdYv/C=US/O=*.wikipedia.org/OU=GT03314600/OU=See www.rapidssl.com/resources/cps (c)11/OU=Domain Control Validated - RapidSSL(R)/CN=*.wikipedia.org
issuer= /C=US/O=GeoTrust, Inc./CN=RapidSSL CA




References

  1. How does HTTPS actually work? | Robert Heaton
  2. tls - How are Chrome and Firefox validating SSL Certificates? - Information Security Stack Exchange
  3. SSL certificate revocation and how it is broken in practice
  4. Server Name Indication - Wikipedia



댓글 없음:

댓글 쓰기