대칭키부터 PKI 체계까지
서버와 클라이언트의 암호화 통신이 어떻게 발전했는지 정리하면서, PKI 구성에 대해서 알아보겠습니다.
해싱 알고리즘
해싱 알고리즘은 단방향 함수로, 입력값을 고정된 크기의 해시값으로 변환하며, 이 해시값으로부터 원래의 입력값을 복원하는 것은 불가능합니다.
예를 들어, SHA-256 해싱 알고리즘은 어떤 길이의 데이터든 고정된 256비트의 해시값으로 변환합니다.
중요한 점은 해시값에서 원래 데이터를 복원하는 것이 불가능하다는 것입니다.
비대칭 암호화 방식
대칭키는 인터넷 환경에서 사용하기에 부적합합니다.
클라이언트나 서버가 대칭키를 주고 받을때 어쩔 수 없이 인터넷을 거쳐야하며, 이 때 키가 고스란히 노출되기 때문인데요.
그래서 이러한 문제를 비대칭 암호화 방식을 활용해서 해결하고자 합니다. 이 방식은 데이터 보안을 강화하기 위해 공개키와 개인키를 사용합니다.
간단하게 동작 순서에 대해서 알아보면 아래와 같습니다.
먼저 3-way hand shake을 통해서 TCP 커낵션을 맺습니다.
PC와 서버는 각자의 퍼블릭키와 프라이빗키를 준비합니다.
서버와 클라이언트는 각자의 퍼블릭 키를 교환합니다.
클라이언트는 서버의 퍼블릭키로 암호화해서 데이터를 전송하고 서버는 본인의 프라이빗 키로 데이터를 복호화합니다.
반대로 서버는 클라이언트의 퍼블릭키로 암호화해서 데이터를 전송하고 클라이언트는 본인의 프라이빗키로 데이터를 복호화합니다.
TCP 연결이 맺어지면 논리적인 세션을 형성하게 되는데, 이때 데이터를 안전하게 암호화하는 위 과정을 거치면, ‘암호화된 연결(터널)’이 형성되었다고 표현합니다.
대표적인 비대칭키 알고리즘으로 RSA가 있습니다. RSA는 해싱과 다르게 데이터의 암호화와 복호화에 사용됩니다.
비대칭과 대칭 암호화 방식의 혼합
비대칭 암호화 방식은 매우 안전하지만, 암호화 및 복호화 과정이 계산적으로 복잡하여 시간이 많이 소요됩니다.
특히, 데이터가 크거나 실시간으로 많은 양의 데이터를 전송해야 하는 경우, 성능 저하가 문제가 될 수 있습니다.
반면에 많이 쓰이는 AES와 같은 대칭키 알고리즘과 같은 경우에는 프로세서 하드웨어에 최적화되어 내장되어있는 경우도 많습니다.
또한 비대칭키 암호화는 RSA 알고리즘을 사용하는데, 안전성을 유지하기 위해 긴 키 길이를 필요로 합니다.
이러한 이유로 비대칭 암호화 방식 대신, 대칭키와 비대칭키를 혼합해서 사용하는 방법을 주로 사용합니다.
요약하면 아래와 같습니다.
먼저 서버는 클라이언트로 퍼블릭 키를 제공합니다.
그리고 클라이언트는 대칭키를 생성하고, 제공받은 서버의 퍼블릭키로 대칭키를 암호화해서 서버에 전달합니다.
그리고 서버는 해당 대칭키를 자신의 프라이빗키로 복호화합니다. 이 때의 대칭키를 세션키라고 부릅니다.
이를 통해서 이제 비용에 대한 문제는 해결했습니다.
MITM(Man In The Middle)
이제는 MITM이라는 중간자 공격을 해결해야하는데요.
먼저 MITM이 어떤 공격인지 알아보겠습니다.
TCP 커낵션이 맺어지고 암호화 통신을 위해서 PC가 서버에게 퍼블릭 키를 요청합니다.
이에 따라 서버가 퍼블릭키를 클라이언트에게 제공해주는데, 이 과정은 인터넷을 통해서 이뤄집니다.
그렇기 때문에, 해커가 해당 패킷을 가로챌 수 있는데요.
여기에서 서버의 퍼블릭 키를 자신의 퍼블릭키로 바꿔치기할 수 있습니다.
그리고 다시 클라이언트에게 위조된 패킷을 전송합니다.
그러면 클라이언트는 아무것도 모르고 해커의 퍼블릭 키를 기반으로 본인의 세션키를 암호화해서 보내게됩니다.
그러면 해커는 다시 인터넷을 경유하는 패킷을 낚아챕니다.
그리고 본인의 프라이빗키로 복호화해서 클라이언트가 보낸 세션키를 탈취합니다.
그리고 나서는 해당 세션키를 앞에서 낚아챈 서버의 퍼블릭키로 암호화해서 서버로 보냅니다.
그러면 서버는 자신의 프라이빗키로 해당 요청을 복호화하게되며 중간에 어떠한 일이 발생했는지 모르게됩니다.
결과적으로 서버와 클라이언트가 통신할 때 사용하는 세션키를 악의적인 해커가 탈취에 성공하게되고, 앞으로 주고받는 모든 데이터는 해커가 복호화할 수 있게 됩니다.
그래서 MITM 공격을 해결하기 위해서는 클라이언트가 퍼블릭키를 받을때, 내가 요청을 보낸 서버에서 보내준 퍼블릭 키가 맞는지 검증을 해야합니다.
그래서 퍼블릭 키에 대한 검증을 위한 인증체계가 만들어지게 되었고, 이게 바로 PKI(Public Key Interface)입니다.
PKI(Public Key Interface)
PKI의 전반적인 구조를 이해하기 위해서, 현실세계의 내용증명서를 생각하면 쉽습니다.
내용증명서는 개인 간의 계약 내용을 증명하기 위해 우체국과 같은 공공기관에서 보관해주는 문서를 의미합니다.
PKI 체계에서, 내용증명서를 인증서라고 부르며 우체국과 같은 공공기관을 CA라고 부릅니다.
먼저 서버는 퍼블릭 키와 프라이빗 키 쌍을 생성합니다.
그런 다음 서버는 퍼블릭 키와 몇 가지 필요한 정보를 포함하여 CSR(Certificate Signing Request)을 생성하고, 이를 CA에 제출합니다.
그러면 CA는 CSR을 검토하여 X.509 형식의 SSL 인증서를 생성합니다.
SSL 인증서는 아래 구성으로 이루어져있습니다.
- 서버의 정보
- 서버의 퍼블릭 키
- 서버 정보와 서버가 생성한 퍼블릭 키를 SHA 256와 같은 해싱 알고리즘으로 뽑아낸 해시값을, CA의 프라이빗키로 서명한 값
만들어진 인증서를 CA가 서버에게 전달하면 서버는 이를 웹서버에 저장합니다.
서버와 클라이언트는 퍼블릭 키를 직접 주고받는 대신, X.509 형식의 인증서를 주고 받습니다.
클라이언트는 이제 인증서에 포함된 퍼블릭 키를 사용하여 세션 키를 교환하면 됩니다.
그러면 단순하게 퍼블릭키를 주고받는것과 다르게, 인증서를 주고받음으로써 MITM 공격을 어떻게 해결하는지 알아보겠습니다.
CA는 클라이언트와 서버가 서로 신뢰하는 기관이어야 합니다. OS를 설치하면 보통 OS에 미리 신뢰하는 기관에 대한 기관 인증서가 저장되어 있습니다.
여기서 기관 인증서는 CA의 퍼블릭 키를 의미합니다. 즉, 클라이언트는 미리 CA의 퍼블릭 키를 알고 있습니다.
클라이언트가 서버로부터 인증서를 제공받으면, 먼저 발행자 정보가 통신하고자 하는 서버와 일치하는지 확인합니다.
그리고 아래의 두 데이터가 같은지 확인합니다.
- 클라이언트가 해싱 알고리즘으로 서버의 정보와 서버의 퍼블릭 키를 해시화한 값
- 클라이언트가 서명값을 CA의 퍼블릭키로 복호화해서 얻은 해시값
만약 해커가 인증서 내용을 조금이라도 변조한다면, 두개의 결과값이 다릅니다.
두개의 데이터가 다르다면 클라이언트는 MITM 공격 여부를 알 수 있게 되는것이죠.
이로써 클라이언트는 무결성이 보장된 퍼블릭키를 사용합니다.
공인 인증서
원래는 한국에서는 공공기관만 CA가 가능했는데요.
이것을 민간 기업에서도 가능하도록 법을 변경하면서, 카카오 인증서나 네이버 인증서가 등장하게된 것입니다.
그래서 공공기관에서 발급하면 공인인증서, 민간 기업에서 발급하면 **인증서와 같은 이름이 붙습니다.
지금까지 설명한 퍼블릭 키에 대한 검증이 목적이 아닌, 인증의 목적으로도 공인인증서는 사용되는데요.
우리은행이나 국민은행은 RA로써 대행자 역할을하고, 같은 CA를 사용함으로써 하나의 인증서로 호환이 되도록 구성해뒀는데요.
이 때 제공해주는 공인인증서는 인증의 목적으로 사용됩니다.
우리가 은행과같은 RA로 부터 인증서를 받으면, 퍼블릭키로 이루어진 x.509 형식 인증서와 프라이빗키를 usb에 저장합니다.
그리고 usb를 꼽고 은행과 통신하게되면, 은행들은 해당 인증서를 기관인증서로 복호화해보고 user information을 통해서 인증을 해줍니다.
즉, 인터넷 통신에서 인증서가 퍼블릭키 전달과 퍼블릭키에 대한 검증을 위해서 사용되는것과 다르게, 은행 서비스에서는 요청자의 신원 확인을 위해 사용됩니다.
요약
sequenceDiagram
participant 클라이언트
participant 서버
Note right of 서버: 서버는 사전에 CA로부터 인증서를 발급받음
Note right of 클라이언트: 클라이언트는 사전에 브라우저에 CA의 공개키를 저장함
클라이언트->>서버: 3-way handshake 시작 (TCP 연결)
서버-->>클라이언트: 핸드셰이크 확인 및 완료
서버-->>클라이언트: CA 서명된 인증서 전송
클라이언트->>클라이언트: CA의 공개키로 인증서 검증 (해시값 확인)
alt 유효한 인증서
클라이언트->>서버: 세션 키 생성 및 서버의 공개키로 암호화
서버->>서버: 개인키로 세션 키 복호화
Note over 클라이언트,서버: 세션 키를 사용한 암호화된 연결 설정
클라이언트->>서버: 안전한 데이터 전송
서버-->>클라이언트: 안전한 데이터 전송
else 유효하지 않은 인증서
클라이언트->>서버: 연결 종료
end