개요
HTTPS는 웹 클라이언트인 브라우저, 예를 들어 크롬이 서버에 리소스를 요청에서 받은 데이터를 어떻게 파싱하고, 어떻게 해석하는지에 대한 방식을 규칙으로 정리한 HTTP에 통신 시 보안(Secure)에 대한 규칙을 합한 것입니다.
이때 CA에서는 특정 서버에 접근하려는 클라이언트에게 '이 서버는 우리 기관에서 검증된 서버야!'라고 인증하여 알려주기 위해 인증서를 발급합니다.
여기서 CA(Certificate Authority)는 인증 기관입니다.
이후 발급된 CA 인증서는 서버가 갖게 되고, 마치 신분증처럼 클라이언트에게 제시할 수 있습니다.
이때 클라이언트가 서버에게 리소스를 요청하면 서버는 클라이언트에게 해당 CA 인증서를 보내게 되죠.
그렇다면 클라이언트는 어떻게 서버를 검증하고, 서버로부터 받은 CA 인증서가 위조 되지 않았다고 어떻게 입증할 수 있을까요?
문제 제기

웹 브라우저에서 CA 인증서를 볼 수 있습니다.
제가 공부하고 있는 HTTPS 관련 교재에서는 해당 CA 인증서를 클라이언트가 CA의 공개키를 통해 검증 할 수 있다고 합니다.
이때 궁금증이 생겼습니다. 그럼 클라이언트는 CA의 공개키를 어디에 어디에 저장하지?
만약 클라이언트가 이를 저장하지 않으면 브라우저가 CA 증명서를 보고 어떤 CA에서 발급 받았는지 알고있으니 그때마다 공개키를 요청하는 것인가?
그렇다면 만약 서버에서 위조된 CA 증명서를 줬고, 클라이언트가 공개키를 요청할 CA 사이에 gateway 등에서 중간자 공격 등으로 위조된 CA의 공개키를 준다면?
그럼 '위조된 CA 증명서를 검증 되었다고 착각하고, 서버를 믿을 수 있는 게 아닌가?'라고 고민했습니다.
본문

결론부터 이야기하면 CA의 인증서는 우리 브라우저나 로컬 컴퓨터에 저장 되어 있습니다.
정확히 이야기 하면 Root CA의 인증서들이 저장 되어 있죠.
mac m2 환경에서는 spotlight > 키체인 접근 > 시스템 루트를 확인하면 Root CA의 인증서들이 존재합니다.
여기에서 Root CA는 OS 등의 기반 소프트웨어를 만든 Apple이나 Microsoft 등의 회사와 여러 어른들이 결정한 가장 대표적인 CA로 알고 있습니다.
클라이언트는 여기에 있는 CA의 공개키로 브라우저가 서버로부터 받은 응답에 있는 CA 증명서를 검증할 수 있을 것처럼 보입니다.
그런데 어떻게 검증할까요?
일단 CA 인증서의 내용을 다시 한 번 생각해볼 필요가 있습니다. 인증서에는 다음과 같은 내용이 있습니다.
- 인증 기관에 대한 내용
- 검증 대상 서버 내용
- 서버의 공개키(엄밀히 이야기하면 해당 인증서 인증 대상의 공개키)
- 인증서 내용 전체를 해싱한 뒤, CA 자신의 비밀키로 암호화 한 데이터
- 사용한 해싱 알고리듬
- 언제까지 이 서버를 보증할 것인지 등

이 사진이 인증서 내용 전체를 해싱 함수에 넣고, 이후 CA 자신의 비밀키로 암호화 한 데이터입니다.
해싱 알고리듬에는 여러 가지가 있는데 그 중 SHA-1은 이미 파훼할 수 있는 알고리듬이지만 널리 사용었기에 넣고, 아직 양자 컴퓨터가 나오지 않는 이상, 근 몇 년은 안전하다고 알려져 있는 SHA-256를 추가로 넣는다고 합니다.
그럼 왜 전체 인증서 내용을 해싱하고, 이미 복호화 할 수 없어 알 수 없는 값을 CA 자신의 비밀키로 암호화 할까요?
이미 전세계 모두가 공개키를 가지고 있음에도 CA가 자신의 비밀키로 해싱된 값을 암호화 하는 이유
먼저 비대칭키인 공개키와 비밀키는 둘 중 하나로 암호화를 하면 다른 하나로 복호화 할 수 있는 매커니즘입니다.
CA의 공개키는 OS 측이든 브라우저 측이든 어떠한 경로로 로컬이나 브라우저에 저장되어 누구에게든지 공유가 되어 있습니다.
때문에 비밀키로 암호화 한 것을 복호화 한다는 것은 안의 내용을 가리기 위한 용도는 아닌 것 같은데요.
그런데도 한 이유는 다음과 같습니다.
클라이언트 각각 저장하고 있는 믿을만한 OS나 브라우저가 저장하게 한 CA 공유키로 복호화가 가능하다는 것은, CA가 이렇게 이야기 하는 것과 같죠.
'그 인증서, 우리 기관에서 만든 게 맞아!'
인증서 전체 내용을 해싱하는 이유
그렇게 CA의 공개키로 복호화한 내용을 뜯어보니 해싱 되어 있는 값이 나왔습니다. 이는 어떻게 사용할까요?
이것이 바로 이 인증서가 위조 되지 않았다는 것을 클라이언트가 확인할 수 있는 것입니다
해싱된 값은 특정한 길이를 가지며 해쉬 함수에 넣은 값이 동일하면 결과값도 항상 동일합니다.

