에러메시지
javax.net.ssl.SSLHandshakeException:
java.security.cert.CertPathValidatorException:
Trust anchor for certification path not found.
SSLHandshakeException, CertPathValidatorException
서버 인증서가 만료 되어서 백엔드팀에서 새 ssl 인증서를 발급했다.
그 뒤부터 SSLHandshakeException 이 발생하였다
백엔드와 함께 문제를 찾으면서 프론트에서 해줄 것이 없는지 찾아보았다.
SSLHandshakeException 에러가 뜨는 이유
- 알 수 없는 인증 기관
- 자체 서명된 서버 인증서
- 누락된 중간 인증 기관
해결방법
백엔드와 확인해본 결과 위 세 개는 아닌 것 같다고 했지만 원인 파악이 어려웠다.
하지만 api 통신 테스트는 계속 진행해야했고 신뢰할 수 있는 인증서로 설정하기로 했다.
AndroidManifest에 네트워크 구성 파일 사용 설정
AndroidManifest.xml
<manifest>
<application
android:networkSecurityConfig="@xml/network_security_config">
...
</application>
</manifest>
네트워크 구성 파일 만들기
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="@raw/인증서 파일"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
<domain-config>
<domain includeSubdomains="true">서브 도메인 주소 (ex. google.com)</domain>
<trust-anchors>
<certificates src="@raw/인증서 파일"/>
</trust-anchors>
</domain-config>
</network-security-config>
base-config : 앱 전체 맞춤설정
domain-config : 도메인별 맞춤설정
인증서 파일 이름을 넣을 때는 확장자 없이 이름만 넣으면 된다.
인증서 넣기
res/raw/인증서 파일
서버에 설정된 인증서 파일을 프로젝트에 넣어야한다
raw 폴더에 자체 서명 또는 비공개 CA 인증서를 PEM 또는 DER 형식으로 넣는다
테스트 하기
SSLHandshakeException이 발생하지 않는지 테스트해본다
신뢰할 수 있는 인증서로 설정해두어서 문제 없이 통신이 진행된다
문제를 찾으면서 의심했던 것
프로젝트의 미니멈 api가 23으로 잡혀 있다
TLS 1.3은 29부터 지원이니 그 문제 인가 의심했다.
하지만 갱신 전에도 tls 1.3이었지만 잘 돌아가고 29 이상의 운영체제가 설치 되어있으면 자동으로 1.3을 지원한다고 했다.
테스트하는 기기가 29 이상이라 이 문제는 아니라고 판단했다.
마지막 이야기
ssl 인증서 만들면서 포트가 빠졌다고 하셨나 뭔가 빼먹으신게 있어서 에러가 발생한 거라는 답을 들었다.
인증서를 다시 만든 후 배포한 서버에서는 신뢰할 수 인증서를 해제 해도 정상 동작되었다.
참고 자료
키워드
Android, kotlin, Retrofit, SSLHandshakeException, CertPathValidatorException, Trust anchor