왜? https는 비대칭키를 사용해서 대칭키를 나누고 이를 사용할까?
그냥 비대칭키를 계속 사용하면 되지 않을까?
라는 질문을 받았다.
대답할 수 없어서 글을 쓰면서 다음엔 대답할 수 있는 개발자가 되어보자
먼저 결론부터 말하면
1. 비대칭 키는 느리다.
2. 클라이언트의 공개키를 서버가 기억해야 하므로 무상태성이 깨진다.
먼저 대칭키랑 암호화, 복호화에 사용하는 키가 동일하다.
비대칭키/ 공개키 : 암호화, 복호화에 사용하는 키가 서로 다르다.
대칭키
세션키, 시크릿 키, 공유 키, 대칭키 ,단용키 라고도 부른다.
비대칭키
장점
단점
- 상대적으로 키의 길이가 길다.
- 연산속도가 느리다.
수신자의 공개키로 암호화하면 이를 수신자의 개인키로 복호화해서 볼 수 있다. (수신자만 해독가능)
서버는 개인키를 소유하고 있다 절대 노출되면 안되는 키다.
공개키는 누구나 사용할 수 있다.
그래서 클라이언트는 공개키로 암호화하고 서버에 보내면 이를 해독할 수 있는건 오직 개인키 뿐이니까
안전하게 요청을 보낼 수 있다.
자 그럼 서버에서 개인키로 암호화해서 클라이언트로 보내면 중간에 누가 탈취하면 누구나 공개키를 알 수 있으니까 응답 내용을 다른 사람이 볼 수 있는거 아닐까?
먼저 결론부터 말하면 서버는 민감 정보를 보내지 않는다.
진짜 서버가 보낸 응답인지 검증할 뿐이다. 개인키로 암호화한 것만 공개키로 열리니까
이게 진짜 서버에서 왔다 변조가 안됐다는걸 보장할 수 있는거다.
그럼? 내용은 어떻게 암호화할건데요? (기밀성 보장은 어떻게?)
내가 자주 헷갈렸던 부분은 서버에서 대칭키를 만들어서 개인키로 암호화하고 클라이언트랑 공유한다고 생각했다. 하지만 반대였다. 클라이언트가 공개키로 암호화해서 서버에 대칭키를 공유하는 것이다.
그럼 서버만 해독할 수 있는 공개키로 암호화 했기 때문에 안전하게 대칭키를 공유할 수 있다.
여기서 궁금한 건 그럼 비대칭 키만 이용해서는 계속 통신할 수 없을까?
서버도 개인키/공개키를 가지고 있고 클라이언트도 개인키/공개키를 가지고 있다면 각자의 공개키로 암호화해서 보내는 방식으로 통신은 가능할 것이다.
근데 이게 대칭키를 공유해서 사용하는 방식보다 느리다고 한다.
느리다. 비대칭 키 왜 느릴까?
구조적인 차이 때문이라고 한다.
| 항목 | 비대칭키 (RSA, ECC) | 대칭키 (AES 등) |
|---|---|---|
| 암호화/ 복호화 속도 | 느림(1000~ 1000배 이상 느림) | 매우 빠름 |
| 키 길이 | 길다( 2048 ~ 4096 bit) | 짧다(128~256bit) |
| CPU 사용량 | 높음 (수학적으로 무거운 연산) | 낮음 |
| 데이터 양 | 적은 데이터에 적합 | 큰 데이터에 적합 |
WHY? 비대칭키랑 대칭키의 암호화 방식이 다를까?
둘 다 암호화한다는 목적이 같은데 왜 서로 다른 것을 사용하고 그래서 암호화, 복호화 속도까지 느리게할까?
좋은게 좋은거라고 안전하고 빠른 방법을 둘 다 선택해서 사용하면 되는거 아닐까? 라는 의문이 든다.
먼저 RSA / ECC 는 키 공유 + 인증 을 위한 알고리즘 이라고 한다.
AES는 “데이터 보안”을 위한 알고리즘이다.
이렇게 작성해두면 잘 와닿지 않는다.
좀 풀어서 얘기하면 비대칭 키 방식은 우체통과 같다. 누구나 편지를 넣을 수 우체통 키를 가지고 있는 우체부만 편지를 꺼낼 수 있다. RSA/ ECC 는 우체통과 같은 구조를 만들어주는 알고리즘이다.
근데 이 알고리즘은 CPU 사용량이 높기에 많이 사용한다면 통신 비용이 증가할 것이다.
이에 비해 단순한 구조르 가진 대칭키가 있다. 대칭키는 예를 들자면 현관문 전자 비밀번호 같은 것 이다. 비밀번호를 아는 누구나 출입 가능한다. 근데 한가지 문제점은 이 비밀번호르 어떻게 안전하게 공유할 것 이냐는 것이다.
자 이 문제를 해결하기 위해서 HTTPS는 비대칭키랑 대칭키를 적절히 함께 사용하는 것이다.
서버는 클라이언트의 공개키를 알기 힘들다
기본적으로 HTTPS 에서는 클라이언트는 익명이다.
그럼 클라이언트가 공개키를 서버에 보내면 되잖아?
키 관리가 복잡할 것 같다.
서버는 클라이언트마다 키를 관리하고 그에 맞는 공개키로 암호화해서 보내야 하니까
무상태를 유지 할 수 없을 것이다.
그리고 클라이언트가 보낸 공개키가 진짜냐?를 검증할 수 있는 방법이 없다. (근데 검증을 해야할까?)