SSLHandshakeException 관련 오류

2024. 1. 25. 10:07프로그래밍/TroubleShooting

728x90

이러한 오류 중에 다음과 같은 오류가 발생 했습니다.

이 오류는 openstreetmap 을 사용 하기 위해서 뷰어 프로그램을 만들어보다가 발생을 했습니다.

정확한 오류 메시지는 다음과 같습니다.


Failed loading https://c.tile.openstreetmap.org/3/5/2.png:
class javax.net.ssl.SSLHandshakeException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

출처 입력

이 문제에 관련 해서 가만히 생각 해 보면 다음과 같은 의문이 듭니다.

 

내가 요청한 다음 URL 에서 지도 파일(그림)을 다운 받지 못하는가?

인증서가 없거나, 잘못 되었나?

 

그렇다면 우선 인증서 등록 해야 하는 것이 아닐까? 라는 생각이 듭니다. 그래서 인증서를 등록하는 방법들을 다음과 같이 찾아보고 인증서를 등록하였습니다.

하지만 정확하게 내가 어떤 일을 하고 있는 지에 대해서 생각해 본 적이 없는 데, 한 번 정도는 생각해 봐야 할 것 같아서 이렇게 글을 남깁니다.

 

문제의 정의

문제를 먼저 정의하고자 합니다. 이 문제는 일반적인 경우에는 일어 나지 않을 것입니다.

그냥 openstreet.org 서버가이미 모든 클라이언트를 다음과 같이 허용 해 주었을 테니까요

하지만, 만약 내 PC가 내부망에 있다고 한다면, 적어도 다음과 같이 되어 있을 것이라고 생각 합니다.

사실 이때 내 PC는 openstreet.org 를 바로 붙을 수가 없을 것이며, 반드시 Tobee.com 을 거쳐서 붙었을 것이라고 예상 할 수 있습니다. 물론 이 얘기는 개념적인 이야기 입니다. 정확히는 tobee.com 을 가지고 있는 인증서버에서의 인증 일 수 있습니다.

이 경우에는 openstreet.org 에 대한 인증보다는 Tobee.com 의 인증이 더 중요 할 것이라고 봄니다.

그리고 Tobee.com 은 내부에 있는 어떤 컴퓨터 이므로 인증을 해 줄 것이기 때문에 반드시 이 인증 과정을 거쳐야만 할 것 같습니다.

 

인증서의 등록

우선 내가 지금 현재 자바 프로그램을 구동 하고 있다면, 특정 자바 JDK/JRE 를 사용하고 있을 것입니다. 여기서 인증서의 위치를 확인해야 하는 데, 일반적으로 인증서의 위치는 다음 디렉토리에 존재합니다.

%JAVA_HOME%/lib/security/cacerts
 

여기서 JAVA_HOME 은 JRE 혹은 JDK 루트 디렉토리의 위치가 될 것입니다.

여기에 있는 cacerts 파일에 내가 원하는 인증서를 등록 하는 것입니다.

 

기본 인증서의 위치

순서가 좀 잘 못되어 보이긴 하지만, 인증서의 위치가 어디인가에 대해서 생각을 해보게 되었습니다. 실제 인증서의 위치가

%JAVA_HOME%/lib/security/cacerts
 

가 맞는지에 대해서 말이죠...

결론을 말하자면 아니라는 것입니다. 기본 인증서의 위치는 다음 스택오버플로우 답변에 존재 합니다.

리눅스/유닉스 계열의 경우

$HOME/.keystore
 

윈도우즈의 경우

%USERPROFILE%/.keystore
 

라는 것이죠. 그래서 이 기본 인증서 저장소에 해당 이름으로 파일이 존재한다면, 이 파일안에 있는 인증서를 이용할 확률이 높습니다.

오류의 가능성이 있다는 것과 똑같은 말이 됩니다.

 

인증서의 변경 등록

오류의 가능성이 있다는 것은 내가 가지고 있는 Java 버전이 여러개 일때, 문제가 크게 부각 될 것 같습니다. 예를 들어 JDK 1.8, JDK 1.11, JDK 1.19 등등등 말이죠.

