info

Spring Boot에서 Jasypt를 사용하면 application.properties 또는 application.yml에 저장되는 DB 접속 정보, API Key, 외부 연동 비밀번호 등을 암호화하여 관리할 수 있다.
핵심은 설정 파일에는 암호화된 값만 저장하고, 복호화 키는 소스와 분리해서 운영 환경에서 주입하는 것이다.


🧩 Jasypt란?

Jasypt(Java Simplified Encryption)는 Java 애플리케이션에서 문자열, 프로퍼티 값 등을 쉽게 암호화/복호화할 수 있도록 도와주는 라이브러리이다.

Spring Boot에서는 보통 다음과 같은 민감 정보를 암호화할 때 사용한다.

  • DB URL
  • DB Username
  • DB Password
  • API 인증키
  • 외부 시스템 접속 비밀번호
  • SMTP 계정 정보

❓ 왜 Jasypt를 사용하는가?

일반적인 설정 파일은 아래처럼 평문으로 관리되는 경우가 많다.

spring.datasource.url=jdbc:postgresql://10.10.10.10:5432/appdb
spring.datasource.username=app_user
spring.datasource.password=1234

이 경우 Git, 배포 파일, 서버 접근 권한을 통해 민감 정보가 노출될 수 있다.

Jasypt를 적용하면 아래처럼 암호화된 값으로 관리할 수 있다.

spring.datasource.url=ENC(암호화된_DB_URL)
spring.datasource.username=ENC(암호화된_사용자명)
spring.datasource.password=ENC(암호화된_비밀번호)

tip

ENC(...)는 “이 값은 암호화된 값이므로 애플리케이션 기동 시 복호화해서 사용하라”는 표시이다.


🔄 Jasypt 적용 흐름

[평문 설정값]
      ↓
[Jasypt 암호화]
      ↓
application.properties에 ENC(...) 형태로 저장
      ↓
Spring Boot 기동 시 복호화 키 주입
      ↓
애플리케이션 내부에서는 복호화된 값으로 사용

📦 의존성 추가

Gradle

dependencies {
    implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'
}

Maven

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>

warning

폐쇄망 환경에서는 외부 저장소에서 직접 다운로드할 수 없으므로, 해당 jar와 의존 라이브러리를 사내 Maven Repository 또는 mavenLocal()에 사전 등록해야 한다.


⚙️ application.properties 설정

기본 설정

jasypt.encryptor.password=${JASYPT_PASSWORD}
jasypt.encryptor.algorithm=PBEWITHHMACSHA512ANDAES_256
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.RandomIvGenerator

DB 설정 암호화 예시

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=ENC(xxxxxxxxxxxxxxxxxxxxxxxxx)
spring.datasource.username=ENC(yyyyyyyyyyyyyyyyyyyyyyyyy)
spring.datasource.password=ENC(zzzzzzzzzzzzzzzzzzzzzzzzz)

🔑 복호화 키 관리 방식

Jasypt에서 가장 중요한 것은 복호화 키를 설정 파일에 직접 넣지 않는 것이다.

❌ 비추천

jasypt.encryptor.password=my-secret-key

이 방식은 설정 파일만 보면 복호화 키까지 같이 노출되므로 보안 효과가 떨어진다.


✅ 추천 1. 환경변수 사용

Linux 서버에서 환경변수로 주입한다.

export JASYPT_PASSWORD='my-secret-key'

애플리케이션 실행:

java -jar app.jar

✅ 추천 2. 실행 옵션으로 주입

java -Djasypt.encryptor.password=my-secret-key -jar app.jar

warning

실행 옵션 방식은 프로세스 목록이나 쉘 히스토리에 노출될 수 있으므로 운영계에서는 주의가 필요하다.


✅ 추천 3. systemd 서비스에 등록

[Unit]
Description=springboot-app

[Service]
User=appuser
Environment="JASYPT_PASSWORD=my-secret-key"
ExecStart=/usr/bin/java -jar /app/app.jar

[Install]
WantedBy=multi-user.target

