Let’s Encrypt가 7월 8일부터 자체 서명한 인증서를 발급한다는 소식을 듣고, 바로 관련된 문제가 무엇인지 찾아보았다. 문제는 ISRG가 Root CA로 신뢰받기 시작한 것이 최근이라는 점인데, 예를 들어 Windows의 경우, 작년 8월 이후에 윈도우즈 업데이트를 하지 않았을 경우 테스트 사이트에 접속했을 때 “신뢰할 수 없는 사이트” 에러를 볼 수도 있다.

이제 이를 이해하고 대응하기 위해 필요한 개념들을 살펴보자.

  1. Chain of Trust
  2. Cross Sigining
  3. 그래서 방법은?

Chain of Trust

Let’s Encrypt에서 발급받은 인증서를 이용하는 사이트에 접속하면 다음과 같은 인증서 정보를 볼 수 있다.

인증서가 3단계로 계층 형태를 갖는데, 각각이 무엇인지 아래 그림과 함께 살펴보자.

우선 End-entity Certificate이 바로 아까 본 그림의 a.cyclic.dev 인증서에 해당한다. 이 인증서에는 Let's Encrypt Authority X3에 의해 발급되었고, RSA로 서명 받았음이 기재되어 있다. 기재된 정보를 따라가면 Intermediate Certificate를 만날 수 있다.

Intermediate Certificate은 다시 Root CA인 DST Root CA X3에 의해 발급된 것이라고 한다.

이번엔 스스로 발급한(self-signed) Root CA의 인증서가 나온다.

보통 브라우저와 OS는 신뢰할 수 있는 Root CA의 정보를 가지고 있고, 이를 바탕으로 유효한 체인을 따라가서 신뢰할 수 있는 Root CA까지 도달하면 해당 체인을 모두 신뢰하게 된다.

Let’s Encrypt의 (현재) 인증서를 따라가면 나오는 Root CA인 DST Root CA는 IdenTrust에서 관리하는데, 역사가 길어 대부분의 기기(OS,브라우저,…)가 해당 Root CA 인증서를 신뢰한다.

한편, 7월부터는 Let’s Encrypt를 운영하는 ISRG(Ineternet Security Research Group) Root CA에서 발급한 인증서를 이용하는 것을 테스트 사이트에서 확인할 수 있다.

Cross Sigining

그런데, 방금 그림을 자세히 보면 중간에 있는 Let’s Encrypt Authority X3가 너무 익숙하다. 처음에 살펴본 DST 인증서 체인에도 같은 CA의 인증서가 있었다.

이는 Let’s Encrypt Authority X3가 Cross Signing을 받은 CA이기 때문이다. 즉 두 Root CA, DST Root CA X3와 ISRG Root X1에게 인증을 받은 CA란 것이다.

CA라는 것은 사실 결국 RSA 공개키와 비밀키의 쌍이고, 인증서는 비밀키로 서명된 데이터와 공개키로 이루어진 것인데, CA가 하나라는 말은 키 쌍이 하나라는 뜻이고(중요), 두 곳에서 인증을 받았단 것은 인증서는 둘이라는 뜻이다(중요). 즉, 우리의 End-Entity Certificate은 그 하나의 키(Let’s Encrypt Authority X3)로 서명된 것이므로, 위의 두 인증서(DST Root CA X3, ISRG Root X1) 둘 중 어느 쪽을 이용해도 인증이 유효하다(매우 중요).

따라서, Intermediate Certificate이 만료되기 전까지는 현재 이용중인 DST Root CA X3의 서명이 들어있는 Intermediate Certificate을 ISRG Root X1의 인증서 대신 서버에 적용함으로써 오래 된 유저들이 업데이트 하기를 기다릴 수 있다!!!

그래서 방법은?

Certbot을 이용해서 인증서를 발급받으면 fullchain.pem이 생성되고, TLS 스펙을 따르는 서버는 보통 이 파일을 이용한다. 여기엔 두 개의 인증서 정보가 들어있는데, 위의 것이 End-Entity Certificate, 아래의 것이 Intermediate Certificate 이다.

직접 ISRG의 것과 DST의 것을 바꿔보며 테스트 해 보면 가장 확실한데, ISRG의 Intermediate Certificate은 아까의 테스트 사이트에 접속해서 얻을 수 있다.

openssl s_client -showcerts -connect valid-isrgrootx1.letsencrypt.org:443 -servername valid-isrgrootx1.letsencrypt.org