인증서 폐기는 화이트보드 앞에서 설명하면 늘 해결된 문제처럼 들리고, 브라우저에서 실제로 무슨 일이 일어나는지 설명하면 늘 고장 난 문제처럼 들리는 PKI의 한 부분이다.

이론은 단순하다. 인증서가 침해되거나 잘못 발급되면 폐기한다. 그러면 세상이 그 인증서를 더는 믿지 않아야 한다.

현실은 어설픈 조치, 낡은 데이터, 소프트페일 로직, 그리고 백업 계획의 백업 계획이 줄줄이 이어지는 행렬이다.

OCSP와 CRL, 한 문단으로

CRL은 목록이다. CA가 자기가 폐기한 인증서의 일련번호를 전부 게시하고, 클라이언트는 목록 전체를 내려받아 자기가 거기 있는지 찾는다. OCSP는 질문이다. 클라이언트가 인증서 하나에 대해 CA에 묻고, 서명된 “정상”, “폐기”, “알 수 없음” 중 하나를 받는다. 성능으로 보면 차이는 비용을 어디서 치르느냐다. CRL은 처음에 대역폭을 쓰지만, 그다음엔 낡은 사본을 믿어 줄 수 있는 동안 오프라인으로 확인할 수 있다. OCSP는 답이 캐시에 없는 연결마다 네트워크 왕복 한 번과 프라이버시 유출을 치르고, 응답기가 느리거나 닿지 않으면 실패한다. 스테이플링은 그 OCSP 왕복을 브라우저에서 서버로 옮긴다. 셋 중 어느 것도 설계된 방식 그대로는 브라우저에서 잘 돌아가지 않았다. 결국 제대로 돌아가게 된 건 첫 번째 것을 재료로 만든 네 번째 방식이다.

CRL: 아무도 내려받지 않는 큰 목록

Certificate Revocation List가 원래의 답이었다. CA가 폐기한 인증서 일련번호 목록을 게시한다. 클라이언트는 목록을 내려받아 지금 보고 있는 인증서가 거기 있는지 확인한다.

규모가 커지면 문제가 뻔히 보인다. CRL은 계속 커진다. 큰 CA의 목록은 수십만 항목에 이르기도 한다. 인증서 하나를 검증하려고 메가바이트 단위의 폐기 데이터를 먼저 받아야 한다면 아무도 그 지연을 참지 않는다. 캐시를 쓰면 낫지만, 그러면 낡은 데이터로 확인하게 된다. 한 시간 전에 폐기된 인증서는 캐시한 사본이 바뀔 때까지 보이지 않는다.

브라우저는 오래전에 CRL을 실시간으로 받는 일을 포기했다. 2012년 Chrome은 온라인 폐기 확인을 기본으로 끄고, 그 대신 CRLSet을 도입했다. 구글이 CA의 폐기 데이터로 만든 작은 목록을 Chrome 업데이트 경로로 내려보내는 방식이다. Firefox는 OCSP를 계속 썼다. 목록 자체는 사라지지 않았고, 나중에 이게 중요해진다.

OCSP: 실시간이라지만 실시간이 아닌 확인

Online Certificate Status Protocol이 개선안이었다. 목록 전체를 받는 대신 CA에 실시간으로 묻는다. “이 인증서, 폐기됐나요?”

CA는 OCSP 응답기를 운영한다. 일련번호를 주면 서명된 상태를 돌려주는 HTTP 엔드포인트다.

이론으로는 낫다. 현실에서는 끔찍하다.

지연. 상태가 캐시에 없는 사이트에 접속하면, 브라우저는 인증서를 믿기 전에 CA 응답기로 HTTP 요청을 한 번 더 보내야 한다. TLS 핸드셰이크 위에 남의 서버까지 왕복이 한 번 더 붙는다.

프라이버시. OCSP 요청은 내가 어느 사이트에 언제 가는지 CA에 그대로 알려 준다. 보통 평문 HTTP로 가기 때문에 경로상의 누구나 함께 알게 된다. 보안을 높이자고 만든 장치치고는 좋지 않다.

