안녕하세요, PSJ입니다.
오늘은 HTTPS 통신 시 사용되는 SSL(SSecure Socket Layer) 인증서 포맷을 바꾸는 방법을 알아보겠습니다.
(서론은 거창하지만, OpenSSL & Keytool 을 이용해서 명령어 몇 줄 입력하는 게 전부입니다 ^^;;)
#1. 서론
인증서 파일의 경우 인코딩 방식과 확장자가 일치하는 경우도 있고, 그렇지 않은 경우도 있기 때문에 사용 시 혼란스러울 때가 있는데요. 그래서 아래와 정리해 봤습니다.
먼저 X.509 공개키 암호화 방식에는 대표적으로 두 가지 인코딩 체계를 사용합니다. PEM과 DER인데요.
X.509 란? 암호학에서 공개키 인증서와 인증알고리즘의 표준 가운데에서 공개 키 기반(PKI)의 ITU-T 표준이다.
Encoding 체계 | 특 징 |
PEM (Privacy Enhanced Mail) | - X.509 인증서의 가장 일반적인 형식이다. - PEM 파일은 Base64 ASCII 인코딩으로 된 하나 이상의 항목을 포함하는 텍스트 파일이다. - 일반 텍스트 머리글과 바닥 글 (예 : -----BEGIN XXX-----및 -----END XXX-----)이 있다. 들어간 정보에 따라 XXX 부분이 CERTIFICATE, RSA PRIVATE KEY, CERTIFICATE REQUEST 등의 키워드가 들어간다. - 단일 PEM 파일에는 최종 엔터티 인증서, 개인 키 또는 완전한 신뢰 체인을 형성하는 여러 인증서가 포함될 수 있다. |
DER (Distinguished Encoding Rules) | - X.509 인증서 및 개인 키에 대한 바이너리 인코딩이다. - PEM과 달리 -----BEGIN XXX----- 과 같은 키워드가 포함되지 않는다. |
위 두 가지 인코딩 방식 외에도 JKS, PKCS#XX 같은 별도 Encoding 포맷도 존재합니다.
보통 SSL인증서 관련 파일은 아래와 같은 형식의 확장자로 사용됩니다. 확장자 별로 다시 한번 알아보시죠.
확장자 | 설명 |
.pem | PEM (Privacy Enhanced Mail)은 Base64 인코딩된 ASCII 텍스트 이다. 파일 구분 확장자로 .pem 을 주로 사용하며, 에디터를 통한 열기/수정도 가능하다. 개인키, 서버인증서, 루트인증서, 체인인증서 및 SSL 발급 요청시 생성하는 CSR 등에 사용되는 포맷이며, 가장 광범위하고 거의 99% 대부분의 시스템에 호환되는 산업 표준 포맷이다. (대부분 텍스트 파일) |
.crt | 거의 대부분 PEM 포맷이며, 주로 UNIX/Linux 기반 시스템에서 인증서 파일임을 구분하기 위해서 사용되는 확장자다. 다른 확장자로 .cer 도 사용된다. 파일을 에디터로 열어 보면 PEM 포맷인지 바이너리 포맷인지 알수 있지만 99% 는 Base64 PEM 포맷이라고 봐도 무방하다. (대부분 텍스트 파일) |
.cer | 거의 대부분 PEM 포맷이며, 주로 Windows 기반에서 인증서 파일임을 구분하기 위해서 사용되는 확장자다. crt 확장자와 거의 동일한 의미이며, cer 이나 crt 확장자 모두 윈도우에서는 기본 인식되는 확장자이다. 저장할때 어떤 포맷으로 했는지에 따라 다르며, 이름 붙이기 나름이다. |
.csr | Certificate Signing Request 의 약자이며 거의 대부분 PEM 포맷이다. SSL 발급 신청을 위해서 본 파일 내용을 인증기관 CA 에 제출하는 요청서 파일임을 구분하기 위해서 붙이는 확장자 이다. (대부분 텍스트 파일) |
.der | Distinguished Encoding Representation (DER) 의 약자이며, 바이너리 포맷이다. 노트패드등으로 열어 봐서는 알아 볼수 없다. 바이너리 인코딩 포맷을 읽을수 있는 인증서 라이브러리를 통해서만 내용 확인이 가능하다. 사설 또는 금융등 특수 분야 및 아주 오래된 구형 시스템을 제외하고는, 최근 웹서버 SSL 작동 시스템 에서는 흔히 사용되는 포맷은 아니다. (바이너리 이진 파일) |
.pfx .p12 |
PKCS#12 바이너리 포맷이며, Personal Information Exchange Format 를 의미한다. 주로 Windows IIS 기반에서 인증서 적용/이동시 활용된다. 주요 장점으로는 개인키, 서버인증서, 루트인증서, 체인인증서를 모두 담을수 있어서 SSL 인증서 적용이나 또는 이전시 상당히 유용하고 편리하다. Tomcat 등 요즘에는 pfx 설정을 지원하는 서버가 많아지고 있다. (바이너리 이진 파일) |
.key | 주로 openssl 및 java 에서 개인키 파일임을 구분하기 위해서 사용되는 확장자이다. PEM 포맷일수도 있고 DER 바이너리 포맷일수도 있으며, 파일을 열어봐야 어떤 포맷인지 알수가 있다. 저장할때 어떤 포맷으로 했는지에 따라 다르며, 확장자는 이름 붙이기 나름이다. |
.jks | Java Key Store의 약자이며, Java 기반의 독자 인증서 바이너리 포맷이다. pfx 와 마찮가지로 개인키, 서버인증서, 루트인증서, 체인인증서를 모두 담을수 있어서 SSL 인증서 파일 관리시 유용하다. Tomcat 에서 SSL 적용시 가장 많이 사용되는 포맷이다. (바이너리 이진 파일) |
근데, 왜 바꿔야 하나요?
실무에서 가끔 apache/nginx/webtob 와 같은 웹 서버에서 사용하는 인증서를 Tomcat에 등록해서 사용해야 할 일이 있을 때 사용한다. 보편적으로 웹서버(apache/nginx/webtob)에서는 PEM(Privacy Enhanced Mail) 포맷의 인증서를 사용하다 보니, 해당 인증서를 Tomcat에 등록해야 할 때는 Tomcat Native Library를 사용하거나, JKS 포맷으로 변환해야 할 때가 있다.
#2. PEM to JKS 포멧 변경
자, 서론이 너무 길었습니다. 일반적인 웹서버에서 사용하는 형식을 JKS(Java Key Store) 형식으로 변환해 보겠습니다.
- OpenSSL/Java Keytool 이 설치되어 있어야 합니다.
- 인증서 파일(cert.pem)에 공개키(인증서)/개인키가 포함되어 있을 경우, 2-1부터 진행하시면 됩니다.
- 별도 파일로 공개키(인증서)/개인키가 분리되어 있을 경우, 2-3부터 진행하시면 됩니다.
#2-1. 인증서 파일(cert.pem)에서 개인키 파일 추출
## openssl rsa -in 인증서.pem -text > 개인키.key
$ openssl rsa -in cert.pem -text > private.key
Enter pass phrase for cert.pem: "cert.pem 인증서 파일 패스워드 입력"
writing RSA key
#2-2. 인증서 파일(cert.pem)에서 공개키 파일 추출
## oepnssl x509 -inform PEM -in 인증서.pem -out 공개키.crt
$ oepnssl x509 -inform PEM -in cert.pem -out cert.crt
#2-3. 공개키(cert.crt) 및 중계기관 인증서(RootCA 포함)를 합친 신규 인증서 파일 생성
## cat 공개키.crt 중계기관인증서.crt > 신규인증서.pem
$ cat cert.crt Chain_RootCA_Bundle.crt > cert_new.pem
#2-4. 신규 인증서 파일(cert_new.pem)과 개인키(private.key) 합친 PFK 인증서 교환 파일 생성
## openssl pkcs12 -export -name 인증서별칭 -in cert_new.pem -inkey 개인키.key -out 인증서.pfx
$ openssl pkcs12 -export -name psjco.com -in cert_new.pem -inkey private.key -out cert.pfx
Enter Export Password : "cert.pfx 파일의 패스워드 입력"
Verifying - Enter Export Password : "cert.pfx 패스워드 확인"
#2-5. PFK 인증서 파일(cert.pfk)을 JKS로 변환
## keytool -importkeystore -srckeystore 인증서.pfx -srcstoretype pkcs12 -destkeystore 인증서.jks -deststoretype jks
$ keytool -importkeystore -srckeystore cert.pfx -srcstoretype pkcs12 -destkeystore cert.jks -deststoretype jks
Importing keystore cert.pfx to cert.jks...
Enter destination keystore password : "jks 인증서 파일의 패스워드 입력"
Re-enter new password : "jks 인증서 파일의 패스워드 확인"
Enter source keystore password : "cert.pfx 패스워드 입력, 2-4에서 생성된 Password"
Entry for alias psjco.com successfully imported.
#2-6. 생성된 JKS 인증서 파일(cert.jks) 확인
$ keytool -list -v -keystore cert.jks
Enter keystore password: "cert.jks 인증서 패스워드 입력"
Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: psjco.com
Creation date: Dec 30, 2020
Entry type: PrivateKeyEntry
Certificate chain length: 4
Certificate[1]:
Owner: CN=www.psjco.com, ...
...
...
끝입니다. 이렇게 생성된 cert.jks 파일을 Application에 적용해 주면 됩니다.
실제 별거 없었죠? JKS 포멧의 경우 인증서(공개키), 개인키, 중계기관/Root 인증서를 포함하는 형태라서 각각 분리돼 있던 파일을 합쳐서 JKS 포맷으로 변환해 준 것이라고 이해하시면 되겠습니다.
# Spring boot
server:
port:8443
ssl:
enabled: true
key-store: /ssl/cert.jks
key-store-type: jks
key-store-password: password
# Tomcat
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="8443"
maxThreads="150" scheme="https" secure="true" SSLEnabled="true"
keystoreFile="/ssl/cert.jks"
keystorePass="password" clientAuth="false" sslProtocol="TLS" />
#3. 다른 유형의 변경
## cert.pfx 에서 공개키(cert.crt) 추출하기 (cert.pfx 암호 필요)
$ openssl pkcs12 -in cert.pfx -clcerts -nokeys -out cert.crt
## cert.pfx 에서 개인키(private.key) 추출하기 (cert.pfx 암호 필요)
$ openssl pkcs12 -in cert.pfx -nocerts -nodes -out private.key
## cert.pfx 에 포함된 인증서 확인 (.pfx 암호 필요)
$ openssl pkcs12 -info -in cert.pfx
## Java Key Store(cert.jks) 를 PKCS#12 으로 변환
## cert.jks 파일을 cert.pfx 파일로 변환 저장 (원본 cert.jks 파일 패스워드 필요, 대상 cert.pfx 패스워드 지정)
$ keytool -importkeystore -srckeystore cert.jks -srcstoretype JKS -srcstorepass "password" -destkeystore cert.pfx -deststoretype PKCS12 -deststorepass "password"
## Java Key Store(cert.jks) 비밀번호 변경
$ keytool.exe -storepasswd -new 변경비밀번호 -keystore cert.jks
키 저장소 비밀번호 입력: (기존 KeyStore 비밀번호)
## PEM -> DER (바이너리)
## 인증서 :
$ openssl x509 -outform DER -in cert.pem -out newcert.der
## 개인키 :
$ openssl rsa -in private.key -pubout -outform DER -out newPrivate.key
## DER(바이너리) -> PEM
$ openssl x509 -inform der -in cert.der -out newcert.pem
## CER(바이너리) -> PEM
$ openssl x509 -in cert.cer -outform PEM -out newcert.pem
## PEM -> p7b(pkcs#7)
$ openssl crl2pkcs7 -nocrl -certfile cert.pem -out cert.p7b -certfile RootChain.cer
## CER/PrivateKey -> pfx(pkcs#12)
$ openssl pkcs12 -export -in cert.cer -inkey private.key -out newcert.pfx -certfile RootChain.cer
PEM to JKS 외에도 위와 같이 다양한 포멧 형태로 변환이 가능합니다. 참고하셔서 활용하시면 되겠습니다.
오늘도 좋은하루 보내세요. ^^
공감과 댓글은 큰 힘이 됩니다.
댓글