인증서
고친 사람 github-actions[bot]
인증서는 어떤 공개키가 누구의 것인지를 처음 보는 상대에게 믿게 해 줍니다. 공개키와 그 키 주인의 이름을 한 묶음으로 적고, 양쪽이 모두 믿기로 한 제삼자가 그 묶음에 디지털 서명을 붙여 내줍니다. 받는 쪽은 그 서명만 확인하면 상대를 직접 알아보지 않고도 공개키의 주인을 판단합니다.
쉽고 빠른 이해
인증서는 「이 공개키는 이 서버의 것이다」라는 문장에 남의 도장을 찍어 둔 파일입니다. 브라우저가 주소창에 자물쇠를 띄울 때 받아서 확인하는 것이 이 파일입니다.
이게 없으면 받은 공개키가 진짜 상대의 것인지 확인할 길이 없습니다. 중간에서 가로챈 쪽이 자기 공개키를 대신 내밀어도 겉보기에는 똑같습니다.
- 서버가 자기 공개키와 이름을 적어 인증 기관에 신청합니다
- 인증 기관이 확인한 뒤 그 묶음에 서명해 돌려줍니다
- 접속한 쪽이 서명과 이름과 기간을 확인하고 연결을 이어 갑니다
대가는 남을 믿어야 한다는 것입니다. 인증 기관이 엉뚱한 사람에게 발급하면 그 잘못이 그대로 통합니다. 기간이 끝나기 전에 갈아 끼우는 손도 계속 듭니다.
상세
처음 보는 사람과 거래할 때 양쪽을 다 아는 사람이 「이쪽이 그 김 과장입니다」 하고 소개해 주면 우리는 김 과장이 아니라 소개한 사람을 믿고 자리에 앉습니다. 소개한 사람이 믿을 만한지는 또 그를 아는 누군가에게 물어야 압니다. 소개가 붙여 주는 것은 이름까지여서, 그와 거래해서 손해를 볼지는 소개받은 쪽이 따로 따져야 합니다.
이름이 같은 다른 물건도 있습니다. 사람이 시험을 보고 받는 자격증도 인증서라고 부르지만, 이 편이 다루는 것은 기계가 확인하는 파일 쪽입니다.
인증서를 실제로 주고받는 쪽은 대개 TLS(Transport Layer Security, 전송 계층 보안)입니다. 웹 주소가 https 로 시작할 때 브라우저가 서버에서 받아 확인하는 것이 이 인증서입니다.
인증서가 묶는 두 짝
인증서가 하는 일은 묶음 하나를 만드는 것입니다. 한쪽에는 공개키가 있고, 다른 쪽에는 그 키 주인의 이름이 있습니다.
공개키는 누구에게나 보여 주는 키입니다. 짝이 되는 개인키는 주인만 갖고 있어서, 공개키로 잠근 것은 개인키를 가진 쪽만 풉니다.
문제는 공개키만 봐서는 주인을 알 수 없다는 것입니다. 공개키는 숫자 덩이라서 누가 만들어 내밀어도 생김새가 같습니다. 이름과 묶어 두고 그 묶음을 남이 보증해야 비로소 주인이 정해집니다.
보증한다는 것은 서명을 붙인다는 뜻입니다. 디지털 서명은 어떤 내용을 자기 개인키로 계산해 붙인 값입니다. 그 사람의 공개키로 다시 계산해 보면 내용이 도중에 바뀌지 않았는지와 누가 붙인 값인지가 함께 드러납니다.
인증서에 적히는 칸
인증서는 이름과 키만 담고 끝나지 않습니다. 언제까지 쓸 수 있는지, 무엇에 쓰라고 낸 것인지도 함께 적습니다. 받은 쪽이 확인할 거리를 문서 안에 미리 다 넣어 두는 것입니다.
| 칸 | 담는 것 | 없으면 |
|---|---|---|
| 주체 | 이 인증서가 가리키는 대상의 이름 | 누구의 키인지 모릅니다 |
| 공개키 | 주체가 쓰는 공개키 값 | 묶어 줄 대상이 없습니다 |
| 발급자 | 이 인증서에 서명한 인증 기관의 이름 | 누구의 서명인지 못 찾습니다 |
| 유효 기간 | 언제부터 언제까지 쓰나 | 한 번 낸 인증서가 영영 삽니다 |
| 용도 | 서버 확인용인지 서명 검증용인지 | 낸 목적과 다른 곳에 쓰입니다 |
| 서명 | 발급자가 위 칸 전부에 붙인 서명 | 아무나 칸을 고쳐도 모릅니다 |
마지막 칸이 나머지 전부를 묶습니다. 서명은 위의 칸들을 한 덩이로 보고 계산한 값이라, 이름이든 기간이든 한 글자만 바뀌어도 서명이 안 맞습니다.
이 칸들을 어떤 이름으로 어떤 순서로 적을지는 X.509 라는 표준이 정합니다. 인증서 파일을 열어 보면 그 표준이 정한 칸 이름이 그대로 보입니다.
받은 인증서를 확인하는 순서
인증서를 받은 쪽은 네 가지를 차례로 확인합니다. 하나라도 어긋나면 연결을 끊습니다.
flowchart TD
A["인증서를 받는다"] --> B{"주체 이름이 접속한 주소와 같나"}
B -->|다르다| X["거절한다"]
B -->|같다| C{"오늘이 유효 기간 안인가"}
C -->|아니다| X
C -->|맞다| D{"발급자의 서명이 맞나"}
D -->|아니다| X
D -->|맞다| E{"그 발급자를 믿나"}
E -->|아니다| X
E -->|믿는다| F["연결을 이어 간다"]
앞의 셋은 인증서 한 장만 보고 끝납니다. 이름은 접속한 주소와 맞대 보고, 기간은 오늘 날짜와 견주고, 서명은 발급자의 공개키로 계산해 봅니다.
넷째가 어려운 물음입니다. 발급자를 믿느냐는 그 발급자의 인증서를 또 확인해야 답이 나옵니다.
여기서 확인하는 쪽은 대개 접속을 건 클라이언트입니다. 서버가 거꾸로 클라이언트에게 클라이언트 인증서를 요구하는 구성도 있고, 그때는 같은 확인을 양쪽이 한 번씩 합니다.
뿌리까지 이어지는 사슬
그래서 인증서는 한 장으로 끝나지 않습니다. 발급자의 인증서를 또 다른 발급자가 서명하고, 그 사슬이 어디선가 끝나야 합니다.
사슬의 끝에 있는 것이 루트 인증서입니다. 루트 인증서는 자기가 자기에게 서명한 인증서라 위에 물어볼 곳이 없습니다. 대신 운영체제와 브라우저가 믿을 루트 목록을 미리 갖고 들어옵니다. 이 목록을 신뢰 저장소라고 부릅니다.
flowchart TD
R["루트 인증서 · 신뢰 저장소에 미리 들어 있다"] -->|서명| I["중간 인증서"]
I -->|서명| E["서버 인증서"]
확인하는 쪽은 받은 인증서에서 위로 거슬러 올라가다 신뢰 저장소에 든 인증서를 만나면 멈춥니다. 거기까지 못 가면 그 인증서는 믿을 수 없는 것으로 봅니다.
가운데에 중간 인증서를 한 칸 두는 까닭은 루트의 개인키를 되도록 안 꺼내려는 것입니다. 루트의 키가 새면 그 루트를 믿던 모든 인증서가 한꺼번에 흔들립니다.
기간이 끝나기 전에 못 쓰게 만들기
유효 기간은 인증서가 스스로 죽는 때를 적어 둔 칸입니다. 그 날이 지나면 확인하는 쪽이 알아서 거절하므로 따로 알릴 것이 없습니다.
문제는 그 전에 개인키가 새는 때입니다. 키를 훔친 쪽은 기간이 남은 인증서를 그대로 들고 주인 행세를 합니다. 인증서 자체는 서명이 멀쩡하니 확인 절차도 통과합니다.
그래서 인증서 폐기라는 별도의 장치가 있습니다. 발급자가 「이 인증서는 이제 무효」라고 알리고, 확인하는 쪽이 그 알림을 조회해 봅니다.
다만 이 조회는 늘 되는 것이 아닙니다. 조회할 곳에 닿지 못하면 확인하는 쪽은 폐기 여부를 모른 채 넘어가기 쉽습니다. 그래서 유효 기간을 짧게 잡고 자주 갈아 끼워 폐기에 덜 기대는 방식도 같이 씁니다.
스스로 서명한 인증서
자기 서명 인증서는 발급자 칸에 자기 이름을 적고 자기 개인키로 서명한 인증서입니다. 만드는 데 남이 필요 없어서 명령 한 줄로 바로 나옵니다.
대신 받는 쪽에는 믿을 근거가 없습니다. 사슬을 거슬러 올라가도 신뢰 저장소에 든 인증서를 못 만나기 때문입니다. 브라우저가 경고 화면을 띄우는 것이 이 경우입니다.
그래도 쓰는 곳이 있습니다. 사내 서비스나 개발 장비처럼 접속하는 쪽이 정해져 있으면, 그 인증서를 각 장비의 신뢰 목록에 직접 넣어 두고 씁니다.
인증서가 증명하지 않는 것
인증서는 「이 공개키가 이 이름의 것이다」까지만 말합니다. 그 이름을 가진 쪽이 정직한지, 그 서비스에 취약점이 없는지는 아무것도 말하지 않습니다.
이름을 얼마나 확인하고 내주는지도 발급 방식마다 갈립니다. 그 도메인을 다룰 권한이 있는지만 보고 내주는 것이 있고, 그 이름의 회사가 실제로 있는지까지 확인하고 내주는 것이 있습니다.
그래서 자물쇠 표시가 떴다는 것은 「주고받는 내용이 가려졌고 상대 이름이 확인됐다」는 뜻입니다. 그 상대가 믿을 만한 상대라는 뜻은 아닙니다.
관련 항목
인증서 한 장을 이루는 구성 요소
공개키 · 개인키 · 디지털 서명 · 주체 이름 · 유효 기간 · 일련번호 · 키 용도 · 주체 대체 이름
인증서를 발급하고 신뢰를 세우는 주체
인증 기관 · 루트 인증 기관 · 중간 인증 기관 · 등록 기관 · 신뢰 저장소 · 공개키 기반구조
인증서의 형식과 파일 표현을 정하는 표준
X.509 · ASN.1 · DER · PEM · 인증서 서명 요청 · Base64
인증서의 하위 종류
루트 인증서 · 중간 인증서 · 서버 인증서 · 클라이언트 인증서 · 자기 서명 인증서 · 와일드카드 인증서 · 코드 서명 인증서
인증서를 못 쓰게 되는 상태와 그 확인 수단
인증서 만료 · 인증서 폐기 · 인증서 폐기 목록 · OCSP · 인증서 투명성 · 인증서 고정
인증서를 주고받는 프로토콜
TLS · HTTPS · 상호 TLS · TLS 핸드셰이크 · 서버 이름 표시 · ACME
인증서가 기대는 암호 기술
공개키 암호 · 해시 함수 · 디지털 서명 알고리즘 · RSA · 타원 곡선 암호 · 키 쌍
인증서를 운영에서 다루는 작업
인증서 발급 · 인증서 갱신 · 키 회전 · 시크릿 관리 · 하드웨어 보안 모듈
인증서가 맡는 일을 대신하는 다른 수단
사전 공유 키 · API 키 · JWT · 신뢰 웹 · 공개키 지문
인증서를 잘못 다뤘을 때 나는 오류
호스트 이름 불일치 · 만료된 인증서 · 신뢰할 수 없는 발급자 · 인증서 사슬 누락 · 중간자 공격
다른 이름: certificate · digital certificate · 디지털 인증서 · 공개키 인증서 · public key certificate