tip

운영계에서는 systemd, Jenkins Credential, 서버 환경변수 등을 통해 복호화 키를 분리 관리하는 방식이 일반적이다.


🛠 암호화 값 생성 방법

방법 1. 테스트 코드로 암호화

import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.iv.RandomIvGenerator;

public class JasyptEncryptTest {

    public static void main(String[] args) {
        String key = "my-secret-key";
        String plainText = "1234";

        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(key);
        encryptor.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
        encryptor.setIvGenerator(new RandomIvGenerator());

        String encryptedText = encryptor.encrypt(plainText);

        System.out.println(encryptedText);
    }
}

생성된 값을 아래처럼 넣는다.

spring.datasource.password=ENC(생성된_암호문)

방법 2. Spring Bean으로 Encryptor 정의

@Configuration
public class JasyptConfig {

    @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor(
            @Value("${jasypt.encryptor.password}") String password
    ) {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();

        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(password);
        config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
        config.setStringOutputType("base64");

        encryptor.setConfig(config);
        return encryptor;
    }
}

필요 import:

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

warning

암호화할 때 사용한 알고리즘, IV Generator, Salt 설정과 애플리케이션 복호화 설정이 다르면 기동 시 복호화에 실패한다.


🧱 Spring Boot 설정 클래스 예시

@EnableEncryptableProperties
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

jasypt-spring-boot-starter를 사용하면 대부분 자동 설정으로 동작하지만, 명시적으로 설정하고 싶다면 @EnableEncryptableProperties를 사용할 수 있다.


🗄️ DB 정보는 어디까지 암호화해야 할까?

1. Password

DB 비밀번호는 반드시 암호화 대상이다.

spring.datasource.password=ENC(...)

2. Username

운영계 계정명이 민감하거나 내부 정책상 노출되면 안 된다면 암호화한다.

spring.datasource.username=ENC(...)

3. URL

DB 주소, 포트, 서비스명이 내부망 구조를 드러낼 수 있다면 암호화 대상이 될 수 있다.

spring.datasource.url=ENC(...)

tip

금융권, 폐쇄망, 대외비 시스템에서는 URL, username, password 세 가지 모두 암호화하는 방향이 더 안전하다.


🏷️ ENC(...)를 사용하는 이유

ENC(...)는 Jasypt가 해당 값을 암호화된 값으로 인식하기 위한 표식이다.

예를 들어 아래와 같은 설정이 있다고 가정한다.

spring.datasource.password=ENC(Ak3sdf98sdf...)

Spring Boot가 설정 값을 읽을 때 Jasypt는 ENC(...) 안의 값을 복호화한 뒤 실제 datasource 설정에 주입한다.

즉 애플리케이션 내부에서는 아래와 같은 평문 값처럼 동작한다.

1234

하지만 파일에는 암호문만 남는다.


🔍 기존 자체 암호화 모듈과 Jasypt의 차이

구분 자체 암호화 모듈 Jasypt
적용 방식 직접 복호화 코드 작성 프로퍼티 로딩 단계에서 자동 복호화
설정 파일 표기 자체 규칙 ENC(...)
Spring 연동 직접 구현 필요 자동 연동
유지보수 프로젝트별 상이 표준화 가능
보안 키 관리 직접 설계 환경변수/시스템 프로퍼티 연계 쉬움

자체 암호화 모듈도 충분히 사용할 수 있다.
다만 Jasypt는 Spring Boot 설정 로딩 단계에 자연스럽게 통합되는 방식 이라서 datasource, mail, 외부 API 설정 등에 일관되게 적용하기 쉽다.


🚨 운영 배포 시 주의사항

1. 복호화 키는 Git에 올리지 않는다

  
# 금지
jasypt.encryptor.password=my-secret-key

2. 운영/개발 키를 분리한다

local  : local-jasypt-key
dev    : dev-jasypt-key
prod   : prod-jasypt-key

환경별 키가 다르면 같은 평문이라도 암호문이 달라질 수 있다.


