주요 데이터 형식
X.509, PKCS 7, PKCS 10, PKCS 12, ASN.1, PEM 등 암호 기술과 인증서에 꼭 필요한 형식을 알아보십시오.

X.509
X.509는 디지털 인증서의 바로 그 표준입니다. 예전에는 OpenPGP 같은 경쟁 규격도 있었지만 요즘은 훨씬 덜 쓰입니다. 그런데 사실 X.509가 정확한 표준 이름은 아닙니다. X.509는 ITU-T 표준이고, 실제로 중요한 정의는 ITU-T가 아닌 IETF의 표준, 즉 RFC 5280에 들어 있습니다. 이 RFC는 X.509를 바탕으로 "인터넷용 PKI 프로파일"을 정의하는데, 실무에서 의미가 있는 프로파일은 이것뿐입니다.
디지털 인증서는 비대칭 암호 기술, 특히 디지털 서명을 활용합니다. 오늘날 디지털 인증서의 가장 흔한 사용 사례는 서버 인증입니다. 누구나 이미 디지털 인증서를 써 봤지만, 그것이 X.509 인증서인 줄은 대개 모르고 지나갑니다. HTTPS 웹 사이트에 접속할 때마다 브라우저는 웹 서버와 TLS 연결을 맺습니다. 웹 서버는 X.509 인증서로 자신이 누구인지 증명합니다. 예를 들어 은행 계좌에서 돈을 이체하려고 은행 웹 사이트에 접속할 때, 사용자는 자신이 통신하는 상대가 정말 그 은행인지 확신하고 싶어 합니다. 공격자는 은행 웹 사이트를 사칭해 사용자의 비밀번호와 보안 코드를 읽어 낸 다음 자신이 통제하는 계좌로 돈을 옮기려 할 수 있습니다. HTTPS는 이를 막는 데 도움이 되는데, 공격자에게는 은행 웹 서버의 X.509 인증서가 없기 때문입니다. 브라우저가 특정 도메인에 HTTPS로 접속하고 있다고 알려 주면, 인증서는 그 도메인을 소유한 주체의 웹 서버에 정말로 연결되어 있음을 보증합니다.
인증서는 이를 어떻게 해낼까요? 인증서에는 몇 가지 메타데이터와 암호 키 쌍의 공개 키, 그리고 인증 기관의 서명이 들어 있습니다. 이 세 부분을 차례로 살펴보겠습니다.
X.509 인증서의 구성 요소
메타데이터
X.509 인증서의 메타데이터에는 무엇보다 인증서가 언제까지 유효한지, 어떤 용도로 쓰여야 하는지, 누구에게 발급되었는지가 담깁니다. 특히 TLS 서버 인증서라면 웹 서버의 도메인이 들어 있습니다. 브라우저는 접속하려던 도메인과 인증서의 도메인을 비교합니다. 둘이 일치하지 않으면 브라우저는 진행하지 않고 경고를 표시합니다. 인증서가 만료된 경우에도 경고를 표시합니다.
이상하게도 브라우저는 TLS 없이 HTTP 사이트에 접속할 때는 경고를 표시하지 않는 경우가 많았습니다. 그쪽이 오히려 덜 안전한데도 말입니다. 유효하지 않은 X.509 인증서를 쓰는 웹 서버에 접속했다면 단순한 구성 오류일 수 있고 연결을 엿보는 공격자로부터는 실제로 안전할 수도 있는 반면, HTTP 연결은 아무런 보호도 제공하지 않습니다.
이 문제에도 인증서 피닝 같은 진전이 있기는 합니다. 다만 이는 고급 주제이므로, X.509 인증서에 들어 있는 나머지 두 요소를 살펴보겠습니다.
공개 키
인증서에는 비대칭 키 쌍의 공개 부분이 들어 있습니다. 암호 기술 덕분에 웹 서버는, 다른 사용 사례라면 일반적으로 인증서 소유자는, 키 쌍의 개인 부분도 함께 가지고 있음을 접속하는 클라이언트나 그 누구에게도 노출하지 않고 증명할 수 있습니다. 따라서 클라이언트는 웹 서버가 인증서를 복사한 제삼자가 아니라 실제 소유자임을 확신할 수 있습니다. 인증서 자체를 복사하는 일은 사실 꽤 쉬운데, 웹 서버가 접속을 시도하는 모든 상대에게 인증서 사본을 보내기 때문입니다. 반면 개인 키를 훔치는 일은 어렵거나 불가능합니다. 개인 키는 웹 서버를 벗어나지 않기 때문입니다. 개인 키 탈취를 더 어렵게 만드는 방법으로는 HSM과 TPM 등이 있습니다.
인증 기관의 서명
메타데이터는 인증서가 해당 사용 사례에 적합한지 클라이언트가 확인할 수 있게 해 줍니다. 공개 키는 상대방이 실제로 인증서의 소유자임을 보여 줍니다. 그런데 공격자도 새 키 쌍과 새 인증서를 만들어 이 두 조건을 충족시킬 수 있습니다. 그렇다면 클라이언트는 그 인증서가 신뢰할 만한지 어떻게 알 수 있을까요?
인증서에는 인증 기관(CA) 인증서에 속한 다른 키 쌍의 암호학적 서명이 들어 있습니다. CA 인증서 역시 같은 방식으로 확인할 수 있으며, 그 인증서도 또 다른 인증서로 서명되어 있습니다. 클라이언트는 이 "신뢰 체인"을 이른바 리프 인증서에서 Root CA 인증서까지 따라 올라갈 수 있습니다. Root CA 인증서는 자체 서명되어 있다는 점, 즉 인증서의 서명이 자기 자신의 키 쌍에서 나왔다는 점으로 알아볼 수 있습니다. 보통 이 과정은 한두 단계에 그치므로 관여하는 CA 인증서도 한두 개뿐입니다.
CA는 인증서를 발급할 때 메타데이터가 올바른지 신중하게 확인해야 합니다. 예를 들어 자기 도메인의 TLS 서버 인증서를 받으려면, 자신이 정말 그 도메인의 소유자임을 CA에 증명해야 합니다. 이 확인이 얼마나 철저한지에 따라 기본 인증서를 받을지 Extended Validation(EV) 인증서를 받을지가 정해집니다.
브라우저와 운영 체제는 저마다 미리 정의된 신뢰할 수 있는 Root CA 목록을 함께 제공합니다. 사용자나 관리자는 신뢰할 수 있는 Root CA를 추가할 수 있습니다. 어떤 Root CA는 특정 용도로만 신뢰되고, 어떤 Root CA는 더 포괄적인 신뢰를 받습니다. 클라이언트는 신뢰 체인이 신뢰할 수 있는 Root CA에서 끝나는지 확인합니다. 그렇고, 신뢰 체인의 모든 인증서가 여전히 유효하며, 메타데이터상 용도에 맞게 쓰이고 있다면, 웹 서버의 리프 인증서는 신뢰되고 연결이 수립됩니다.
X.509 인증서의 유효성
X.509 인증서는 결국 신뢰를 어떻게 확립하느냐의 문제입니다. 앞서 설명했듯이 신뢰의 한 가지 기준은 인증서가 신뢰할 수 있는 Root CA까지 체인으로 이어져야 한다는 점입니다. 또 하나는 유효 기간 안에 있어야 한다는 점입니다. 보통은 만료되지 않았다는 뜻이지만, 대개 기술적 오류 때문에 인증서가 아직 유효해지지 않은 경우도 있습니다. 그리고 기준이 하나 더 있습니다. 인증서를 발급한 CA가 그것을 해지하지 않았어야 합니다. 이 자체로 하나의 주제가 되므로 별도의 문서에서 다룹니다.
PKCS#7
PKCS#7은 암호 데이터 형식의 맥가이버 칼이라 할 만하며, 암호화된 메시지, 서명된 메시지, 서명하고 암호화한 메시지, 인증서, 개인 키 등 사실상 무엇이든 담을 수 있습니다
이 점은 이 형식의 큰 단점이기도 합니다. 애플리케이션이나 사용자가 PKCS#7을 받아도 그것만으로는 무엇을 해야 할지 분명하지 않습니다. 중요한 사용 사례를 몇 가지 들면 다음과 같습니다.
- S/MIME 메시지는 기본적으로 본문이나 첨부 파일이 PKCS#7인 이메일입니다.
- SCEP 요청과 응답은 둘 다 실제로는 PKCS#7 서명 메시지입니다.
- EST 응답은 CMS 메시지입니다.
인코딩
흔한 파일 확장자는 .p7b(DER 인코딩), .p7s(서명된 메시지 또는 메시지 서명), .p7m(서명되었거나 암호화된 메시지)입니다. 라벨이 "PKCS7"인 PEM 인코딩도 정의되어 있지만 거의 쓰이지 않습니다.
도구
Windows에서는 PKCS#7 메시지를 더블 클릭으로 열 수 있고 Crypto-shell 확장이 내용을 표시해 줍니다. 다만 대개는 그 안에서 인증서와 개인 키만 꺼낼 수 있고 메시지 내용은 꺼낼 수 없습니다.
OpenSSL 같은 도구로 이런 파일을 다른 형식으로 변환할 수 있습니다.
PKCS#10
PKCS#10에 정의된 인증서 서명 요청(CSR)은 인증 기관(CA)에서 받고자 하는 인증서의 내용을 기술한 파일입니다. 구조는 X.509 인증서와 비슷하지만 CA의 서명이 없습니다. 대신 인증서 요청자의 서명이 들어 있습니다. 그래도 형식 자체가 다르므로 자체 서명 인증서와 같지는 않습니다.
바이너리 DER 인코딩으로 만들 수도 있고, "CERTIFICATE REQUEST" 라벨을 사용해 PEM 인코딩으로 만들 수도 있습니다.
PKCS#12
PKCS#12는 특히 Windows 환경에서 PFX라고도 합니다. 그래서 흔한 파일 확장자는 .pfx와 .p12입니다. 여기에는 X.509 인증서와, 기술적으로 강제되지는 않지만 거의 언제나 그에 대응하는 개인 키가 들어 있습니다.
PKCS#12 파일의 데이터는 보통 비밀번호로 암호화됩니다. 개인 키만 암호화되는 경우가 많아서, 애플리케이션이 허용한다면 비밀번호를 몰라도 인증서를 꺼낼 수 있습니다. 다만 대부분의 애플리케이션은 이를 허용하지 않습니다. Windows 환경에서는 인증서와 개인 키를 파일 하나에 담을 때 PKCS#12가 가장 흔한 방식인 반면, Linux 환경에서는 PEM 인코딩된 PKCS#8 파일이 더 흔합니다.
표준이 인증서와 개인 키를 중첩된 "세이프백"에 저장하는 방법을 여러 가지로 제공하기 때문에, PKCS#12 파일에는 다음과 같은 호환성 문제가 있습니다.
- Windows는 PKCS#12의 개인 키를 그 파일에서 추출한 모든 인증서에 연결해 버리는 것으로 악명이 높습니다. 원래 대응하는 인증서 하나에만 연결해야 하는데 그렇지 않습니다. PKCS#12에 인증서 체인이 들어 있으면 Windows가 CA 인증서의 개인 키를 가지고 있다고 표시할 수도 있습니다.
- macOS에서는 암호 알고리즘이 너무 최신이면 PKCS#12 파일을 가져올 수 없습니다.
- 받는 쪽 애플리케이션이 인증서를 추출할 수 있게 하려면 PKCS#12 파일 안의 인증서를 암호화해야 할 때가 있습니다. 그런데 일부 애플리케이션은 아주 오래되고 약한 알고리즘만 지원합니다. 어차피 공개된 정보이므로 보통은 문제가 되지 않지만, OpenSSL 3.x는 이렇게 오래되고 취약한 알고리즘을 지원하지 않아 해당 PKCS#12를 열기를 거부합니다.
ASN.1과 PEM
Abstract Syntax Notation One(ASN.1)은 데이터 구조를 기술하는 데 쓰는 언어입니다. 정수나 시퀀스 같은 기본 데이터 타입이 미리 정의되어 있고, 프로토콜이나 파일 형식을 만드는 사람은 이를 조합해 사용자 정의 데이터 타입을 정의할 수 있습니다.
DER 인코딩
ITU-T 표준 X.680은 ASN.1로 규정된 데이터에 대해 여러 인코딩 방식을 정의합니다. X.509 관련 데이터에서 가장 중요한 인코딩은 DER입니다. 타입을 인코딩하는 방법이 하나뿐이므로 타입의 바이너리 DER 표현을 해싱하면 언제나 같은 값이 나오기 때문인데, 이는 예를 들어 ASN.1로 인코딩된 데이터에 서명할 때 중요합니다.
PEM 인코딩
전부는 아니지만 상당수의 X.509 관련 파일 형식은 DER 인코딩으로 바이너리 저장할 수도 있고, DER 인코딩 위에 PEM 인코딩을 추가로 적용할 수도 있습니다. PEM은 ASCII 문자만 사용하므로 클립보드로 손쉽게 복사해 붙여 넣을 수 있고, 그것이 아직 중요하던 수십 년 전에는 이메일로 보낼 수도 있었습니다.
도구
ASN.1로 인코딩된 파일이 있는데 그것이 어떤 타입인지 모르거나 그 타입을 다루는 애플리케이션이 없더라도, 원시 ASN.1 구조를 디코딩해 내용을 확인할 수는 있습니다. Windows에서는 내장 도구인 certutil이 certutil -decode 명령으로 이를 처리할 수 있습니다.