[Security] 암호기술에 대한 최소 이론 10강 — 인증서와 CA, SSL이 신뢰를 만드는 방법
암호기술에 대한 최소 이론 시리즈 정리 — 10강. 참고: 널널한 개발자 TV, 인증 시스템이 포함된 SSL 통신 및 인증서 검증원리 (재생목록)
지금까지 쌓아 온 구조에는 구멍이 하나 남아 있다. 서버가 공개키를 보내오고 PC는 그 공개키로 세션 키를 암호화해 건넨다. 그런데 그 공개키가 정말 그 서버의 것인지 확인할 방법이 없다. 중간에서 누가 서버의 공개키를 가로채 자기 공개키로 바꿔치기해도 PC는 알아차리지 못한다(9강). 이번에는 그 구멍을 메우는 마지막 조각을 정리한다. 서로 얼굴도 못 보는 두 통신 주체 사이에 제3의 기관을 세우고, 공개키에 발급 정보와 서명을 붙여 인증서로 만들고, 받은 쪽이 그 인증서를 검증하는 체계다. 이 체계를 HTTP에 얹은 것이 HTTPS이고, 그 계층 기술의 이름이 SSL이다. 시리즈에서 가장 무거운 편이지만, 여기까지가 SSL 통신의 골격 전부다.
문제 — 상대가 보낸 키를 신뢰해야 하나
먼저 문제를 정확히 세우자. 인터넷으로 연결된 두 엔드포인트가 있다. 한쪽은 PC, 한쪽은 서버다. 둘은 서로 떨어져 있고, 얼굴을 본 적도 없고, 앞으로도 볼 일이 없다.
이 상황에서 상대가 보내준 키를 신뢰해야 하나, 말아야 하나. 이것이 문제다. 서로를 확인할 수단이 통신 회선 하나뿐인데, 그 회선 자체가 위조가 가능한 구간이다. 회선 안에서만 답을 찾으려 하면 답이 나오지 않는다.
그래서 방법은 의외로 단순하다. 회선 밖에 제3의 기관을 등장시킨다. PC도 그 기관을 신뢰하고, 서버도 그 기관을 신뢰한다. 이 전제를 깔면 둘은 서로를 직접 믿을 필요가 없다. 둘 다 믿는 제3자가 "이 공개키는 저 서버 것이 맞다"고 보증해 주면 된다.
제3자 : [ 인증 기관 ] ← 둘 다 신뢰하는 기관
▲
├─ "이 기관은 믿는다" ──── [ PC ]
└─ "이 기관은 믿는다" ──── [ 서버 ]
회선 : [ PC ] ──── 인터넷 ──── [ 서버 ] (서로는 못 믿는다)
신뢰를 직접 만들어 내는 대신 신뢰를 위임한다. 이것이 인증 체계의 출발점이다.
인증 기관의 구조 — CA와 RA
그 기관 체계 안에는 크게 둘이 있다.
- CA(Certificate Authority) — 인증서를 발급하고 그 인증서에 최종적으로 서명하는 주체다. VeriSign, Comodo 같은 회사가 대표적인 CA다.
- RA(Registration Authority) — CA와 연결된 파트너로, 실제로 키 쌍 발급 요청을 받고 신청자를 확인해 처리하는 창구 역할을 한다.
CA와 RA 사이에는 발급된 인증서 목록을 담은 데이터베이스가 놓여 있다. 양쪽이 여기에 접근해 등록하고 조회한다. 둘 사이의 신뢰 관계와 등록·검증 처리는 그 자체로 복잡한 절차이고, 그쪽은 자기들끼리 알아서 보안을 유지한다. 여기서는 깊이 들어가지 않는다.
인증 기관 체계
├─ [ CA ] : 인증서 최종 서명
├─ [ RA ] : 발급 창구
└─ 인증서 목록 DB : CA·RA가 공유 — 양쪽이 등록하고 조회
[ 회사 A / 서버 ] ──── 키 쌍 요청 ────▶ [ RA ]
키 쌍을 서버가 직접 만들지 않는다
앞에서는 서버가 자기 키 쌍을 스스로 만들었다. 이 부분이 바뀐다.
어떤 회사 A가 서버를 운영한다고 하자. A는 자기 손으로 키를 만드는 대신 RA에 요청한다. 순서는 이렇다.
① 요청 : [ 회사 A ] ──── "키 쌍 좀 만들어 줘" ────▶ [ RA ]
② 생성 : [ RA ] 에서 A의 공개키 · A의 개인키 생성
③ 전달 : [ RA ] ──── 키 쌍 전달 ────▶ [ 회사 A ]
└─ 받은 키 쌍을 서버 디스크에 저장
요청할 때는 그냥 "키 주세요"가 아니다. 누가 쓸 것인지, 어느 조직인지 같은 여러 항목의 정보를 함께 낸다. 이 정보가 뒤에서 결정적인 역할을 한다.
여기까지만 보면 "누가 만들었냐"만 달라진 것 같다. 키 쌍 자체는 이전과 다를 게 없다. 차이는 다른 데 있다.
핵심 변화 — 공개키가 혼자 오지 않는다
전에는 공개키 하나만 달랑 날아왔다. 이제는 그 공개키에 정보가 잔뜩 붙어서 온다.
붙는 것들은 이렇다.
- 이 키를 누가 발급받았는가 (발급 대상)
- 언제 발급됐고 유효기간은 언제까지인가
- 어떤 알고리즘을 썼는가
- 무결성 보장을 위한 해시
- 그리고 서명
이 묶음 전체를 인증서(certificate) 라고 부른다. 널리 쓰이는 인증서 형식의 표준 이름은 X.509다.
인증서 (X.509)
├─ 공개키 ← 원래 주고받던 것
├─ 발급 대상 : 회사 A
├─ 발급자 : CA
├─ 발급일 / 유효기간
├─ 공개키 알고리즘
├─ 해시 (무결성)
└─ 서명 : 위 해시를 CA 개인키로 암호화한 값
그래서 키 교환 단계에서 서버가 PC에 보내는 것도 바뀐다. 공개키가 아니라 인증서를 보낸다.
[ 이전 ] 서버 ──── 공개키 ────▶ PC
└─ 검증할 근거가 없다
[ 이후 ] 서버 ──── 인증서 ────▶ PC
└─ 공개키 + 발급 정보 + 해시 + 서명 — 검증할 근거가 함께 온다
| 구분 | 공개키만 주고받던 구조 | 인증서 구조 |
|---|---|---|
| 키 쌍 생성 주체 | 서버가 직접 생성 | RA에 요청해 발급받음 |
| 전달되는 것 | 공개키 하나 | 인증서(공개키 + 부가 정보) |
| 보증하는 주체 | 없음 | 인증서에 서명한 CA |
| 받은 쪽의 판단 근거 | 없음 — 믿는 수밖에 없다 | 서명 검증 결과 |
| 바꿔치기 대응 | 불가능 — 알아챌 수 없다 | 검증 실패로 드러난다 |
받는 쪽이 판단할 근거가 함께 온다는 것, 이것이 인증서가 만들어 내는 유일하고 결정적인 차이다.
검증 원리 ① — 서명은 개인키로 암호화한 해시다
이제 PC가 인증서를 어떻게 검증하는지 볼 차례다. 여기서 키 쌍의 낯선 용법이 하나 나온다.
지금까지는 공개키로 암호화하고 개인키로 풀었다. 그런데 키 쌍은 이 역할을 반대로 쓰는 것도 가능하다. 즉 개인키로 암호화하고 공개키로 푸는 것도 된다. 둘의 용도를 서로 바꿔도 수학적으로 성립한다.
인증서의 서명이 바로 이 반대 방향 용법을 쓴다. 인증서 안의 해시는 CA의 개인키로 암호화되어 들어가 있다. 이렇게 만들어진 값을 서명이라고 부르고, 이런 방식으로 만든 서명을 전자서명이라고도 한다.
일반적인 용법 : 공개키로 암호화 → 개인키로 복호화 (기밀성)
서명의 용법 : 개인키로 암호화 → 공개키로 복호화 (보증)
CA의 개인키는 CA만 가지고 있다. 그러니 CA의 공개키로 풀리는 값을 만들 수 있는 것은 CA뿐이다. "이 값은 CA가 만들었다"가 여기서 증명된다.
검증 원리 ② — CA의 공개키는 이미 PC에 있다
서명을 풀려면 CA의 공개키가 필요하다. 그런데 그 공개키를 인터넷으로 받아 온다면 같은 문제가 반복된다. 그래서 CA의 공개키는 통신 중에 받는 것이 아니라 PC에 미리 깔려 있다.
운영체제 회사가 CA와 제휴를 맺는다. 그리고 운영체제 업데이트를 할 때 CA의 공개키를 CA의 인증서 형태로 PC에 설치한다. 윈도우라면 Windows Update가 이 일을 한다. 인증서를 업데이트하는 항목이 종종 보이는 이유가 이것이다.
윈도우에서는 실행 창에 certmgr.msc를 입력하면 이 저장소를 직접 볼 수 있다. "신뢰할 수 있는 루트 인증 기관" 항목을 열면 미리 설치된 기관 인증서 목록이 나온다. 앞에서 CA로 언급한 회사들의 인증서도 여기에 들어 있다. 인증서 하나를 열어 보면 이런 필드들이 보인다.
| 필드 | 내용 |
|---|---|
| 버전 | V3 |
| 일련번호 | 인증서마다 부여된 고유 번호 |
| 서명 알고리즘 | 예: SHA-384 계열 |
| 발급자 / 발급 대상 | 어느 기관이 발급했고 누구에게 발급됐는가 |
| 유효기간 | 시작일과 만료일 |
| 공개키 / 공개키 알고리즘 | 실제 키 값과 그 알고리즘 |
| 키 식별자 | 키를 가리키는 식별 값 |
| 지문(thumbprint) | 인증서 전체의 해시 값 |
이렇게 운영체제에 미리 깔려 있는 기관 인증서를 루트 인증서라고 부르고, 루트 인증서에서 서버 인증서까지 이어지는 서명 관계를 신뢰 체인이라고 부른다. 여기서는 이름만 짚고 넘어간다.
검증 원리 ③ — 해시 두 개를 맞춰 본다
재료가 다 모였다. PC가 서버에게서 인증서를 받았을 때 하는 일은 두 갈래다.
한쪽 갈래에서는 인증서 안의 정보를 전부 모아 해시를 직접 계산한다. 다른 쪽 갈래에서는 인증서에 붙어 온 서명을 CA 공개키로 복호화한다. 그러면 CA가 발급 시점에 계산해 넣어 둔 해시가 나온다.
그리고 둘을 비교한다.
받은 인증서
├─ 인증서 정보 전체 ─[ 해시 계산 ]─▶ 해시 A
└─ 서명 ─[ CA 공개키로 복호화 ]─▶ 해시 B (키는 루트 인증서에)
해시 A == 해시 B ─▶ 검증 성공 : 신뢰하는 CA가 보증한 공개키
해시 A != 해시 B ─▶ 검증 실패 : 조작 또는 바꿔치기
두 값이 같으면 결론은 이렇게 된다. "나는 이 CA를 신뢰한다. 그 CA가 이 공개키를 저 서버의 것이라고 보증했다. 그러므로 이 공개키는 해커의 것이 아니라 진짜 서버의 공개키다." 9강에서 답할 수 없었던 질문에 드디어 답이 나온다.
해커가 개입하면 어떻게 되는지도 자동으로 정해진다. 인증서 안의 정보를 조작하면 해시 A가 달라져서 해시 B와 어긋난다. 서버 공개키를 자기 공개키로 바꿔치기해도 마찬가지다. 그러면 새 정보에 맞는 해시를 다시 계산해 서명을 새로 만들어 넣으면 되지 않느냐는 반문이 나올 수 있는데, 그러려면 CA의 개인키가 있어야 한다. 그것이 없으면 CA 공개키로 풀리는 서명을 만들 수 없다. 그래서 조작이 아예 작동하지 않는다. 하려면 할 수는 있으나 불가능에 가깝게 되어 있다.
HTTPS와 SSL
이 체계를 웹에 적용하면 무엇이 되는지가 남았다.
서버가 웹 서버라면 그 통신은 HTTP를 쓴다. HTTP는 평문 프로토콜이라 오가는 내용이 그대로 노출된다. 여기에 지금까지 정리한 PKI 기술을 적용해 트래픽을 암호화하면 HTTP가 HTTPS가 된다. 그 암호화를 담당하는 계층 기술의 이름이 SSL(Secure Socket Layer) 이다. SSL은 이후 TLS(Transport Layer Security)로 이름과 규격이 이어졌고, 지금 쓰이는 것은 TLS 쪽이지만 관례적으로 SSL이라는 이름이 함께 쓰인다.
브라우저에서 확인할 수 있다. HTTPS 사이트에 접속하면 주소창에 자물쇠 아이콘이 뜬다. 눌러 보면 연결이 안전하다는 표시와 함께 인증서가 유효함이라는 문구가 나오고, 인증서 정보를 열면 앞에서 본 필드들이 그대로 보인다.
- 공개키 — 여기에 실제 키와 알고리즘이 표시된다. 요즘은 타원곡선 암호(ECC) 계열이 자주 보인다. RSA보다 같은 강도에서 키가 짧고 성능이 좋다.
- 지문 — SHA-256 같은 해시 알고리즘으로 계산한 값이다.
- 서명 알고리즘 — 이 인증서의 서명을 만들 때 쓴 방식이다. 그 서명은 CA의 개인키로 암호화되어 있으니, 푸는 데는 CA의 공개키를 쓴다.
명령줄에서도 같은 것을 볼 수 있다. 서버가 보내오는 인증서를 그대로 받아 필드를 풀어 보는 방법은 이렇다.
# 서버가 제시하는 인증서 체인을 그대로 받아 본다
openssl s_client -connect example.com:443 -servername example.com </dev/null
# 받은 인증서 파일의 필드를 사람이 읽을 수 있게 푼다
openssl x509 -in cert.pem -text -noout
두 번째 명령의 출력에는 Version, Serial Number, Signature Algorithm, Issuer, Validity, Subject, Subject Public Key Info, Signature Value 같은 항목이 나온다. 브라우저 인증서 창에서 본 것과 같은 내용을 이름만 영문으로 바꿔 보여 주는 셈이다.
클라이언트와 서버를 뒤집으면
마지막으로 방향을 뒤집어 본다.
지금까지의 그림은 서버가 인증서를 갖고 PC가 검증하는 구조였다. 서버가 진짜인지 PC가 확인하는 방향이다. 이 관계를 그대로 뒤집으면, 개인이 인증서를 갖고 기관이 검증하는 구조가 된다.
[ 서버 인증서 ] 서버 ──── 인증서 제시 ────▶ PC
└─ PC가 검증 : "이 사이트가 진짜인가"
[ 뒤집으면 ] 개인 ──── 인증서 제시 ────▶ 은행
└─ 은행이 검증 : "이 사람이 본인인가"
인터넷뱅킹의 공인인증서가 정확히 이것이다. 역할 배치는 이렇게 된다.
- 은행이 RA 역할을 한다. 발급 창구다.
- 금융결제원(yessign) 같은 기관이 CA 역할을 한다. 이용자와 은행이 함께 신뢰하는 제3자다.
- 개인은 이 체계에서 키 쌍을 발급받는다. 개인의 공개키에 "누가 언제 발급받았는지" 같은 정보가 붙어 인증서가 된다.
인터넷뱅킹을 할 때 개인은 이 인증서를 은행에 제시한다. 은행은 발급 기관을 확인하고 CA 쪽에 물어 검증한다. 만약 발급 자체를 그 은행이 직접 했다면 CA까지 갈 필요도 없다. 자기가 발급한 것이니 자체 검증으로 끝난다.
여기에 국가 기관이 개입해 제도로 구현된 것이 공인인증 체계였고, 지금은 민간 인증서도 함께 쓰인다. 이름과 제도는 달라져도 본질은 키 쌍이다. 그 위에 인증서와 검증 절차가 얹혀 있을 뿐, SSL에서 본 것과 완전히 같은 체계다.
문제가 됐던 것은 기술 자체가 아니라 운영 방식이었다. 이 체계를 굴리자고 개인 PC마다 별도 프로그램을 설치하게 만든 부분이 부담으로 남았다.
정리
- 서로 얼굴을 못 보는 두 주체가 상대의 키를 신뢰할 방법은 회선 안에 없다. 그래서 양쪽이 모두 신뢰하는 제3의 인증 기관을 세우고 신뢰를 위임한다.
- 인증 기관 체계는 CA(인증서 발급·서명)와 RA(발급 창구)로 이루어지고, 둘 사이에 인증서 목록 데이터베이스가 놓인다.
- 서버는 키 쌍을 직접 만들지 않고 RA에 요청해 발급받는다. 그리고 공개키가 혼자 오지 않는다 — 발급 대상·유효기간·알고리즘·해시·서명이 함께 붙은 인증서 형태로 온다.
- 서명은 인증서의 해시를 CA의 개인키로 암호화한 값이다. 키 쌍은 개인키로 잠그고 공개키로 여는 반대 방향 용법도 가능하며, 이 방향을 쓰면 "CA만 만들 수 있는 값"이 된다.
- 검증은 두 해시를 맞춰 보는 일이다 — 인증서 정보로 직접 계산한 해시와, 서명을 CA 공개키로 풀어 나온 해시가 같아야 한다. CA의 공개키는 운영체제에 미리 설치된 루트 인증서에 들어 있다.
- 조작이나 바꿔치기는 CA의 개인키가 없으면 서명을 다시 만들 수 없어 검증에서 걸린다. 9강의 중간자 공격이 여기서 막힌다.
- HTTP에 이 PKI 기술을 적용해 트래픽을 암호화한 것이 HTTPS이고, 그 계층 기술이 SSL(이후 TLS)이다. 브라우저 자물쇠 아이콘에서 인증서의 공개키·지문·서명 알고리즘을 직접 확인할 수 있다.
- 클라이언트와 서버를 뒤집어 개인이 인증서를 제시하고 기관이 검증하게 하면 인터넷뱅킹의 공인인증서 체계가 된다. 은행이 RA, 금융결제원 같은 기관이 CA다. 본질은 어디까지나 키 쌍이다.
- 시리즈를 관통하는 흐름은 넷이다 — 비대칭 키로 키 전달 문제를 풀고(7강), 무거운 비대칭 키 대신 세션 키를 교환해 실제 통신을 대칭 키로 하고(8강), 그 과정에서 드러난 중간자 공격을 확인하고(9강), 인증서로 공개키의 진위를 검증해 그 구멍을 메운다(10강).
여기까지가 SSL 통신의 골격이다.
댓글
아직 댓글이 없습니다. 첫 댓글을 남겨보세요.