3. 키가 바뀌면 기존 암호문은 다시 생성해야 한다

Jasypt 암호문은 복호화 키와 알고리즘에 의존한다.
복호화 키를 변경하면 기존 ENC(...) 값은 복호화되지 않는다.


4. 로그에 복호화된 값이 찍히지 않게 한다

datasource 설정, 환경변수 출력, debug 로그에서 민감 정보가 노출되지 않도록 주의해야 한다.


🧪 Jenkins 배포 시 예시

Jenkins Credential에 키 등록

  • Credential ID: jasypt-password
  • Type: Secret text
  • Value: 운영용 복호화 키

Pipeline 예시

pipeline {
    agent any

    environment {
        JASYPT_PASSWORD = credentials('jasypt-password')
    }

    stages {
        stage('Deploy') {
            steps {
                sh '''
                  java -jar app.jar
                '''
            }
        }
    }
}

warning

Jenkins 콘솔 로그에 JASYPT_PASSWORD가 출력되지 않도록 echo, printenv 사용을 피해야 한다.


🌐 폐쇄망 환경에서의 적용 포인트

폐쇄망에서는 Jasypt 라이브러리를 외부에서 직접 받을 수 없기 때문에 다음 절차가 필요하다.

  1. 외부망에서 Jasypt 관련 jar 다운로드
  2. 의존 라이브러리 함께 수집
  3. 사내 Nexus 또는 로컬 Maven Repository에 등록
  4. 프로젝트 build.gradle 또는 pom.xml에서 내부 저장소 참조
  5. 운영 서버에는 복호화 키만 별도 주입

Maven local 등록 예시

mvn install:install-file \
  -Dfile=jasypt-spring-boot-starter-3.0.5.jar \
  -DgroupId=com.github.ulisesbocchio \
  -DartifactId=jasypt-spring-boot-starter \
  -Dversion=3.0.5 \
  -Dpackaging=jar

🧯 자주 발생하는 오류

1. 복호화 실패

Unable to decrypt property

원인:

  • 복호화 키 불일치
  • 알고리즘 불일치
  • ENC(...) 값 깨짐
  • 운영 서버 환경변수 누락

2. 알고리즘 미지원

Algorithm not available

원인:

  • JDK 보안 정책 문제
  • 알고리즘명 오타
  • JDK 버전 차이

3. 애플리케이션 기동 실패

Failed to bind properties under 'spring.datasource'

원인:

  • DB URL 복호화 실패
  • datasource 값이 정상 문자열로 변환되지 않음
  • ENC() 괄호 누락

📎 실무 권장 구성

  
# Jasypt
jasypt.encryptor.password=${JASYPT_PASSWORD}
jasypt.encryptor.algorithm=PBEWITHHMACSHA512ANDAES_256
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.RandomIvGenerator
  
# Datasource
spring.datasource.url=ENC(...)
spring.datasource.username=ENC(...)
spring.datasource.password=ENC(...)

실행 환경:

운영 서버 / Jenkins / systemd
        ↓
JASYPT_PASSWORD 주입
        ↓
Spring Boot 기동
        ↓
ENC(...) 값 자동 복호화

📌 정리

[!summary] Jasypt는 Spring Boot 설정 파일에 포함되는 민감 정보를 암호화하여 관리하기 위한 실무적인 방법이다.

  • 설정 파일에는 ENC(...) 값만 저장한다.
  • 복호화 키는 Git과 소스에서 분리한다.
  • DB password는 필수 암호화 대상이다.
  • 폐쇄망에서는 jar와 의존성을 사전 반입해야 한다.
  • 운영계에서는 systemd, Jenkins Credential, 환경변수 등을 통해 키를 주입한다.
  • URL, username, password 모두 암호화하면 내부망 구조 노출을 줄일 수 있다.

결국 중요한 것은 단순히 값을 암호화하는 것이 아니라,
암호문과 복호화 키를 서로 다른 경로로 관리하는 운영 구조 를 만드는 것이다.


연결문서

댓글남기기