가용성. 응답기가 단일 장애점이 된다. 응답기가 죽으면 어떻게 하나? 맞는 답은 “인증서를 거부한다”, 즉 닫힌 실패다. 브라우저의 실제 답은 “그냥 인증서를 받아들인다”, 즉 열린 실패였다. 닫힌 실패를 택하면 응답기가 잠깐 삐끗할 때마다 그 CA를 쓰는 모든 사이트가 내려가기 때문이다.

이 소프트페일이 목적 자체를 무너뜨린다. 공격자가 인증서를 탈취하고 OCSP 요청까지 막으면(네트워크 수준 공격자에겐 쉬운 일이다) 브라우저는 어깨를 한번 으쓱하고 탈취된 인증서를 받아들인다. 폐기 확인은 서류상으로만 존재했다.

OCSP Stapling: 낫지만 선택 사항

스테이플링은 OCSP의 문제 두 가지를 고친다. 브라우저가 CA에 묻는 대신, 서버가 자기 OCSP 응답을 주기적으로 받아 TLS 핸드셰이크에 “스테이플”한다. 브라우저는 별도 왕복 없이 최신 상태 증명을 받고, CA는 클라이언트의 요청을 아예 보지 못한다.

지연도 없고 프라이버시 유출도 없다. 깔끔하다.

함정은 스테이플링이 선택 사항이라는 점이다. 서버가 응답을 붙이지 않으면 브라우저는 직접 OCSP(문제를 고스란히 안은 채)로 돌아가거나 아예 확인하지 않는다. 스테이플링을 안 하는 서버가 많다. 기본값으로 켜지 않는 웹 서버도 있고, 그런 기능이 있는 줄 모르는 관리자도 있고, 구현에 버그가 있어 가끔씩 실패하는 경우도 있다.

결과적으로 스테이플링은 동작할 땐 완벽하고, 동작하지 않을 땐 아무도 모른다. 굳이 설정하는 곳은 대개 가장 덜 필요한 곳, 즉 관리가 잘되는 사이트다. 인증서가 잊힌 채 방치된 사이트에는 없다.

OCSP Must-Staple: 아무도 쓰지 않은 해결책

RFC 7633의 TLS Feature 확장, 흔히 Must-Staple이라 부르는 인증서 확장이 있다. 이 확장이 든 인증서는 브라우저에 이렇게 말한다. “스테이플된 OCSP 응답 없이 오면 나를 거부하라.”

폴백 구멍이 막힌다. 스테이플이 없으면 하드 페일이다. 단, 이를 강제한 Firefox에서만 그렇다. Chrome은 한 번도 강제하지 않았다.

채택은 끝내 미미했다. 스테이플링이 실패하면(응답기가 느리거나, 캐시한 응답이 만료됐거나, 갱신 스크립트가 깨지면) 사이트가 내려가기 때문에 운영자들은 Must-Staple을 두려워했다. 느려지는 게 아니라 내려간다. 선택이던 확인을 CA 인프라에 대한 강한 의존으로 바꾼 셈이다. 2025년 Let’s Encrypt가 Must-Staple 인증서 발급을 아예 중단하면서, 웹 대부분에서는 논쟁 자체가 끝났다.

CRLite: Mozilla의 영리한 접근

Mozilla는 CRLite를 만들었다. 웹 PKI의 모든 폐기 인증서를 압축해 Firefox에 미리 내려보내는 방식이다. 2025년 4월 데스크톱 Firefox 137부터 기본으로 켜졌다. Mozilla에 따르면 전체 패키지가 약 6.7MB이고, 몇 시간마다 받는 증분 업데이트는 그에 비해 아주 작다. Firefox 142부터 데스크톱 Firefox는 도메인 검증(DV) 인증서에 대해 OCSP 질의를 아예 보내지 않는다.

브라우저가 CA에 연락할 필요가 없다. 폐기 데이터가 이미 로컬에 있다. 지연도, 프라이버시 유출도, 가용성 의존도 없고, 공격자가 파고들 소프트페일 구멍도 없다.