그리고 이는 복호화를 할 수 없어 장난질을 할 수 없죠.
(참고: SHA-256 해쉬 함수는 여기에서 이용해볼 수 있습니다. https://emn178.github.io/online-tools/sha256.html)
그래서 클라이언트는 다음과 같은 과정으로 인증서가 위조되지 않았다는 것을 검증합니다.
- 서버에게 받은 CA 인증서 내용 자체를 CA 인증서에 적혀있는 해싱 함수로 해싱합니다.
- 그렇게 하면 이미 인증서에 있어서 CA의 공개키로 복호화 한 해싱된 값과 브라우저가 직접 해싱한 값, 두 가지가 있습니다.
- 두 값을 비교합니다.
- 이 둘이 같다면 중간에 위조 되지 않은 안전한 인증서라는 것을 증명 할 수 있습니다. 왜냐하면 해싱 알고리듬에 같은 값을 넣으면 항상 같은 결과가 나오기 때문입니다.
클라이언트는 이렇게 내가 요청할 서버가 CA에게 검증된 서버다라는 것을 증명하고, 안심하고 이 서버와 통신할 용기를 가질 수 있습니다.
이후 우리는 안전하게 리소스를 요청할 수 있죠.
결론
사실 위 내용만 보면 전부 올바른 순서로 이루어져 있지 않습니다.
저는 처음에 브라우저를 통해 CA 인증서를 보고 Root CA, 중간 CA, 서버의 인증서 이렇게 세 개를 전부 받는다고 생각했고, Root CA의 공개키는 로컬에서 갖고 있지 않으면 어떻게 이를 믿지?라는 물음에서 시작했으니까요.
엄밀하게 이야기하면 Root CA의 공개키와 인증서는 이미 로컬의 신뢰 기관 목록에 있고, 우리가 접근하려는 서버에서 받는 것은 Root 인증서를 제외한 서버 인증서와 중간 CA 인증서라고 합니다.

본문과 같은 과정을 통해 여기서 이야기하는 서버인 zep.us의 인증서가 검증 되면, 이를 타고 올라가 중간 CA 인증서도 동일한 과정을 거쳐 검증이 되고, 이를 타고 올라가 중간 CA 인증서에 명시된 Root CA의 인증서가 우리 컴퓨터에(신뢰 Root 인증 기관 목록) 존재한다면 아래 모든, 마치 사슬처럼 연결된 기관과 서버가 검증 되었다고 볼 수 있죠.
이러한 방식을 인증서 체인 방식이라고 합니다.
마지막으로 정리하면 인증서 하나의 입장에서 보면 나를 인증해준 인증 기관의 비밀키로 암호화된 암호문이 있고, 이미 나는 인증 기관의 공개키를 갖고 있습니다.
그래서 해당 공개키로 암호문을 해독 가능하고, 해독을 성공적으로 마무리했다면 정말로 그 인증 기관이 발급한 인증서구나라고 방증할 수 있고, 이를 서명이라고 표현합니다.
또한 복호화가 불가능하고, 인증서 내용이 토시 하나 변하면 결과값도 변하며, 입력값이 같을 때 출력값이 바뀌는 해싱 알고리듬을 사용하여 인증서 내용 전체를 해싱해뒀었죠?
이는 브라우저가 직접 인증서 내용 전체를 스스로 해싱한 값과 비교하여 이 인증서가 위조되지 않았음을 증명할 수 있습니다.
참고로 사진에서 보이는 Amazon Root CA 1은 이미 로컬에 있는 인증서가 있기 때문에 서버는 이를 보내줄 필요가 없습니다.
이렇게 HTTPS에서 S에 대한 보안적인 내용을 공부해봤습니다.
'개발 일지' 카테고리의 다른 글
| 개발자가 하드웨어를 공부해봤다 - 메모리 계층 구조 (0) | 2025.09.24 |
|---|---|
| 오픈소스 컨트리뷰션 아카데미(OSSCA) 참여형 Challenges 후기 (6) | 2025.08.11 |
| 제 5회 프로그래머스 데브 코스 커리어 TALK, 취업을 앞당기는 실전 전략과 취업 인사이트 후기 (0) | 2025.07.07 |
| socket.io의 특징과 장단점 (0) | 2024.08.02 |
| socket.io 서버 소켓에서 연결된 클라이언트 소켓 ID와 입장한 room을 찾는 방법 (0) | 2024.08.02 |