証明書一枚を四つに分けて読む
한국어 원문으로 표시합니다.
목표
자체 CA 로 서버 인증서를 발급하고, 사슬·유효기간·SAN·키 일치를 각각 openssl 로 검증합니다. 중간 CA 를 세워 fullchain 을 조립하고 이름 검사 결과를 표로 남깁니다.
왜 중요한가
인증서 장애는 넷 중 하나입니다 — 사슬이 끊겼거나, 만료됐거나, 이름이 다르거나, 키가 짝이 아니거나. 고치는 법이 전부 달라서 어느 것인지 먼저 읽어야 합니다. 이 실습은 그 네 가지를 고의로 만들고 검증기가 무엇이라고 말하는지 봅니다. 특히 OpenSSL 3.0 의 x509 -req 가 CSR 의 확장을 기본으로 버린다는 사실은 발급이 성공한 것처럼 보이는 함정이라 직접 겪어 두는 편이 낫습니다.
단계
/root/pki/ca.key와 자기 서명 인증서/root/pki/ca.crt를 만드세요. 주체는CN=Lab Root CA, 유효기간 30일입니다.- 서버 키
/root/pki/server.key와 CSR/root/pki/server.csr을 만드세요. 주체CN=www.lab.internal, SAN 은DNS:www.lab.internal과DNS:api.lab.internal두 개입니다. - CA 로 서명해
/root/pki/server.crt를 만드세요. 유효기간은 3일, SAN 이 인증서에 남아 있어야 합니다. server.crt의 일련번호·만료일·SHA-256 지문·SAN 을/root/pki/04-fields.txt에 저장하세요.- 비교용 키
/root/pki/other.key를 하나 더 만들고,/root/pki/05-keymatch.txt에cert=·key=·other=세 줄(각 공개키 PEM 의 sha256 64자리)과verdict=match를 적으세요. /root/pki/06-expiry.txt에openssl x509 -enddate의 출력 줄과renew_within_7d=yes|no를 적으세요. 판정은-checkend 604800의 종료 코드로 합니다.- 중간 CA(
/root/pki/inter.key,/root/pki/inter.crt,CN=Lab Intermediate CA, CA:TRUE)를 루트로 서명해 만들고, 그 중간 CA 로 리프/root/pki/api.crt(키/root/pki/api.key, SANDNS:api.lab.internal)를 발급하세요. 리프와 중간 CA 를 이 순서로 이어/root/pki/fullchain.pem을 만드세요. server.crt에 대해www.lab.internal·api.lab.internal·other.lab.internal세 이름의 검증 결과를/root/pki/08-hostname.txt에이름=OK|FAIL로 적으세요.
참고
- 키 생성:
openssl genrsa -out <파일> 2048. 자기 서명:openssl req -x509 -new -key ... -days ... -subj .... - CSR 에 SAN:
openssl req -new ... -addext "subjectAltName=DNS:a,DNS:b". 서명 때 확장 유지:openssl x509 -req ... -copy_extensions copy. - 중간 CA 에는
-extfile로basicConstraints=critical,CA:TRUE,pathlen:0과keyUsage=critical,keyCertSign,cRLSign을 주세요. - 이름 검사:
openssl verify -CAfile ca.crt -verify_hostname <이름> server.crt. - 흔한 실수: 3단계에서
-copy_extensions copy를 빠뜨리면 발급은 되는데 SAN 이 사라집니다. 7단계에서 리프를 루트로 직접 서명하면 사슬이 아닙니다.
루트 CA 만들기
/root/pki/ca.key 와 자기 서명 /root/pki/ca.crt(CN=Lab Root CA, 30일)를 만드세요.
req 에 -x509 를 주면 CSR 대신 자기 서명 인증서가 나옵니다. 발급자와 주체가 같고 basicConstraints 가 CA:TRUE 인지 openssl x509 -text 로 확인하세요.
SAN 이 든 CSR
/root/pki/server.key 와 /root/pki/server.csr(CN=www.lab.internal, SAN 두 개)을 만드세요.
-newkey rsa:2048 -nodes -keyout 으로 키와 CSR 을 한 번에 만들 수 있습니다. SAN 은 -addext 로 넣고 openssl req -in server.csr -noout -text 에서 Subject Alternative Name 을 확인하세요.
3일짜리 서버 인증서 발급
CA 로 서명해 /root/pki/server.crt(3일, SAN 유지)를 만드세요.
x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3 이 뼈대입니다. 발급 뒤 openssl x509 -in server.crt -noout -ext subjectAltName 이 비어 있으면 CSR 의 확장이 버려진 것입니다 — 그걸 옮기는 옵션이 있습니다.
식별값 읽기
server.crt 의 일련번호·만료일·SHA-256 지문·SAN 을 /root/pki/04-fields.txt 에 저장하세요.
x509 에 -serial -enddate -fingerprint -sha256 -ext subjectAltName 을 한꺼번에 줄 수 있습니다. 채점기는 같은 인증서에서 값을 다시 계산해 대조합니다.
키가 짝인지 판정하기
/root/pki/other.key 를 만들고 /root/pki/05-keymatch.txt 에 cert=·key=·other=(공개키 PEM 의 sha256)와 verdict=match 를 적으세요.
인증서의 공개키는 x509 -pubkey, 개인키의 공개키는 pkey -pubout 으로 같은 PEM 형식이 나옵니다. | sha256sum | cut -d' ' -f1 으로 64자리만 남기세요. cert 와 key 가 같고 other 만 달라야 합니다.
7일 창으로 만료 판정
/root/pki/06-expiry.txt 에 -enddate 출력 줄과 renew_within_7d=yes|no 를 적으세요.
-checkend 604800 은 7일(604800초) 안에 만료되면 0 이 아닌 코드로 끝납니다. if 문으로 받아 yes/no 를 정하세요. 3일짜리 인증서라면 답은 정해져 있습니다.
중간 CA 와 fullchain
루트가 서명한 중간 CA(inter.key/inter.crt, CN=Lab Intermediate CA, CA:TRUE)를 만들고, 그것으로 리프 api.crt(SAN api.lab.internal)를 발급한 뒤 리프+중간 순서로 /root/pki/fullchain.pem 을 만드세요.
중간 CA 의 CSR 을 루트로 서명할 때 -extfile 에 basicConstraints=critical,CA:TRUE,pathlen:0 과 keyUsage=critical,keyCertSign,cRLSign 을 주세요. 리프는 -CA inter.crt -CAkey inter.key 로 서명합니다. openssl verify -CAfile ca.crt api.crt 는 실패하고 -untrusted inter.crt 를 주면 통과해야 진짜 사슬입니다.
이름 검사 표
server.crt 에 대해 www·api·other 세 이름의 -verify_hostname 결과를 /root/pki/08-hostname.txt 에 이름=OK|FAIL 로 적으세요.
이름 검사는 SAN 의 dNSName 과 대조합니다. CN 에 있어도 SAN 에 없으면 실패합니다. 세 이름을 for 로 돌리며 종료 코드로 OK/FAIL 을 정하세요.