본문 바로가기

서버 리뷰

[Network/Java] OpenSSL 검증 코드와 Java PKIX 에러 매핑 완벽 정리

728x90

웹 애플리케이션을 개발하거나 방화벽(SSL Inspection) 환경을 구축할 때 가장 자주 마주치는 에러 중 하나가 바로 자바(Java)의 PKIX path building failed입니다.

이 에러는 네트워크 단에서 OpenSSL을 통해 테스트했을 때 출력되는 Verify return code와 밀접한 연관이 있습니다. 하지만 OpenSSL은 직관적인 숫자 코드를 반환하는 반면, 자바는 복잡한 스택 트레이스 문장으로 에러를 표현하기 때문에 매칭하기가 쉽지 않습니다.

실무에서 발생하는 주요 OpenSSL 검증 코드 6가지가 자바 내부에서 각각 어떤 예외(Exception)로 변환되는지 명확하게 정리해 보겠습니다.


1. Java에서 PKIX path building failed를 유발하는 코드

이 그룹의 공인된 특징은 인증서의 상위 뿌리를 찾아 올라가는 계층 경로(Path)가 끊어졌다는 점입니다. 자바의 인증서 경로 검증 엔진은 이 체인을 조립하는 데 실패하면 예외 없이 PKIX path building failed를 던집니다.

Code 1 : unable to get issuer certificate (중간 인증서 누락)

  • 원인: 서버 측에서 인증서 체인을 전송할 때, Root CA와 실제 서버 인증서 사이를 이어주는 중간 관리자 인증서(Intermediate CA)를 누락하고 보낸 경우입니다. (서버 관리자의 설정 미숙)
  • Java의 반응: 최상위 Root CA 도장은 클라이언트에 있지만, 중간 다리가 없어서 경로 구축에 실패합니다.
  • Java 에러 메시지: SunCertPathBuilderException: unable to find valid certification path to requested target

Code 19 : self signed certificate in certificate chain (사설 인증서 포함)

  • 원인: 전체 인증서 체인 내부 혹은 중간에 인증 기관의 공인 서명이 아닌, 개인이 임의로 만든 사설(Self-Signed) 인증서가 끼어들어 온 경우입니다. 방화벽의 SSL 가로채기(SSL Inspection)가 동작할 때 가장 핵심적으로 발생하는 현상입니다.
  • Java의 반응: 경로 끝에 신뢰할 수 없는 사설 CA가 존재하므로 보안 경로 구축을 거부합니다.
  • Java 에러 메시지: SunCertPathBuilderException: unable to find valid certification path to requested target

Code 20 : unable to get local issuer certificate (Root CA를 찾을 수 없음)

  • 원인: 서버가 인증서 체인을 정상적으로 전송했으나, 그 최상위 발급 주체인 Root CA가 클라이언트 PC(또는 자바 내부의 cacerts 보관소)에 등록되어 있지 않은 경우입니다.
  • Java의 반응: 신뢰할 수 있는 기관 목록에 없는 발급자이므로 경로 검증 단계에서 세션을 차단합니다.
  • Java 에러 메시지: SunCertPathBuilderException: unable to find valid certification path to requested target

2. 날짜 및 시간 오류로 인한 Java 에러

인증서의 기간 만료나 효력 시작 시점의 오류는 자바가 계층 구조(Path)를 따지기 전인 날짜 유효성 검증 단계에서 먼저 쳐내기 때문에 PKIX path 문구가 나오지 않고 전용 예외가 발생합니다.

Code 9 : certificate is not yet valid (효력 시작 전)

  • 원인: 인증서를 새로 발급받아 교체했으나, 클라이언트 PC의 현재 시간이 실제 시간보다 과거로 설정되어 있거나 서버 간의 시차가 뒤틀려 발생합니다.
  • Java의 반응: 아직 효력이 발생하지 않은 인증서로 판단하여 즉시 거부합니다.
  • Java 에러 메시지: java.security.cert.CertificateNotYetValidException

Code 10 : certificate has expired (인증서 만료)

  • 원인: 사이트 관리자가 인증서 갱신 주기를 놓쳤거나, 반대로 클라이언트 PC의 현재 시간이 과거로 잘못 설정되어 실제 만료일을 지난 것으로 인식하는 경우입니다.
  • Java의 반응: 유효 기간이 만료된 유령 인증서로 판단하여 연결을 끊습니다.
  • Java 에러 메시지: java.security.cert.CertificateExpiredException

3. 도메인 불일치로 인한 Java 에러

인증서 자체는 글로벌 공인 기관에서 발급한 정상 제품이고 날짜도 올바르지만, 클라이언트가 접속한 주소와 인증서에 명시된 주소가 다를 때 발생합니다.

Code 62 : Hostname mismatch (호스트 네임 불일치)

  • 원인: 예를 들어 주소창에는 update4.alyac.com을 입력하여 접속했는데, 실제 서버가 응답으로 보여준 인증서의 CN(Common Name) 혹은 SAN(Subject Alternative Name) 속성에는 naver.com 같은 엉뚱한 도메인이 적혀있는 경우입니다. 피싱 사이트로 유도되었거나 방화벽 라우팅이 꼬였을 때 나타납니다.
  • Java의 반응: 인증서 계층 구조 조립은 정상 통과(PKIX 통과)하지만, 마지막 호스트 대조 단계에서 차단합니다.
  • Java 에러 메시지: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <도메인> doesn't match any of the subject alternative names

요약 가이드라인

OpenSSL Verify Code 의미 Java 최종 에러 형태
Code 1 중간 인증서 누락 PKIX path building failed
Code 19 사설 인증서 감지 (방화벽 개입) PKIX path building failed
Code 20 신뢰할 수 없는 고유 Root CA PKIX path building failed
Code 9 인증서 효력 시작 전 CertificateNotYetValidException
Code 10 인증서 만료됨 CertificateExpiredException
Code 62 도메인 이름 미스매치 SSLPeerUnverifiedException

결과적으로 자바 프로그램 개발 및 인프라 운영 중 PKIX path building failed 메시지를 마주했다면, 원인은 오직 1번, 19번, 20번 세 가지 구조적 경로 문제 중 하나로 압축할 수 있습니다.

이를 명확히 구분하기 위해 OpenSSL 명령어로 교차 검증을 수행하면, 서버 측의 인증서 누락 문제인지 아니면 사내 보안 장비(방화벽)의 SSL 가로채기 문제인지 정확하게 판별해 낼 수 있습니다.

반응형