Self signed SSL

인증서(digital certificate)는 개인키 소유자의 공개키(public key)에 인증기관의 개인키로 전자서명한 데이터다. 모든 인증서는 발급기관(CA) 이 있어야 하나 최상위에 있는 인증기관(root ca)은 서명해줄 상위 인증기관이 없으므로 root ca의 개인키로 스스로의 인증서에 서명하여 최상위 인증기관 인증서를 만든다. 이렇게 스스로 서명한 ROOT CA 인증서를 Self Signed Certificate 라고 부른다. IE, FireFox, Chrome 등의 Web Browser 제작사는 VeriSign이나 co.krodo 같은 유명 ROOT CA 들의 인증서를 신뢰하는 CA로 미리 등록해 놓으므로 저런 기관에서 발급된 SSL 인증서를 사용해야 browser 에서는 해당 SSL 인증서를 신뢰할수 있는데 OpenSSL 로 만든 ROOT CA와 SSL 인증서는 Browser가 모르는 기관이 발급한 인증서이므로 보안 경고를 발생시킬 것이나 테스트 사용에는 지장이 없다.

ROOT CA 인증서를 Browser에 추가하여 보안 경고를 발생시키지 않으려면 Browser 에 SSL 인증서 발급기관 추가하기를 참고하자.

- SSL 인증서 종류 -

  1. [.pem] PEM (Privacy Enhanced Mail)은 Base64 인코딩된 ASCII 텍스트 이다. 파일 구분 확장자로 .pem 을 주로 사용한다. 노트패드에서 열기/수정도 가능하다. 개인키, 서버인증서, 루트인증서, 체인인증서 및 SSL 발급 요청시 생성하는 CSR 등에 사용되는 포맷이며, 가장 광범위하고 거의 99% 대부분의 시스템에 호환되는 산업 표준 포맷이다. (대부분 텍스트 파일)
  2. [.crt] 거의 대부분 PEM 포맷이며, 주로 유닉스/리눅스 기반 시스템에서 인증서 파일임을 구분하기 위해서 사용되는 확장자 이다. 다른 확장자로 .cer 도 사용된다. 파일을 노트패드 등으로 바로 열어 보면 PEM 포맷인지 바이너리 포맷인지 알수 있지만 99% 는 Base64 PEM 포맷이라고 봐도 무방하다. (대부분 텍스트 파일)
  3. [.cer] 거의 대부분 PEM 포맷이며, 주로 Windows 기반에서 인증서 파일임을 구분하기 위해서 사용되는 확장자 이다. crt 확장자와 거의 동일한 의미이며, cer 이나 crt 확장자 모두 윈도우에서는 기본 인식되는 확장자이다. 저장할때 어떤 포맷으로 했는지에 따라 다르며, 이름 붙이기 나름이다.
  4. [.csr] Certificate Signing Request 의 약자이며 거의 대부분 PEM 포맷이다. SSL 발급 신청을 위해서 본 파일 내용을 인증기관 CA 에 제출하는 요청서 파일임을 구분하기 위해서 붙이는 확장자 이다. (대부분 텍스트 파일)
  5. [.der] Distinguished Encoding Representation (DER) 의 약자이며, 바이너리 포맷이다. 노트패드등으로 열어 봐서는 알아 볼수 없다. 바이너리 인코딩 포맷을 읽을수 있는 인증서 라이브러리를 통해서만 내용 확인이 가능하다. 사설 또는 금융등 특수 분야 및 아주 오래된 구형 시스템을 제외하고는, 최근 웹서버 SSL 작동 시스템 에서는 흔히 사용되는 포맷은 아니다. (바이너리 이진 파일)
  6. [.pfx / .p12] PKCS#12 바이너리 포맷이며, Personal Information Exchange Format 를 의미한다. 주로 Windows IIS 기반에서 인증서 적용/이동시 활용된다. 주요 장점으로는 개인키,서버인증서,루트인증서,체인인증서를 모두 담을수 있어서 SSL 인증서 적용이나 또는 이전시 상당히 유용하고 편리하다. Tomcat 등 요즘에는 pfx 설정을 지원하는 서버가 많아지고 있다. (바이너리 이진 파일)
  7. [.key] 주로 openssl 및 java 에서 개인키 파일임을 구분하기 위해서 사용되는 확장자이다. PEM 포맷일수도 있고 DER 바이너리 포맷일수도 있으며, 파일을 열어봐야 어떤 포맷인지 알수가 있다. 저장할때 어떤 포맷으로 했는지에 따라 다르며, 확장자는 이름 붙이기 나름이다.
  8. [.jks] Java Key Store의 약자이며, Java 기반의 독자 인증서 바이너리 포맷이다. pfx 와 마찬가지로 개인키, 서버인증서, 루트인증서, 체인인증서를 모두 담을 수 있어서 SSL 인증서 파일 관리 시 유용하다. Tomcat에서 SSL 적용시 가장 많이 사용되는 포맷이다. (바이너리 이진 파일)

