지식

[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 통신의 골격이다.

조회 2댓글 0

댓글

아직 댓글이 없습니다. 첫 댓글을 남겨보세요.