전송 계층 보안(TLS)
데이터를 주고 받을 때, 암호화 하는 일반적인 방법에 대해. 과거에는 SSL(Secure Sockets Layer)라는 이름으로 불렸음.
데이터 전송의 암호화는 아래와 같은 순서로 발전한다.
- 평문으로 데이터 주고 받기
- 암호화 해서 주고 받기
- 동일한 암호키를 사용하기
- Q. 암호화 키를 어떻게 싱크할 것인가?
- 비대칭키를 통해 주고 받기
- private key가 있는 서버만 평문 내용을 알 수 있다.
- Q. 통신 하는 대상은 믿을만 한가?
- 자격 증명을 함께 전송하기
- CA를 통해 신용을 확보한다.
평문으로 데이터 주고 받기
유저와 서버가 데이터를 평문으로 주고 받는다면, 통신이 감청 되었을 때 주고 받는 정보가 그대로 보인다.
암호화 해서 주고 받기
유저와 서버는 미리 정해둔 암호키(encryption key)를 사용해서 정보를 암호화 한다. 암호화된 데이터가 돌아다니기에 통신이 감청되어도 정보를 알 수 없다.
유저와 서버가 미리 아는 사이라면, 암호키를 미리 정해둘 수 있을 것이다. 그러나 99.9%의 유저-서버 쌍은 서로 처음 본다. 즉, 둘 사이에 미리 정해둔 암호키가 존재할리 없다.
그렇다고, 암호키를 인터넷을 통해 주고 받는다면, 통신 감청을 통해 암호키가 노출될 수 있다. 이러면 헛수고다!
비대칭키를 통해 주고 받기
서버는 개인키(private key)와 공개키(public key)를 만든다. 통신을 준비할 때, 서버는 유저에게 서버 공개키를 보낸다. 유저는 서버의 공개키로 암호키를 암호화 해서 보낸다.
비대칭키로 암호화 되었으므로 유저가 서버 공개키로 암호화한 값은 서버 개인키가 있는 서버 자신만 해독할 수 있다.
해독한 암호키로 다시 대칭키 암호화하여 데이터를 주고 받는다.
그런데, 해커가 트래픽을 조정해서 서버 자체를 사칭 한다면? 이 방식을 사용하더라도 유저가 사칭한 서버를 믿고 데이터를 보내면 헛수고다!
SSL 인증서로 자신을 증명하기
서버는 자격 증명인 “SSL Certificate”를 유저에게 보내어 자신이 진짜 서버임을 증명한다.
유저는 서버 인증서를 보고, 통신하는 서버가 사칭 서버가 아닌 실제 서버인지 확인한다. 실제 서버인지 확인 했다면, 비대칭키 방식으로 보안 연결을 수립하고 통신한다.
서버 인증서와 CA
CA(Certificate Authority)는 신뢰할 만한 인증 기관으로, 서버 인증서를 발급해준다. 서버 인증서에는 아래의 내용이 들어있다.
- 인증서 소유자 이름
- 인증서 소유자의 공개키
- 당연히 소유자의 개인키는 노출되지 않는다!
- 인증서의 유효기간
- CA의 서명(signature)
- 소유자의 공개키를 CA의 비밀키로 암호화
- 해커가 절대 위조할 수 없음!
- CA 서명의 해싱 알고리즘
이 내용은 CA의 개인키로 암호화 되어 서버에서 파일로 보관했다가 유저와 통신할 때 사용한다.
서버 인증서의 검증
유저는 서버의 인증서를 받았다. 유저는 서버 인증서에 담긴 CA의 서명을 CA의 공개키로 복호화 한다. CA의 공개키는 브라우저에 내장되어 있다.
server_public_key = "12345"
CA_signature = "abcdefg"
CA_hash_function = "SHA-256"
hashed1 = do_decrypt(CA_signature, CA_public_key)
hashed2 = do_hashing(server_public_key, CA_hash_function)
if hashed1 == hashed2:
print("Truth Certificate!")
else:
print("Hacker!!")
해커가 인증서에 흠집을 냈다고 생각해보자.
사칭된 서버 공개키를 썼다면?
해싱의 원리에 의해 해싱키가 다르면, 해싱 값이 다르게 나온다. 즉, 올바른 서버 공개키가 적혀있지 않으면, 서명을 복호화한 hashed1
의 값과 맞지 않게 된다.
정말로 사칭하고 싶다면, do_hashing()
의 값이 hashed2
가 되는 실제 서버 공개키와는 다른 공개키-비밀키 쌍을 찾아야 한다. 그러나 이것은 불가능하다.
사칭된 서명을 썼다면?
CA 공개키는 누구나 다 알고 있으니, 사칭된 서명도 복호화할 수는 있다. 그러나 복호화된 값이 실제 공개키의 해싱 값 hashed2
와 맞지 않는다.
정말로 사칭하고 싶다면, do_decrypt()
의 값이 hashed1
이 되는 실제 CA 서명과 다른 서명값을 찾아야 한다. 그러나 이것은 불가능하다.
서버 인증서를 그대로 쓴다면?
“에라 모르겠다!”하고 서버 공개키도 CA 서명도 위조 할 수 없음을 깨달은 해커는 올바른 서버 인증서를 그대로 사칭 서버에서 그대로 쓰기로 마음 먹었다.
그러나 이 방식으로 유저의 CA 검증은 통과해도, 실제 서버 공개키에 대응되는 실제 서버 비밀키를 모르기 때문에 유저가 보낸 암호키를 제대로 복호화 할 수가 없다.
결론: 사칭은 불가능하다
결국 (1) 해싱 알고리즘의 단방향 암호화, 그리고 (2) CA 비밀키를 알 수 없다는 점 때문에 해커는 공개키와 CA 서명 어떤 것도 흠집을 낼 수 없다.