1. Pre-config

Configure environment to set JAVA_HOME to the Oracle JDK (ALL host) Java Home 경로가 설정되어 있는 경우에는 해당 과정을 스킵하면 된다. 설치한 Oracle Jdk or Open JDK에 맞는 경로로 경로를 설정해주면 된다.

vi ~/.bashrc
export JAVA_HOME=/usr/java/jdk1.8.0_232-cloudera
export PATH=$JAVA_HOME/bin:$PATH

#Directory 생성 ( Rootca Directory )
mkdir -p /opt/security/pki/ca
#CRT(인증서)생성에 필요한 configuration 파일 생성
vi /opt/security/pki/ca/rootca.cnf

[ req ]
default_bits = 2048
default_md = sha1
default_keyfile = rootca.key
distinguished_name = req_distinguished_name
extensions = v3_ca
req_extensions = v3_ca

[ v3_ca ]
basicConstraints = critical, CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
##authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = keyCertSign, cRLSign
nsCertType = sslCA, emailCA, objCA

[req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = KR
countryName_min = 2
countryName_max = 2
# 회사명 입력
organizationName = Organization Name (eg, co.krpany)
organizationName_default = Example Inc.
# 부서 입력
#organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default = Condor Project
# SSL 서비스할 domain 명 입력
co.krmonName = co.krmon Name (eg, your name or your server's hostname)
co.krmonName_default = Example's Self Signed CA
co.krmonName_max = 64
vi /opt/security/pki/ca/openssl_host.cnf

[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = server_cert

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
co.krmonName = co.krmon Name
emailAddress = Email Address
countryName_default = KR
stateOrProvinceName_default = Seoul
localityName_default = mapo #지역구
0.organizationName_default = example #회사이름
organizationalUnitName_default = bigdata #조직이름
emailAddress_default = test@example.co.kr

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, ditestalSignature, cRLSign, keyCertSign

[ server_cert ]
basicConstraints = CA:FALSE
nsco.krment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = nonRepudiation, ditestalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = example.co.kr
DNS.2 = *.example.co.kr
DNS.3 = test01.example.co.kr
DNS.4 = *.test01.example.co.kr

2. RootCA생성

  • Keytool을 이용한 jks(java key store) 파일 생성 // 공개키, 개인키, 인증서 발급까지 가능한 java에서 사용하는 키 저장소 방식. 내용 추출까지 가능하므로 csr key파일로 뽑아서 사용
  • keytool을 이용한 java keystore와 CSR 생성 (비밀번호는 무조건 같아야 함, 다르면 CM 에러 발생)

1. test-rootca.jks 생성

$JAVA_HOME/bin/keytool -genkeypair -alias test-rootca -keyalg RSA -keystore /opt/security/pki/ca/test-rootca.jks -keysize 2048 -dname "CN=test-rootca,OU=Bigdata_Team,O=Exapmle,L=MapoGu,ST=Seoul,C=KR

$JAVA_HOME/bin/keytool -genkeypair -alias test-rootca -keyalg RSA -keystore /opt/security/pki/ca/test-rootca.jks -keysize 2048 -dname "CN=test-rootca,OU=Bigdata_Team,O=test,L=MapoGu,ST=Seoul,C=KR" -ext san=dns:test01.example.co.kr

2. test-rootca.csr 생성

$JAVA_HOME/bin/keytool -certreq -alias test-rootca -keystore /opt/security/pki/ca/test-rootca.jks -file /opt/security/pki/ca/test-rootca.csr -ext san=dns:test01.example.co.kr -ext EKU=serverAuth,clientAuth

3. Jks로 pkcs #12 파일 생성

$JAVA_HOME/bin/keytool -importkeystore -srckeystore /opt/security/pki/ca/test-rootca.jks -destkeystore /opt/security/pki/ca/test-rootca.p12 -deststoretype PKCS12 -srcalias test-rootca

4. pkcs #12를 openssl로 key파일 생성(PEM형식)

openssl pkcs12 -in /opt/security/pki/ca/test-rootca.p12 -nocerts -out /opt/security/pki/ca/test-rootca.key
openssl pkcs12 -in /opt/security/pki/ca/test-rootca.p12 -nocerts -out /opt/security/pki/ca/test-rootca.key.pem

5. crt 인증서 생성

openssl x509 -req -days 3650 -extensions v3_ca -set_serial 1 -sha256 -in /opt/security/pki/ca/test-rootca.csr -signkey /opt/security/pki/ca/test-rootca.key -out /opt/security/pki/ca/test-rootca.crt -extfile /opt/security/pki/ca/openssl_rootca.cnf

openssl x509 -req -days 3650 -extensions v3_ca -set_serial 1 -sha256 -in /opt/security/pki/ca/test-rootca.csr -signkey /opt/security/pki/ca/test-rootca.key -out /opt/security/pki/ca/test-rootca.crt.pem -extfile /opt/security/pki/ca/openssl_rootca.cnf

외부 접근 및 수정을 방지를 위한 권한 변경

chmod 600 /opt/security/pki/ca/test-rootca.*

3. Host 인증서 생성

  1. CSR생성
$JAVA_HOME/bin/keytool -certreq -alias *.example.co.kr -keystore /opt/security/pki/asterisk.example.co.kr.jks -file /opt/security/pki/asterisk.example.co.kr.csr; done
  1. jks » pkcs 12
$JAVA_HOME/bin/keytool -importkeystore -srckeystore /opt/security/pki/test.example.co.kr.jks -destkeystore /opt/security/pki/test.example.co.kr.p12 -deststoretype PKCS12 -srcalias test.example.co.kr; done

  1. pkcs 12 »key
openssl pkcs12 -in /opt/security/pki/test.example.co.kr.p12 -nocerts -out /opt/security/pki/test.example.co.kr.key; done

4. getting CA Private key

openssl x509 -req -sha256 -days 365 -extensions server_cert -in /opt/security/pki/test.example.co.kr.csr -CA /opt/security/pki/ca/test-rootca.crt -CAkey /opt/security/pki/ca/test-rootca.key -CAcreateserial -out /opt/security/pki/test.example.co.kr.crt -extfile /opt/security/pki/ca/openssl_host.cnf;done

#공개키를 대체 시스템 truststore(jssecacerts)에 import
$JAVA_HOME/bin/keytool -importcert -alias test-rootca -keystore $JAVA_HOME/jre/lib/security/jssecacerts -file /opt/security/pki/ca/test-rootca.crt

password : changeit (기본 설정값)

Yes

#비밀번호 변경 $JAVA_HOME/bin/keytool -storepasswd -keystore $JAVA_HOME/jre/lib/security/jssecacerts changeit 설정할 password 입력

#jssecacerts 배포 pscp -h /root/allnodes $JAVA_HOME/jre/lib/security/jssecacerts $JAVA_HOME/jre/lib/security/jssecacerts

#RootCA를 server cert에 추가, truststore에 저장

» 명령을 통해서 test-rootca.crt의 내용을 test.example.co.kr.crt 파일에 추가 하는 것.

cat /opt/security/pki/ca/test-rootca.crt >> /opt/security/pki/test.example.co.kr.crt

#변경한 crt를 기반으로 jks파일 업데이트(importcert)

$JAVA_HOME/bin/keytool -importcert -alias test.example.co.kr -file /opt/security/pki/test.example.co.kr.crt -keystore /opt/security/pki/test.example.co.kr.jks
$JAVA_HOME/bin/keytool -importcert -alias *.example.co.kr -file /opt/security/pki/asterisk.example.co.kr.crt -keystore $JAVA_HOME/jre/lib/security/jssecacerts
openssl x509 -inform PEM -in /opt/security/pki/test.example.co.kr.crt > /opt/security/pki/serverpublic.pem
openssl rsa -in /opt/security/pki/test.example.co.kr.key -text > /opt/security/pki/serverprivate.pem
  • RootCA에 대한 public.pem 파일 생성 (RootCA를 생성한 호스트에서 작업 진행) openssl x509 -inform PEM -in /opt/security/pki/ca/test-rootca.crt > /opt/security/pki/ca/rootpublic.pem

#truststore에 RootCA가 포함되었는지 확인

  • keytool 은 외부에서 생성된 private key 를 keystore 에 import 하는 방법을 제공하지 않는다. 한 가지 방법은 JDK 6 이상부터 PKCS#12 으로 된 인증서와 개인키를 keystore 에 import 하는게 가능하므로 openssl 로 pkcs#12를 만들고 pkcs#12 를 KeyStore 로 임포트하면 된다.
keytool -list -keystore $JAVA_HOME/jre/lib/security/jssecacerts >> jssecacerts.txt

https://nuritech.tistory.com/25