[Spring Boot] SSL 인증서 적용하기

김희정·2023년 11월 9일
4

Spring

목록 보기
9/18

💎 들어가며

Spring Boot로 만든 애플리케이션에 SSL 인증서를 적용해야하는 이슈가 생겼습니다. 이번 포스팅에서는 PEM 형식의 SSL 인증서를 적용하는 방법에 대해 포스팅하겠습니다.



🎈 1. SSL 인증서 발급받기

localhost 환경에서 테스트 하기 위해 localhost에 인증서를 발급했습니다.

1.1 OpenSSL 설치

설치 URL은 리눅스, 윈도우 별로 설치하시면 됩니다.


1.2 SSL 인증서 및 개인 키 생성

다음 명령을 사용하여 localhost 도메인을 사용하는 SSL 인증서와 개인 키를 생성합니다

$openssl req -x509 -out localhost.pem -keyout localhost-key.pem -newkey rsa:2048 -nodes -sha256 -days 365 -subj "/CN=localhost"

생성된 인증서 및 개인 키를 확인하려면 다음 명령을 사용합니다

$openssl x509 -noout -text -in localhost.pem
$openssl rsa -noout -text -in localhost-key.pem


🎈 2. Issue Tracking

제가 했던 삽질이 도움이 될까 공유합니다.


Issue

첫 시도는 PEM 파일을 Keysotre에 적용하는 것이었습니다.
GPT도 그렇고 구글링도 그렇고 다들 이런 방식으로 알려주더군요.

ChatGPT

# SSL Configuration
server:
  port: 8443
  ssl:
    enabled: true
    key-store: classpath:localhost.pem
    key-store-password: Password
    key-store-type: PEM
    key-alias: tomcat

결과, 아래와 같은 오류가 발생했습니다.

Failed to load keystore type [PEM] with path [file:/Project/target/classes/localhost.pem] due to [PEM not found]

GPT가 말해놓고 답변하길...

Spring Boot는 기본적으로 Java 키 저장소 형식 (JKS)의 인증서를 지원하며 PEM 형식의 인증서를 직접 로드하는 기능은 제공하지 않습니다. 따라서 server.ssl.key-store-type를 "PEM"으로 설정하면 "PEM not found"와 같은 오류가 발생합니다.


Tracking

GPT가 말하는 두가지 대안이 있습니다.

  1. PEM 형식의 인증서를 JKS 형식으로 변환
  2. PEM 형식을 읽을 수 있는 외부 라이브러리 사용 - Bouncy Castle

1) JKS 형식으로 변환 (실패)

우선 JKS 형식으로 변환하는 방식으로 실행합니다.
=> 결론: 괜히 PEM 파일 손상시키지 말자

keystore password was incorrect

특정 Java 버전에는 최신 OpenSSL의 기본 암호 및 비밀번호 해시 알고리즘에 문제가 있는 것 같습니다.

OpenSSL에 다음 매개변수를 추가하여 문제를 해결했습니다. -certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -macalg sha1

openssl pkcs12 -export -in '.\server.cer' -inkey .\server.key -out .\server.merged.pfx -certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -macalg sha1

keytool 오류

$ openssl pkcs12 -export -out localhost.p12 -inkey localhost-key.pem -in localhost.pem
$ keytool -importkeystore -srckeystore localhost.p12 -destkeystore localhost.jks -srcstoretype PKCS12

keytool 오류: java.io.IOException: parseAlgParameters failed: ObjectIdentifier() -- data isn't an object ID (tag = 48)

What the...
그밖에도 수많은 오류가 있어 패스


2) Bouncy Castle 라이브러리 사용 (실패)

Bouncy Castle 라이브러리 사용 SSL Configuration 정의합니다.

GPT가 추천해준 두번째 라이브러리 Import 방식으로 진행했습니다.

먼저 Spring Boot 프로젝트에 Bouncy Castle 라이브러리를 추가해야 합니다. Maven을 사용하는 경우, pom.xml 파일에 다음 종속성을 추가합니다

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.68</version> <!-- 현재 버전을 업데이트하세요 -->
</dependency>

그 뒤 Pem파일 읽는 코드를 작성하는데, PEMParser, PEMKeyPair 등 클래스를 찾을 수 없었습니다.

public class PemFileReader {
    public static KeyPair readPemFile(String pemFilePath) throws Exception {
        try (FileReader fileReader = new FileReader(pemFilePath);
             PemReader pemReader = new PemReader(fileReader)) {

            PemObject pemObject = pemReader.readPemObject();
            PEMParser pemParser = new PEMParser(pemObject.getContent());
            PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject();

            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            return converter.getKeyPair(pemKeyPair);
        }
    }
}

3. Solution

resources 폴더 아래 public-keyprivate-key를 두고, 경로를 classpath로 설정합니다.

# SSL Configuration
server:
  port: 8443
  ssl:
    enabled: true
    certificate: classpath:pem/localhost.pem
    certificate-private-key: classpath:pem/localhost-key.pem

certificate 옵션을 이용하면 PEM파일을 바로 적용할 수 있습니다.


💎 Reference


💎 마치며

이번 포스팅에서는 Spring Boot 에 PEM 형식의 SSL 인증서를 적용하는 방법에 대해 알아보았습니다.

profile
Java, Spring 기반 풀스택 개발자의 개발 블로그입니다.

0개의 댓글