OpenSSL!
SSL, TLS
- SSL(Secure Sockets Layer) 보안 소켓 계층
- 1990년대 넷스케이프(Netscape)에서 개발한 보안 프로토콜
SSL 2.0
(1995),SSL 3.0
(1996)으로 발전.
- TLS(Transport Layer Security) 전송 계층 보안
SSL 3.0
을 기반으로IETF
에서 표준화한 프로토콜.TLS 1.3
(2018, 최신 버전)
핸드쉐이크를 통해 세션키(대칭키)를 공유하고 세션키로 암호화 통신 하기 위한 방법이다.
해당 키 교환을 위한 핸드쉐이크를 PKI 기반으로 수행한다.
TLS 1.3
은 여러 키(클라이언트→서버, 서버→클라이언트)를 생성한다.
X.509
ITU-T(국제전기통신연합) 에서 정의한 공개 키 기반 구조(PKI, Public Key Infrastructure) 인증서 구조 표준.
Openssl 로 생성하는 인증서(공개키) 는 모두 대부분 X.509 표준을 따른다.
아래와 같은 구조로 정의되며 ASN.1(Abstract Syntax Notation One)
구조라한다.
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING
}
TBSCertificate ::= SEQUENCE {
version [0] INTEGER, -- v1(0), v2(1), v3(2)
serialNumber INTEGER, -- 인증서 일련번호
signature AlgorithmIdentifier, -- 서명 알고리즘 (예: SHA256withRSA)
issuer Name, -- 발급자 정보 (CA의 DN)
validity Validity, -- 유효 기간 (notBefore, notAfter)
subject Name, -- 소유자 정보 (DN)
subjectPublicKeyInfo SubjectPublicKeyInfo, -- 공개 키와 알고리즘
issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL, -- 발급자 고유 ID (선택)
subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL, -- 소유자 고유 ID (선택)
extensions [3] Extensions OPTIONAL -- 확장 필드 (v3에서 사용)
}
DN은 아래와 같은 정보가 포함된다.
- Country Name (C): US
- State or Province Name (ST): California
- Locality Name (L): San Francisco
- Organization Name (O): Example Inc.
- Organizational Unit Name (OU): IT Department
- Common Name (CN): www.example.com
- Email Address: admin@example.com
X.509
는 CA 기반에서 동작하는SSL/TLS
표준이다.
이외에도 이메일, Linux 패키지 서명할 때 사용하는OpenPGP
같은 인증서 표준이 있다.
OpenSSL 기반 인증서 생성
테스트용으로 인증 기관에서 사용하는것 처럼 사설 루트 인증서(이하 RootCA) 를 생성,
ca.key
: 루트 개인키ca.crt
: 루트 공개키(루트 인증서)
공인 RootCA
를 관리하는 공인 인증 기관(CA: Public Certificate Authority) 목록은 아래와 같다.
- DigiCert - DigiCert Global Root G2
- DigiCert - DigiCert Global Root CA
- DigiCert - DigiCert High Assurance EV Root CA
- Amazon - Amazon Root CA 1
- Amazon - Amazon Root CA 2
- Let’s Encrypt (ISRG) - Let’s Encrypt Authority X3 (이전, 지금은 X1/X2)
- Let’s Encrypt (ISRG) - ISRG Root X1
- Let’s Encrypt (ISRG) - ISRG Root X2 (신규)
- Microsoft - Microsoft Root Certificate Authority 2011
- Microsoft - Microsoft ECC Root Certificate Authority 2017
- Google - GTS Root R1
- Google - GTS Root R2
- Google - GTS Root R3
- Google - GTS Root R4
- Apple - Apple Root CA
RootCA
의 개인키는 물리적 금고에서 보관중이라고 함.
OS 와 브라우저 설치 및 업데이트 과정에서 신뢰 저장소 에 공식 RootCA
를 저장 및 업데이트한다.
Root CA
아래 명령을 통해 사설 RootCA
를 생성.
openssl genrsa -out root_ca.key 2048
openssl req -x509 -new -key root_ca.key -days 3650 -out root_ca.crt \
-subj "/C=KR/ST=Gyeonggi-do/L=Seongnam-si/\
O=Demo-Comp/OU=Demo-Service/\
CN=RootCA/emailAddress=kouzie@test.com"
Intermediate CA
보통 인증서는 루트 CA 가 바로 인증해주기 보단 2 단계정도를 레벨로 구성한다.
이때 중간에 있는 CA 기관들을 Intermediate CA
라 부른다.
Intermediate CA
역시 사설로 생성
- intermediate_ca.key: 중간 CA 개인키
- intermediate_ca.csr: 서명 요청서(Certificate Signing Request)
- 중간 CA 의 공개키와 메타데이터를 서명한 파일.
- 서명을 RootCA 에 제출, RootCA 가 서명한 중간 CA 공개키를 받기 위해 사용함.
- intermediate_ca.crt: 중간 CA 공개키(중간 CA 인증서)
openssl genrsa -out intermediate_ca.key 2048
openssl req -new -key intermediate_ca.key \
-out intermediate_ca.csr \
-subj "/C=KR/ST=Gyeonggi-do/L=Seongnam-si/\
O=Demo-Comp/OU=Demo-Service/\
CN=IntermediateCA/emailAddress=kouzie@test.com"
intermediate_ca.csr
파일을 기반으로 서버 공개키(서버 인증서)를 CA 로 서명 및 생성
openssl x509 -req -in intermediate_ca.csr \
-CA root_ca.crt \
-CAkey root_ca.key \
-CAcreateserial \
-days 1825 \
-out intermediate_ca.crt \
-extensions v3_ca \
-extfile <(cat <<EOF
[v3_ca]
basicConstraints = critical,CA:TRUE
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
EOF
)
-days 1825
RootCA 보단 유효기간을 짧게 설정해야함.-CA root_ca.crt
RootCA 공개키로 발급자 정보를 포함, 인증서에 RootCA 정보를 추가(체이닝)-CAkey root_ca.key
RootCA 개인키로 csr 파일에 서명-CAcreateserial
인증서의 고유식별자를 생성,ca.srl
파일에 저장.extensions v3_ca
확장자 섹션 이름. 중간 CA로 동작하도록 설정.extfile <(cat <<EOF ... EOF)
사용하여 확장자 정의를 인라인으로 제공
[v3_ca]
# 인증서가 CA로 동작 가능(인증서 발급 권한 부여).
basicConstraints = critical,CA:TRUE
# digitalSignature: 디지털 서명 가능.
# cRLSign: CRL(인증서 폐지 목록) 서명 가능.
# keyCertSign: 다른 인증서 서명 가능.
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
# 인증서의 공개키에서 고유 식별자 생성.
subjectKeyIdentifier = hash
# 루트 CA의 키 식별자와 정보 포함, 신뢰 체인 추적에 사용.
authorityKeyIdentifier = keyid:always,issuer
명령을 수행하면 root_ca.srl(인증서 고유식별자 파일)
이 생성된다.
향후 Intermediate CA
의 폐기 필요시 인증서 폐기 리스트(Certificate Revocation List)
에 저장될 용도로 사용한다.
Server 인증서
Intermediate CA
를 통해 끝단에 위치하는 서버 인증서를 생성,
- server.key: 서버 개인키
- server.csr: 서버 서명 요청서(Certificate Signing Request)
- 서버 공개키와 메타데이터를 서명한 파일.
- 서명을
IntermediateCA
에 제출,IntermediateCA
가 서명한 서버 공개키를 받기 위해 사용함.
- server.crt: 서버 공개키(서버 인증서)
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
-subj "/C=KR/ST=Gyeonggi-do/L=Seongnam-si/\
O=Demo-Comp/OU=Demo-Service/\
CN=ServerCN/emailAddress=kouzie@test.com"
server.csr
파일을 기반으로 서버 공개키(서버 인증서)를 IntermediateCA
로 서명 및 생성
openssl x509 -req -in server.csr \
-CA intermediate_ca.crt \
-CAkey intermediate_ca.key \
-CAcreateserial \
-days 365 -out server.crt
명령을 수행하면 intermediate_ca.srl(인증서 고유식별자 파일)
이 생성된다.
향후 서버 인증서의 폐기 필요시 인증서 폐기 리스트(Certificate Revocation List)
에 저장될 용도로 사용한다.
인증서 파일 포맷 종류
-----BEGIN CERTIFICATE-----
MIIEDjCCAvagAwIBAgIUAMXlft1kCF7moTjpZsTFQi90OBgwDQYJKoZIhvcNAQEL
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE REQUEST-----
MIIC3TCCAcUCAQAwgZcxCzAJBgNVBAYTAktSMRQwEgYDVQQIDAtHeWVvbmdnaS1k
...
-----END CERTIFICATE REQUEST-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDUKO4G4+2QfGjP
...
-----END PRIVATE KEY-----
인증서 파일을 만들다 보면 위와같은 포멧, .crt
, .pem
같은 확장자 암호 관련 파일이 생성된다.
- crt(Certificate)
- X.509 포멧 인증서 파일,
- PEM 또는 DER 형식으로 인코딩됨.
- 파일을 열었는데 깨진 문자열 혹은 이진 구조일 경우 DER, 16진수 형태일경우 PEM.
- pem (Privacy Enhanced Mail)
- 인증서/키 같은 보안 객체를 Base64로 인코딩하여 저장한 파일.
- 대부분 crt 파일이 pem 형태로 인코딩되어있음.
- cer
crt
파일과 동일한 역할을 한다.- Windows 기반 인증서 파일임을 구분하기 위해서 사용되는 확장자,
crt
는 주로 유닉스/리눅스에서 사용.
- .p12/.pfx
- 인증서, 개인 키, CA 체인을 하나의 암호화된 파일에 저장하는 형식.
PKCS#12
포멧으로 바이너리 형식으로 저장.- 백업 또는 이동용으로 주로 사용.
공개 키 암호 표준(Public-Key Cryptography Standard, PKCS)
PKCS#1, PKCS#8, PKCS#10, PKCS#12
포멧은 PKI 에서 매우 자주 사용됨.
.key
확장자의 경우 PKCS#1
혹은 PKCS#8
.p12
확장자의 경우 PKCS#12
- PKCS#1
- RSA 개인키를 저장하는 가장 기본적인 형식
-----BEGIN RSA PRIVATE KEY-----
로 시작함- 아래 정보가 저장됨
version INTEGER, -- 0
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER -- (q^-1) mod p
- PKCS#8
- 개인 키를 저장하는 일반화된 표준, RSA뿐만 아니라 EC, DSA 등 다양한 알고리즘을 지원
PKCS#8
가 더 최신 포멧-----BEGIN PRIVATE KEY-----
로 시작함- 아래 정보가 저장됨
version INTEGER, -- 0
algorithm AlgorithmIdentifier, -- 예: rsaEncryption
privateKey OCTET STRING -- PKCS#1 RSAPrivateKey 또는 다른 키 데이터
- PKCS#10
- 인증서 서명 요청 표준
-----BEGIN CERTIFICATE REQUEST-----
로 시작함
- PKCS#12
- 개인 정보 교환 구문 표준
- 인증서, 개인 키, CA 체인을 하나의 암호화된 파일에 저장.
- 바이너리 포멧
인증서 체인
대부분의 인증서는 RootCA, IntermediateCA 를 기반으로 보안성, 관리성을 위해 체인 형태로 제공된다.
실제 End-entity Certificate(Leaf Certificate)
파일을 openssl
명령어로 출력하면 아래와 같은데
openssl x509 -in _.tistory.com.pem -text -noout
# Certificate:
# Data:
# Version: 3 (0x2)
# Serial Number:
# 0c:bd:1f:4c:fc:57:68:e7:92:4e:32:d2:2b:7d:c2:0f
# Signature Algorithm: sha256WithRSAEncryption
# Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=Thawte TLS RSA CA G1
# Validity
# Not Before: Mar 4 00:00:00 2025 GMT
# Not After : Mar 30 23:59:59 2026 GMT
# Subject: C=KR, ST=Jeju-do, L=Jeju-si, O=Kakao Corp., CN=*.tistory.com
# Subject Public Key Info:
# Public Key Algorithm: rsaEncryption
# Public-Key: (2048 bit)
# Modulus:
# 00:8d:f3:6f:64:5d:94:72:bf:8e:0b:58:5c:f7:2c:
# ...
# e2:61
# Exponent: 65537 (0x10001)
# X509v3 extensions:
# X509v3 Authority Key Identifier:
# A5:8C:FE:32:CC:EB:0F:2C:D4:19:C6:08:B8:00:24:88:5D:C3:C5:B7
# X509v3 Subject Key Identifier:
# B6:CB:E6:47:D0:60:C3:CE:F3:C5:85:92:AA:6D:81:99:10:99:78:23
# X509v3 Subject Alternative Name:
# DNS:*.tistory.com, DNS:tistory.com
# X509v3 Certificate Policies:
# Policy: 2.23.140.1.2.2
# CPS: http://www.digicert.com/CPS
# X509v3 Key Usage: critical
# Digital Signature, Key Encipherment
# X509v3 Extended Key Usage:
# TLS Web Server Authentication, TLS Web Client Authentication
# X509v3 CRL Distribution Points:
# Full Name:
# URI:http://cdp.thawte.com/ThawteTLSRSACAG1.crl
# Authority Information Access:
# OCSP - URI:http://status.thawte.com
# CA Issuers - URI:http://cacerts.thawte.com/ThawteTLSRSACAG1.crt
# X509v3 Basic Constraints: critical
# CA:FALSE
# CT Precertificate SCTs:
# Signed Certificate Timestamp:
# Version : v1 (0x0)
# Log ID : 96:97:64:BF:55:58:97:AD:F7:43:87:68:37:08:42:77:
# E9:F0:3A:D5:F6:A4:F3:36:6E:46:A4:3F:0F:CA:A9:C6
# Timestamp : Mar 4 00:09:58.545 2025 GMT
# Extensions: none
# Signature : ecdsa-with-SHA256
# 30:45:02:21:00:D1:26:55:02:8F:84:2E:97:A4:69:06:
# ...
# 22:DE:F9:E0:5D:DF:10
# Signed Certificate Timestamp:
# Version : v1 (0x0)
# Log ID : 64:11:C4:6C:A4:12:EC:A7:89:1C:A2:02:2E:00:BC:AB:
# 4F:28:07:D4:1E:35:27:AB:EA:FE:D5:03:C9:7D:CD:F0
# Timestamp : Mar 4 00:09:58.527 2025 GMT
# Extensions: none
# Signature : ecdsa-with-SHA256
# 30:44:02:20:62:9C:4D:27:A9:A2:57:B5:17:F4:21:AC:
# ...
# D0:92:D0:5E:2B:A1
# Signed Certificate Timestamp:
# Version : v1 (0x0)
# Log ID : 49:9C:9B:69:DE:1D:7C:EC:FC:36:DE:CD:87:64:A6:B8:
# 5B:AF:0A:87:80:19:D1:55:52:FB:E9:EB:29:DD:F8:C3
# Timestamp : Mar 4 00:09:58.548 2025 GMT
# Extensions: none
# Signature : ecdsa-with-SHA256
# 30:44:02:20:53:1A:08:2A:88:F4:CA:80:38:5E:3B:33:
# ...
# 3D:2F:84:F0:63:43
# Signature Algorithm: sha256WithRSAEncryption
# Signature Value:
# 62:cf:3c:47:aa:92:6d:8c:b1:e4:60:df:a6:ac:1b:d0:18:9c:
# ...
# d1:4b:50:81
인증서 하나는 issure
(서명자) 와 subject
(주제) 로 구성된다.
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=Thawte TLS RSA CA G1
Subject: C=KR, ST=Jeju-do, L=Jeju-si, O=Kakao Corp., CN=*.tistory.com
서버는 SSL 핸드셰이크(Handshake) 과정중에 전체 인증서 체인을 제공해야한다.
IntermeidateCA
인증서가 누락될 경우 클라이언트는 인증서 체인을 완성할 수 없어 검증에 실패하게 된다.
클라이언트는 ServerCA
, IntermediaCA
를 순서대로 받으며 서명을 검증하고 최종적으로 신뢰 저장소에 있는 RootCA
를 통해 모든 인증서는 검증한다.
아래 명령을 통해 인증서 체인 목록을 확인할 수 있다.
openssl s_client -connect google.com:443 -showcerts
#Connecting to 142.250.206.206
#CONNECTED(00000005)
#depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R4
#verify return:1
#depth=1 C=US, O=Google Trust Services, CN=WE2
#verify return:1
#depth=0 CN=*.google.com
#verify return:1
#---
#Certificate chain
# 0 s:CN=*.google.com
# i:C=US, O=Google Trust Services, CN=WE2
# a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA256
# v:NotBefore: Mar 31 08:54:37 2025 GMT; NotAfter: Jun 23 08:54:36 2025 GMT
#-----BEGIN CERTIFICATE-----
#MIINZDCCDQmgAwIBAgIRANBmClal7OtcCYWduPzonj0wCgYIKoZIzj0EAwIwOzEL
#...
#Y8ukaMiA4vzXMLEIXueiK1Acw54EZnxp
#-----END CERTIFICATE-----
# 1 s:C=US, O=Google Trust Services, CN=WE2
# i:C=US, O=Google Trust Services LLC, CN=GTS Root R4
# a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA384
# v:NotBefore: Dec 13 09:00:00 2023 GMT; NotAfter: Feb 20 14:00:00 2029 GMT
#-----BEGIN CERTIFICATE-----
#MIICnjCCAiWgAwIBAgIQf/Mta0CdFdWWWwWHOnxy4DAKBggqhkjOPQQDAzBHMQsw
#...
#ONo=
#-----END CERTIFICATE-----
# 2 s:C=US, O=Google Trust Services LLC, CN=GTS Root R4
# i:C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
# a:PKEY: id-ecPublicKey, 384 (bit); sigalg: RSA-SHA256
# v:NotBefore: Nov 15 03:43:21 2023 GMT; NotAfter: Jan 28 00:00:42 2028 GMT
#-----BEGIN CERTIFICATE-----
#MIIDejCCAmKgAwIBAgIQf+UwvzMTQ77dghYQST2KGzANBgkqhkiG9w0BAQsFADBX
#...
#vepuoxtGzi4CZ68zJpiq1UvSqTbFJjtbD4seiMHl
#-----END CERTIFICATE-----
#---
#Server certificate
#subject=CN=*.google.com
#issuer=C=US, O=Google Trust Services, CN=WE2
#---
#No client certificate CA names sent
#Peer signing digest: SHA256
#Peer signature type: ECDSA
#Server Temp Key: X25519, 253 bits
#---
#SSL handshake has read 5315 bytes and written 401 bytes
#Verification: OK
#---
#New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
#Protocol: TLSv1.3
#Server public key is 256 bit
#This TLS version forbids renegotiation.
#Compression: NONE
#Expansion: NONE
#No ALPN negotiated
#Early data was not sent
#Verify return code: 0 (ok)
#---
google.com
의 경우 아래와 같이 [Server Cert] -> [Intermediate CA] -> [Root CA]
구조를 가진다.
depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R4
depth=1 C=US, O=Google Trust Services, CN=WE2
depth=0 CN=*.google.com