CRLite는 정말 좋은 아이디어다. 그리고 Firefox 전용이다. Chrome은 여전히 전체가 아닌 선별된 일부인 CRLSet에 기대고, Safari도 CRLite를 쓰지 않는다. 폐기 문제는 브라우저마다 다르게 “해결”돼 있다. 바꿔 말하면 한 브라우저에서만 해결됐다.

2026년 현재: OCSP가 졌다

여기서 반전이 있다. 2023년 CA/브라우저 포럼은 Ballot SC-063을 통과시켜 공개 CA의 OCSP를 선택 사항으로, CRL을 의무로 바꿨다. 웹 인증서의 큰 몫을 발급하는 Let’s Encrypt는 그 뒤 OCSP 서비스를 단계적으로 닫았다. 2025년 1월 30일부터 Must-Staple 발급 요청이 실패하기 시작했고, 5월 7일부터 새 인증서에 OCSP URL이 빠졌으며, 8월 6일 응답기가 꺼졌다. 이유로는 프라이버시와 수십억 건의 OCSP 질의에 답하는 비용을 들었다.

결국 아무도 내려받지 않던 큰 목록이 이겼다. 브라우저가 CRL을 하나씩 받아 오는 건 여전히 아니다. Mozilla와 구글이 CRL을 모아 압축하고, 그 결과를 브라우저에 내려보낸다. CRL은 원재료가 됐다.

운영자에게는 실무적인 결과가 하나 있다. Let’s Encrypt 인증서라면 스테이플할 것이 없다. nginx는 인증서에 OCSP 응답기 URL이 없어서 ssl_stapling을 무시했다는 로그를 남긴다. 설정 실수가 아니라 정상이다. OCSP 응답기를 계속 운영하는 CA라면 스테이플링은 여전히 제 역할을 하지만, 웹이 가는 방향은 더 이상 그쪽이 아니다.

짧은 수명 인증서: 암묵적 폐기

이게 또 하나의 진짜 답이다. 인증서 수명이 며칠이면 폐기는 거의 상관없어진다. 탈취된 인증서는 어떤 폐기 메커니즘이 클라이언트 대부분에 닿기도 전에 만료된다.

Let’s Encrypt는 2015년 90일 인증서로 시작해 그것을 표준으로 만들었다. 2026년 1월부터는 6일짜리 인증서를 선택적으로 제공한다. 기본 수명은 2027년 2월 64일, 2028년 2월 45일로 줄어들 예정이다. CA/브라우저 포럼의 Ballot SC-081은 업계 전체를 같은 방향으로 몬다. 최대 유효기간은 2026년 3월 15일 398일에서 200일로 줄었고, 2027년 3월 100일, 2029년 3월 47일로 줄어든다.

수명이 며칠이면 인증서 자체가 폐기 수단이다. 그냥 유효하지 않게 된다. 대가는 자동화에 대한 전적인 의존이다. 갱신 파이프라인이 깨지면 며칠 안에 사이트가 내려간다.

풀리지 않은 문제

수십 년을 시도했지만 폐기는 아직도 어디서나 같은 방식으로 동작하지 않는다. CRL을 실시간으로 받기엔 너무 느렸다. OCSP는 느리고, 새고, 소프트페일했다. 스테이플링은 선택이었다. Must-Staple은 너무 무서웠고, 이제 사라졌다. CRLite는 동작하지만 한 브라우저에서만이다.

솔직한 현재 상태는 이렇다. 오늘 인증서가 탈취되면 Firefox는 몇 시간 안에 폐기 사실을 안다. Chrome은 그 폐기가 CRLSet에 들어가면 안다. 그 밖의 곳에서는 만료될 때까지 그냥 신뢰될 수 있다.

그래서 인증서 수명 단축이 어떤 폐기 프로토콜 개선보다 중요하다. 인증서가 나쁘다고 세상에 확실히 알릴 수 없다면, 적어도 빨리 유효하지 않게 만들어야 한다.