Root 인증서

키 생성

루트 인증서(=Root CA)는 “서버 인증서를 서명해주는 최상위 발급자”이다. rootCA.key는 절대 유출되면 안되므로, 서버에 올리지 않는다.

openssl genrsa -out rootCA.key 4096
  • genrsa: RSA 개인키(private key) 생성

  • -out rootCA.key: 결과를 rootCA.key 파일로 저장

  • 4096: 키 길이(bit). RSA는 2048도 많이 쓰지만, 4096은 더 무겁고(연산 느림) 대신 여유 있음

개인키는 파일 권한을 잠그는게 좋다:

chmod600 rootCA.key

CSR 생성 및 인증서 발급

openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt \ -subj "/C=KR/ST=Seoul/L=Seoul/O=Hahamia/OU=blog/CN=hahamia Root CA"
  • req: CSR(인증서 서명 요청) 생성하거나 서명된 인증서 발급

  • new: 새 인증서 요청 생성

  • x509: CSR이 아니라 자체 서명(Self-signed) 인증서를 바로 만든다

  • nodes: 비밀번호 없이 키를 저장

  • key rootCA.key: 위에서 만든 루트 개인키로 서명

  • sha256: 서명 해시 알고리즘을 SHA-256으로 사용

  • days 3650: 인증서 유효기간. 여기서는 3650일이므로 10년이다.

  • out rootCA.crt: 결과 인증서 파일

  • subj "...": 인증서의 Subject(DN) 필드를 한 줄로 지정

  • subj 세부 필드

    • C=: 국가(ISO 2자리)
    • ST=: 시/도 이름
    • L=: 도시/지역
    • O=: 조직(회사/팀)
    • OU=: 조직 단위(부서/프로젝트)
    • CN=: 발급기관 이름 (식별할 이름 지정)
      • 도메인 매칭은 Root CA에서 하는 게 아니라, 서버 인증서에서 한다.

subj 를 별도로 입력하지 않는 경우 아래와 같이 사용자 입력을 받게 된다

  • Country Name : KR

  • State or Province Name (full name) : Seoul

  • Locality Name (eg, city) [Default City]: Seoul

  • Organization Name: (eg, company) [Default Company Ltd] : B

  • Organizational Unit Name(eg, section) [] : B

  • Common Name : *.hahamia.net

  • Email Addresss: B

생성된 RootCA 인증서 내용을 아래 명령어로 확인한다.

openssl x509 -in rootCA.crt -text-noout
  • x509: X.509 인증서 조작/출력

  • in rootCA.crt: 입력 인증서

  • text: 사람이 읽을 수 있게 상세 출력

  • noout: PEM 원문 출력은 생략(텍스트만)


서버 인증서

서버 인증서(leaf)는 서버 개인키 + CSR + Root CA 서명으로 만든다. 그리고 요즘은 CN만으로 도메인 매칭을 하지 않고 SAN(Subject Alternative Name) 을 필수로 본다. (브라우저/대부분 TLS 스택이 SAN을 기준으로 검증)

서버 키 생성

openssl genrsa -out server.key 4096
  • genrsa: RSA 서버 개인키 생성

  • -out server.key: 서버 개인키 파일

  • 4096: 키 길이(bit)

CSR 생성 (SAN 포함 권장)

openssl req -new -key server.key -out server.csr \
-subj"/C=KR/ST=Seoul/L=Seoul/O=Hahamia/OU=blog/CN=*.hahamia.net" \
-addext"subjectAltName=DNS:*.hahamia.net,DNS:hahamia.net"
  • req: CSR 생성

  • -new: 새 CSR 생성

  • -key server.key: CSR에 포함될 공개키의 원본(개인키에서 파생)

  • out server.csr: CSR 출력 파일

  • -subj: Subject(DN)

  • -addext "subjectAltName=...": SAN 추가

    • *.hahamia.net만 넣으면 hahamia.net 루트 도메인은 매칭이 안 되므로 필요한 경우 둘 다 넣는다
    • -addext가 없는 OpenSSL이라면 server.ext 파일을 만들어 서명 단계에서 SAN을 넣는 방식으로 처리할 수 있다.

💡 CN은 인증서의 이름이자 도메인이고, SAN은 허용되는 도메인의 리스트이다. 요즘 브라우저에서는 SAN을 기준으로 검증하므로 SAN을 반드시 추가하는 것이 좋다.


Root CA로 서버 인증서 서명

이제 CSR에 Root CA로 서명해서 서버 인증서를 만든다.

openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key \
  -CAcreateserial -out server.crt -days 3650 -sha256 -extfile server.ext
  • x509 -req: CSR을 입력으로 받아 인증서를 발급

  • -in server.csr: CSR 입력

  • -CA rootCA.crt: 서명에 사용할 CA 인증서

  • -CAkey rootCA.key: 서명에 사용할 CA 개인키

  • -CAcreateserial: CA 시리얼 파일(rootCA.srl)이 없으면 생성

  • -out server.crt: 발급된 서버 인증서

  • -days 3650: 유효기간

  • -sha256: 서명 해시 알고리즘

  • -extfile server.ext: SAN 적용을 위해 ext 파일을 따로 만들어둔 경우

생성된 서버 인증서 내용을 확인한다:

openssl x509 -in server.crt -text -noout

체인 검증 테스트

서버 인증서가 Root CA로 정상 검증되는지 바로 확인할 수 있다.

openssl verify -CAfile rootCA.crt server.crt

💡

  • 브라우저에서 “안전함”으로 보이려면: 서버에 server.crt를 적용하는 것만으로는 부족하고, 클라이언트(OS/브라우저)에 rootCA.crt를 “신뢰하는 루트 인증서”로 설치해야 한다.
  • Root CA는 서버에 두지 않는 게 기본: 서버는 server.key + server.crt만 있으면 된다. Root CA는 별도 보관하고 필요할 때만 서명용으로 꺼내는 방식이 안전하다.