Client와 Server가 인터넷이라는 Public한 환경에서 어떻게 비밀을 유지하면서 문서를 교환할 수 있을까?
라는 주제를 해결하기 위해서 어떤 일이 일어나고 있는지 학습해봤습니다.
보안을 유지하면서 소통할 수 있는 방법에 대한 흐름을 한번 요약해보려고 합니다.
먼저, 평문을 안전하게 전달하려면 해당 내용을 아무도 알 수 없도록 암호화하는 과정이 필요합니다. 암호화하는 방법에는 여러가지가 있겠지만 저희가 고려해야할 것은 다시 복호화할 수 있어야 한다는 것입니다. 복호화란 암호문을 다시 평문으로 변환하는 것을 말합니다.
예를 들어 비밀번호 1234
를 암호화할 때 모든 자리수에 1을 더해서 암호화를 하게 되면 암호문은 2345
가 되고 이 정보를 알고있으면 반대로 빼기 연산을 통해 1234
를 구할 수 있습니다.
만약 각 자리수의 값을 2로 나눴을 때의 나머지로 변환을 하면 1010
이 됩니다. 하지만 이 값은 다시 1234
로 되돌릴 방법이 없습니다. 1234
도 1010
이지만 3412
또한 해당 규칙으로 암호화하면 1010
이 되기 때문입니다.
일반적으로 복호화가 불가능한 단방향 암호화를 해시(Hash)라고 합니다.
단방향성을 가지기 때문에 데이터 무결성 확보를 위해 주로 사용합니다. 입력 값의 크기에 상관없이 결과 값의 길이(혹은 크기)가 일정하다는 특징을 가지고 있습니다. 해쉬를 보다 안전하게 설계하기 위해서 Salt 값을 사용하기도 합니다. Hash 알고리즘으로 브루트포싱이 가능하기 때문에 길이가 길 수록 안전해집니다.
<알고리즘>
복호화가 가능한 암호화 방법으로는 대칭키를 사용하는 방식과 비대칭키를 사용하는 방식이 있습니다.
대칭키는 쉽게 생각하면 현실에서 볼 수 있는 키를 떠올리시면 됩니다. 자동차 문을 열 때 사용하는 키와 잠글 때 사용하는 키는 똑같습니다. 일상에서 볼 수 있는 거의 대부분의 키는 대칭키입니다. 암호화와 복호화에 사용하는 키가 동일할 경우 이를 대칭키라고 합니다.
<알고리즘>
비대칭키는 암호화를 할 때와 복호화를 할 때 다른 키를 사용하는 방식입니다. 보통 Public Key와 Private Key로 구분해서 사용하고 두 키 중 하나로 암호화를 하게 되면 쌍을 이루는 다른 키로 복호화할 수 있습니다. 여기서 헷갈리지 말아야할 부분은 암호화하는 키가 정해져있지 않다는 것입니다. Public Key로 암호화하면 Private Key로 복호화할 수 있고, Private Key로 암호화하면 Public Key로 복호화할 수 있습니다.
디지털 서명시에 비대칭키와 해시를 활용합니다. 원본 문서를 해싱한 뒤 Private Key로 암호화해서 문서에 같이 작성합니다. 나중에 PublicKey로 암호화된 해시 내용을 복호화한 값과 문서의 내용을 해싱한 값을 비교해서 무결성을 검증하는 방식으로 인증합니다.
<알고리즘>
대칭키는 비대칭키보다 효율적입니다. 근데 인터넷 환경에서 사용하기 껄끄러운 이유는 키를 안전하게 전달할 방법이 없기 때문입니다. 키를 인터넷을 통해 전달하는 순간 전달하는 문서도 암호화하는 이유가 사라집니다. 따라서 비대칭키 방법은 필연적입니다.
비대칭키를 활용하면 서로 PublicKey를 교환해서 암호화된 문서를 주고받고 복호화할 수 있게됩니다. 가볍게 흐름을 소개하겠습니다.
안전하게 문서를 주고받는 상황에는 성공을 했습니다. 하지만 이 방법에는 문제점이 있습니다.
서버에서 연결해야하는 클라이언트 수만큼 키쌍을 생성해야한다는 것입니다. RSA-2048 알고리즘으로 키쌍을 생성한다고 했을 때 1초가 걸린다 하더라고 클라이언트가 늘어나는 만큼 수행되는 시간이 걸리고 부하가 발생합니다. 그리고 PublicKey는 Internet에 공개되기 때문에 이를 통해 PrivateKey를 유추할 수 있습니다.
비대칭키를 사용하면 보안은 유지할 수 있지만 서버에서 클라이언트마다 비대칭키를 만들어야한다는 단점이 존재했습니다. 이를 개선하는 방법으로 Client에서 대칭키를 사용하는 방법이 있습니다.
위 흐름대로 진행하면 서버는 안전하게 클라이언트의 대칭키를 획득할 수 있습니다. Client마다 다른 대칭키를 보내줄테니 클라이언트 수 만큼 비대칭키 쌍을 만들어야 했었던 단점도 사라졌습니다. 그런데 만약 해커가 Server와 Client 사이에 있다면 어떨까요?
중간에 해커가 존재해서 Client와 Server가 직접 연결되어있는 것처럼 구현되어있다면 어떨까요?
1. Server는 Client에게 Server PublicKey를 전달한다.
2. Hacker는 Server PublicKey를 보관한다.
3. Hacker는 Client에게 Hacker PublicKey를 보낸다.
4. Client는 Client 대칭키를 Hacker PublicKey로 암호화해서 전달합니다.
5. Hacker는 Hacker PrivateKey로 Client 대칭키를 입수합니다.
6. Hacker는 Client 대칭키를 Server PublicKey로 암호화해서 전달합니다.
7. Server는 Server PrivateKey로 복호화해서 Client 대칭키를 입수합니다.
Client에서 Server의 PublicKey를 검증하는 과정이 없기 때문에 중간에 Hacker가 개입됐음에도 불구하고 Server는 마치 Client와 직접 연결된 것처럼 알고 있을 수 있습니다. 문서를 Client와 Server 이외에 제 3자 또한 볼 수 있게되는 문제가 발생할 수 있습니다. 이러한 문제를 해결하기 위해서는 Server의 PublicKey를 검증하는 과정이 필요합니다.
Client에서 Server의 PublicKey를 검증하기 위해서 인증 기관을 통해서 Server의 비대칭키쌍을 만듭니다. CA라는 인증기관을 통해서 Server의 비대칭키쌍을 만들게 되는데 이 과정을 살펴보겠습니다.
이때 생성되는 Server의 PublicKey는 x.509 인증서 형태로 보관된다. 이는 Server에서 필요한 내용과 함께 전체 내용을 해싱한 값을 CA의 PrivateKey를 이용해서 암호화된 상태로 같이 저장해둔다. 이 상태로 키를 발급하게 되면 Client에서는 CA에게 PublicKey를 제공받아서 Server가 보낸 PublicKey이지 확인할 수 있다. Client에서는 OS 별로 기관 인증서의 PublicKey를 가지고 있다. Windows 환경이라면 MS에서 업데이트할 때 해당 키를 업데이트 해준다. 그럼 이제 어떻게 연결이 이뤄지는지 확인해봅시다.
이를 PKI 기반 인증체계라고 합니다. 대부분의 서버에서는 해당 구조를 이용해서 클라이언트와 안전한 상태에서 HTTP를 주고받고 SSL 인증이 포함된 프로토콜을 HTTPS라고 부릅니다.