인증서 발급
고친 사람 github-actions[bot]
인증서 발급은 믿을 만한 기관이 신청자의 공개키에 보증 서명을 붙여 인증서로 내주는 일입니다. 서버가 처음 보는 접속자에게 자기가 누구인지 보이려면 이 인증서가 먼저 있어야 합니다. 기관은 서명하기 전에 신청자가 그 이름의 주인이 맞는지 확인합니다. 요즘은 사람이 손으로 신청하기보다 프로그램이 때마다 알아서 받아 오는 일이 많습니다.
쉽고 빠른 이해
인증서 발급은 「이 공개키는 이 서버의 것」이라는 보증서를 받아 내는 일입니다.
shop.example.com 을 운영하는 쪽이 그 이름이 적힌 인증서를 인증 기관에서 받는 것이 발급입니다.
이 보증서가 없으면 접속하는 브라우저는 서버가 내민 공개키를 믿을 근거가 없습니다. 중간에 끼어든 쪽이 자기 키를 내밀어도 가려내지 못합니다.
- 서버 쪽이 키 한 쌍을 만들고 공개키만 담아 신청서를 보냅니다
- 인증 기관이 그 도메인을 정말 다루는 쪽인지 시험해 봅니다
- 통과하면 기관이 서명한 인증서를 돌려줍니다
대가는 기관을 믿어야 한다는 것과 기한이 끝날 때마다 다시 받아야 한다는 것입니다. 사내 장비끼리만 쓰거나 혼자 시험할 때는 회사가 직접 서명하거나 스스로 서명해서 씁니다.
상세
여권을 만들 때는 사진과 서류를 들고 관청에 갑니다. 관청은 그 사람이 본인인지 확인한 뒤 도장을 찍은 여권을 내줍니다. 그 뒤로는 처음 가 보는 나라의 공항도 그 여권만 보고 사람을 들여보냅니다.
인증서 발급은 이 일을 공개키에 대해 하는 것입니다. 신청자가 자기 공개키와 이름을 내밀면 인증 기관(Certification Authority, CA)이 확인하고 서명합니다. 그렇게 나온 결과물이 인증서입니다. 신청에서 시작해 서버에 인증서를 올려 두는 데서 끝나는 한 벌의 절차입니다.
왜 남이 서명해야 할까요. 공개키는 숫자 덩어리라서 값 어디에도 주인 이름이 적혀 있지 않습니다. 누가 만들어 내밀어도 생김새가 같습니다. 양쪽이 다 믿는 제삼자가 「이 키는 이 이름의 것」이라고 보증해 줘야 처음 보는 상대도 그 키를 믿습니다.
아래 그림은 발급 한 번의 흐름입니다. 단계마다 뒤의 소절에서 하나씩 봅니다.
sequenceDiagram
participant 신청자 as 신청자 서버
participant 기관 as 인증 기관
Note over 신청자: 키 한 쌍을 만든다
신청자->>기관: 서명 요청을 보낸다
기관-->>신청자: 확인 과제를 낸다
신청자->>기관: 과제를 풀었다고 알린다
Note over 기관: 과제 결과를 직접 확인한다
기관-->>신청자: 서명한 인증서를 내준다
Note over 신청자: 인증서를 설치한다
키 한 쌍 만들기
발급은 신청자가 키를 만드는 데서 시작합니다. 공개키 암호는 키를 한 쌍으로 만듭니다. 공개키는 누구에게나 보여 줍니다. 짝인 개인키는 주인만 갖습니다.
이 한 쌍으로 서명을 합니다. 여기서 서명은 전자 서명을 말합니다. 개인키로 내용에서 값을 계산해 붙이면, 누구든 짝인 공개키로 그 값을 맞춰 볼 수 있습니다. 내용이 한 글자라도 바뀌면 맞춰 보기가 실패합니다.
키는 인증 기관이 아니라 신청자가 만듭니다. 개인키가 신청자의 서버를 한 번도 떠나지 않게 하려는 것입니다. 기관도 개인키를 모르니 기관이 뚫려도 서버의 개인키는 새지 않습니다.
인증서 서명 요청
신청서는 인증서 서명 요청(Certificate Signing Request, CSR)이라는 정해진 형식으로 보냅니다.
이 요청에는 공개키와 인증서에 올릴 이름이 들어갑니다. 웹 서버라면 그 이름은
shop.example.com 같은 도메인 이름입니다.
신청자는 이 요청에 자기 개인키로 서명해서 보냅니다. 기관은 요청 안의 공개키로 그 서명을 맞춰 봅니다. 맞으면 신청자가 그 공개키의 짝인 개인키를 갖고 있다는 뜻입니다. 남의 공개키를 주워다 자기 이름으로 인증서를 받는 일을 이렇게 막습니다.
이름의 주인인지 확인하기
기관이 서명하기 전에 하는 일이 확인입니다. 요청서의 이름 칸에는 아무 이름이나 적을 수 있습니다. 그래서 기관은 신청자가 그 이름을 정말 다루는 쪽인지 따로 시험합니다.
웹 서버 인증서라면 기관이 확인 과제를 냅니다. 그 도메인을 마음대로 고칠 수 있는 쪽만 해낼 수 있는 일을 시키는 것입니다. 흔한 과제는 둘입니다. 웹 서버에 파일을 올리는 과제와 DNS 레코드를 추가하는 과제입니다.
두 번째 과제가 쓰는 DNS(Domain Name System)는 도메인 이름을 물으면 거기 등록해 둔 정보를 돌려주는 체계입니다. 그 정보 한 줄을 레코드라고 부릅니다. 아래 표는 두 과제를 나란히 놓고 견줍니다.
| 과제 | 신청자가 하는 일 | 기관이 확인하는 것 |
|---|---|---|
| 파일 올리기 | 기관이 준 값을 파일에 담아 그 도메인의 웹 서버 정해진 경로에 둔다 | 그 주소로 접속해 파일이 나오는지 |
| DNS 레코드 추가 | 기관이 준 값을 그 도메인의 DNS 레코드로 등록한다 | 그 도메인을 조회해 값이 나오는지 |
어느 쪽이든 과제를 풀면 기관은 신청자를 그 도메인의 주인으로 봅니다.
확인을 얼마나 깊게 하는지도 인증서마다 갈립니다. 깊이에 따라 세 등급으로 나눠 부릅니다.
| 등급 | 기관이 확인하는 것 |
|---|---|
| 도메인 검증 | 그 도메인을 다룰 권한이 있는지만 본다 |
| 조직 검증 | 인증서에 적을 조직이 실제로 있는지까지 본다 |
| 확장 검증 | 조직의 법적 실체와 신청한 사람의 권한까지 더 엄격하게 본다 |
도메인 검증은 위의 과제만으로 끝납니다. 프로그램이 사람 손 없이 풀 수 있는 것도 이 등급뿐입니다. 그래서 프로그램이 알아서 받아 오는 자동 발급(뒤에서 봅니다)은 도메인 검증으로 나옵니다.
서명해서 내주기
확인을 마친 기관은 인증서의 칸을 채웁니다. 요청에서 받은 공개키와 이름에 더해 발급자인 자기 이름과 유효 기간을 적습니다. 유효 기간은 이 인증서를 믿어도 되는 시작일과 마감일입니다.
일련번호도 적습니다. 일련번호는 기관이 내준 인증서마다 붙이는 고유 번호입니다. 나중에 특정 인증서를 무효로 돌릴 때 이 번호로 가리킵니다. 이 일은 뒤에서 폐기라는 이름으로 다시 나옵니다.
마지막으로 기관은 이 칸 전부에 자기 개인키로 서명합니다. 서명이 붙은 뒤에는 누가 칸을 몰래 고쳐도 맞춰 보기에서 드러납니다. 그러니 인증서는 비밀이 아닙니다. 아무 통신망으로 건네도 됩니다.
아래 그림은 요청서의 칸이 인증서로 어떻게 넘어가는지 보입니다.
flowchart TD
subgraph CSR["인증서 서명 요청"]
RK["공개키"]
RN["이름"]
RS["신청자의 서명"]
end
subgraph CERT["인증서"]
CK["공개키"]
CN["이름"]
CI["발급자"]
CV["유효 기간"]
CSN["일련번호"]
CS["기관의 서명"]
end
RK -->|그대로 옮긴다| CK
RN -->|그대로 옮긴다| CN
요청에서 넘어오는 것은 공개키와 이름뿐입니다. 발급자 · 유효 기간 · 일련번호는 기관이 새로 채웁니다. 기관의 서명은 그 위 칸 전부를 덮습니다.
기관도 신청자처럼 자기 키 한 쌍과 인증서를 갖고 있습니다. 인증서에 서명할 때 쓰는 개인키가 그 키 쌍의 것입니다. 받는 쪽이 서명을 맞춰 보려면 기관의 공개키가 필요합니다. 그 공개키는 기관의 인증서에 들어 있습니다.
그래서 기관은 내준 인증서와 함께 자기 인증서도 건넵니다. 이것이 중간 인증서입니다. 둘을 가르려고, 신청자가 받은 인증서는 서버 인증서라고 부릅니다. 웹 서버의 이름이 적힌 인증서라서 붙은 이름입니다.
중간 인증서에도 서명이 붙어 있습니다. 서명한 쪽은 한 단 위의 기관입니다. 그렇게 거슬러 올라간 맨 윗단의 기관이 루트 인증 기관입니다. 그 위에는 서명해 줄 기관이 없어서 루트 인증서는 스스로 서명합니다.
서버 인증서에서 루트 인증서까지 서명으로 이어진 이 줄이 인증서 사슬입니다. 사슬 끝의 루트 인증서는 받는 쪽이 미리 믿고 있어야 합니다. 브라우저와 운영체제는 믿을 루트 인증서를 목록으로 미리 갖고 있습니다. 이 목록이 신뢰 저장소입니다.
flowchart TD
subgraph STORE["브라우저 신뢰 저장소"]
R["루트 인증서"]
end
subgraph SERVER["서버가 내미는 것"]
M["중간 인증서"]
S["서버 인증서 · shop.example.com"]
end
R -->|서명| M
M -->|서명| S
화살표는 위의 인증서가 아래 인증서에 서명했다는 뜻입니다. 받는 쪽은 맨 아래 서버 인증서에서 출발해 화살표를 거슬러 신뢰 저장소의 루트까지 올라갑니다. 가운데 한 장이 빠지면 사슬이 거기서 끊깁니다.
받은 인증서 설치하기
신청자는 서버 인증서와 중간 인증서를 처음 만든 개인키와 함께 서버에 올립니다. 위 그림에서 「서버가 내미는 것」으로 묶은 두 장입니다. 루트 인증서는 받는 쪽이 이미 갖고 있습니다.
서버가 인증서를 내미는 일은 TLS(Transport Layer Security) 안에서 일어납니다. TLS 는 통신 내용을 암호화하고 상대를 확인하는 프로토콜입니다. 접속이 들어오면 서버는 두 인증서를 내밉니다. 그리고 개인키로 자기가 그 주인임을 보입니다.
중간 인증서를 빠뜨리면 받는 쪽이 루트까지 못 올라갑니다. 그러면 서버 인증서가 멀쩡해도 접속을 거부합니다. 이 실수를 인증서 사슬 누락이라고 부릅니다.
기한이 끝나면 다시 받기
유효 기간이 지나면 받는 쪽은 서명이 멀쩡해도 인증서를 믿지 않습니다. 개인키를 오래 쓸수록 샐 위험이 쌓이기 때문입니다. 발급 뒤에 도메인 주인이 바뀌는 것처럼 사정이 달라져도 인증서는 그걸 모릅니다.
그래서 발급은 한 번으로 끝나지 않습니다. 기한이 끝나기 전에 같은 절차를 다시 밟아 새 인증서를 받습니다. 이것을 인증서 갱신이라고 부릅니다.
갱신을 잊으면 어느 날 갑자기 모든 접속이 경고 화면에 막힙니다. 이 장애가 인증서 만료입니다.
기한 전에 개인키가 샜다면 마감일을 기다리지 않습니다. 기관이 그 인증서를 무효라고 알립니다. 이것이 인증서 폐기입니다. 앞에서 본 일련번호로 어느 인증서인지 가리킵니다.
아래 그림은 발급된 인증서 하나가 갈 수 있는 세 갈래입니다.
stateDiagram-v2
state "발급됨" as Issued
state "사용 중" as InUse
state "만료" as Expired
state "폐기" as Revoked
Issued --> InUse: 서버에 설치한다
InUse --> InUse: 기한 전에 갱신해 새 인증서로 바꾼다
InUse --> Expired: 갱신을 잊고 마감일이 지났다
InUse --> Revoked: 기한 전에 개인키가 샜다
갱신하면 다시 사용 중으로 돌아옵니다. 만료나 폐기에 닿으면 그 인증서는 거기서 끝납니다.
잘못 나간 인증서
확인이 허술하면 엉뚱한 쪽에 인증서가 나갑니다. 이것을 인증서 오발급이라고 부릅니다. 받는 쪽은 서명이 멀쩡하니 가짜를 가려내지 못합니다.
그래서 기관이 내준 인증서를 누구나 볼 수 있는 공개 기록에 남기게 하는 장치가 있습니다. 인증서 투명성입니다. 도메인 주인은 이 기록을 살펴 자기가 신청하지 않은 인증서를 찾아냅니다.
사람 손을 덜어 주는 자동 발급
예전에는 담당자가 웹 화면에 요청서를 붙여 넣고 메일로 인증서를 받아 서버에 올렸습니다. 서버가 수십 대로 늘면 이 일을 손으로 감당하기 어렵습니다. 기한을 하나만 놓쳐도 장애가 납니다.
이 일을 프로그램끼리 처리하도록 정한 프로토콜이 ACME(Automatic Certificate Management Environment)입니다. 서버에서 도는 프로그램이 기관에 요청을 보내고 확인 과제를 스스로 풉니다. 받은 인증서도 설치합니다. 기한이 다가오면 같은 일을 알아서 되풀이합니다.
인증서를 자동으로 받을 수 있게 됐습니다. 그래서 유효 기간을 짧게 잡는 경우가 늘었습니다. 기간이 짧으면 키가 새도 피해가 짧게 끝납니다. 폐기 알림에 덜 기대도 됩니다.
사내 서비스끼리의 발급
인터넷에 공개하지 않는 서비스도 인증서를 씁니다. 사내 서비스끼리 서로 누구인지 확인하며 통신하려는 것입니다.
사내 통신에도 앞에서 본 TLS 를 씁니다. 보통은 서버만 인증서를 내밉니다. 양쪽이 다 인증서를 내밀어 서로를 확인하게도 할 수 있습니다. 이 방식이 상호 TLS입니다.
사내용 인증서는 공개 인증 기관에서 받지 않습니다. 회사가 직접 운영하는 사설 인증 기관이 발급합니다. 그 루트 인증서는 회사 장비의 신뢰 저장소에만 넣어 둡니다. 바깥 브라우저는 이 인증서를 믿지 않습니다. 사내 서비스끼리만 믿습니다.
사내 발급은 플랫폼 엔지니어링 팀이 미리 깔아 두는 경우가 많습니다. 플랫폼 엔지니어링 팀은 여러 서비스 팀이 함께 쓰는 배포 · 운영 바탕을 만들어 주는 팀입니다. 덕분에 서비스 팀은 인증서를 직접 신청하지 않아도 됩니다.
서비스는 뜰 때 자기 서비스 신원을 담은 인증서를 자동으로 받습니다. 서비스 신원은 「주문 서비스」처럼 그 서비스가 누구인지를 가리키는 이름입니다. 이렇게 자동으로 받으니 기한을 공개 인증서보다 훨씬 짧게 잡기도 합니다.
서명하는 쪽에 따른 세 방식
같은 인증서라도 누가 서명하느냐에 따라 믿어 주는 범위가 갈립니다. 아래 표는 그 셋을 견준 것입니다.
| 방식 | 누가 서명하나 | 누가 믿나 | 쓰는 곳 |
|---|---|---|---|
| 공개 인증 기관 발급 | 브라우저가 미리 믿는 기관 | 인터넷의 누구나 | 공개 웹사이트 · 외부에 여는 서버 |
| 사설 인증 기관 발급 | 회사가 운영하는 기관 | 그 루트를 넣어 둔 사내 장비 | 사내 서비스끼리의 통신 |
| 자기 서명 인증서 | 신청자 자신 | 그 인증서를 직접 넣어 둔 장비 | 개발 장비 · 혼자 하는 시험 |
자기 서명 인증서는 확인해 줄 남이 없어서 명령 한 줄로 바로 나옵니다. 대신 받는 쪽에는 믿을 근거가 없습니다. 브라우저는 경고 화면을 띄웁니다.
관련 항목
인증서 발급이 속하는 상위 분류
공개키 기반구조 · 인증서 관리 · 정보 보안 · 암호학
인증서 발급에 관여하는 역할
인증 기관 · 루트 인증 기관 · 중간 인증 기관 · 등록 기관 · 사설 인증 기관 · 신뢰 당사자
인증서 발급이 거치는 처리 단계
키 쌍 생성 · 인증서 서명 요청 · 도메인 소유 확인 · 전자 서명 · 인증서 설치
확인 깊이에 따른 발급 등급
도메인 검증 · 조직 검증 · 확장 검증
발급되어 나오는 인증서의 종류
인증서 · 서버 인증서 · 클라이언트 인증서 · 중간 인증서 · 루트 인증서 · 와일드카드 인증서 · 자기 서명 인증서
인증서 발급을 자동으로 처리하는 수단
ACME · 인증서 자동 갱신 · 시크릿 관리 · 서비스 신원 · 서비스 메시
발급 뒤에 이어지는 운영 작업
인증서 갱신 · 인증서 폐기 · 키 회전 · 유효 기간 · 인증서 투명성 · 하드웨어 보안 모듈
인증서 발급에서 나는 오류·장애
인증서 만료 · 인증서 사슬 누락 · 인증서 오발급 · 호스트 이름 불일치 · 중간자 공격
발급된 인증서를 쓰는 용도
인증서 형식을 정하는 표준
X.509 · PEM · DER · PKCS
다른 이름: certificate issuance · issuing certificates · 인증서 발행