그래서 변경 등록 시에 우선 기본 자격증명서 파일을 삭제하거나 이름을 바꾸어 주고 시작하는 것이 우선적으로 해야 할 일일 것 같습니다.

  1. 기본 저장소 디렉토리 변경
  2. 현재 저장소 변경 등록

순으로 진행 해야 할 것 입니다.

 

변경 등록에 대해서, 만약 openstreetmap.org 사이트에 대해서 실행해 보면 두개의 사이트 인증서가 서버에서 내려 오는 데요.

예를 들어서 다음과 같은 것이 표현 될 것입니다.

D:\DEV\IDE\JDK\openjdk\jdk-17.0.2\registerCert>java -cp ./ com.tobee.util.InstallCert openstreetmap.org
Loading KeyStore jssecacerts...
Opening connection to openstreetmap.org:443...
Starting SSL handshake...

No errors, certificate is already trusted

Server sent 2 certificate(s):

 1 Subject CN=api.openstreetmap.org
   Issuer  CN=SKEnS, O=SKEnS, C=KR
   sha1    8c 6f e3 ef 16 23 58 e1 1e 8f d5 38 4e cc 0c 08 44 48 42 ab
   md5     e2 56 b4 67 c6 a5 56 66 24 27 0a 12 f4 3c 10 21

 2 Subject CN=Tommybee, O=Tommybee, C=KR
   Issuer  CN=Tommybee, O=Tommybee, C=KR
   sha1    4e df 6c b3 0c 53 bc 0b c2 70
   md5     ef 47 ce 1e 60 6c 1c 4a 51 ee a9 6c

Enter certificate to add to trusted keystore or 'q' to quit: [1]
2
 

자 그럼 여기서 어떤 인증서를 선택해야 하는 것인가? 라는 문제가 생깁니다. 지극히 개인적인 의견이지만, api.openstreetmap.org 의 경우에는 지도 서비스를 할 수 있도록 이미 모든 준비를 마친 서버 일 것입니다.

1 Subject CN=api.openstreetmap.org
 

따라서 위의 사이트는 등록할 이유가 없을 것입니다.

하지만, 그 다음 사이트의 경우, 인증서가 하나 더 내려 온 것으로 확인이 된다고 밖에 생각 할 수가 없는 경우 입니다.

 2 Subject CN=Tommybee, O=Tommybee, C=KR
 

예를 들면, 중간에 서버 인증서가 하나 더 있는 느낌이라는 것이죠.

그래서, 2번을 선택해 주어야 한다는 것입니다.

최종적으로 jssecacerts 라는 파일에 다음과 같이 저장 되었다는 메시지를 확인 할 수 있습니다.

Added certificate to keystore 'jssecacerts' using alias 'openstreetmap.org-2'
 

InstallCert 자바 파일에 내용이 아래처럼 되어 있습니다.

File file = new File("jssecacerts");
if (file.isFile() == false) {
	char SEP = File.separatorChar;
	File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");
	file = new File(dir, "jssecacerts");
	if (file.isFile() == false) {
		file = new File(dir, "cacerts");
	}
}
...
X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);

OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();
 

 

이를 변경 등록 하기 위해서 다음 일련의 명령어를 사용 해서 내가 사용하는 JDK 설치 위치에 저장 할 수 있을 것입니다.

~\openjdk\jdk-17.0.2\registerCert>keytool -exportcert -keystore jssecacerts -storepass changeit -file output.cert -alias openstreetmap.org-2
Certificate stored in file <output.cert>
~\openjdk\jdk-17.0.2\registerCert>keytool -importcert -cacerts -storepass changeit -file output.cert -alias Tommybee
...
Trust this certificate? [no]:  y
Certificate was added to keystore
 

이클립스 저장소 등록

참고로 이클립스의 경우, 다음과 같이 이클립스 구동 전에 저장소의 위치와 암호가 적용 되도록 설정 해 주었습니다.

-Djavax.net.ssl.trustStore="~/jdk-17.0.2/lib/security/cacerts "
-Djavax.net.ssl.trustStorePassword="changeit"
 

이상.

728x90