Blog / Java/Kotlin / Jasypt를 이용한 Spring Boot 프로퍼티 암호화

Jasypt를 이용한 Spring Boot 프로퍼티 암호화

Spring Boot 애플리케이션에서 DB 비밀번호, API Key 등 민감한 프로퍼티를 평문으로 application.yml에 저장하면 보안에 취약하다. **Jasypt(Java Simplified Encryption)**를 사용하면 프로퍼티 값을 암호화된 상태로 저장하고, 런타임에 자동으로 복호화하여 사용할 수 있다.

1. 의존성 추가
kotlin
// build.gradle.kts
dependencies {
    implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5")
}
2. Java Config 작성
kotlin
@Configuration
@EnableEncryptableProperties
class JasyptConfig(
    @Value("\${jasypt.encryptor.password:}") private val encryptorPassword: String
) {
    @Bean("jasyptStringEncryptor")
    fun stringEncryptor(): StringEncryptor {
        val config = SimpleStringPBEConfig().apply {
            password = encryptorPassword
            algorithm = "PBEWithMD5AndDES"
            poolSize = 1
            stringOutputType = "base64"
            setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator")
            setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator")
        }
        return PooledPBEStringEncryptor().apply { setConfig(config) }
    }
}

주요 설정:

  • algorithm — 암호화 알고리즘. PBEWithMD5AndDES는 가장 보편적으로 사용되는 알고리즘
  • poolSize — 암호화 풀 크기. 멀티스레드 환경에서는 늘려주면 좋음
  • RandomSaltGenerator — 같은 평문이라도 매번 다른 암호문이 생성됨

⚠️ jasypt.encryptor.password절대로 소스코드나 yml 파일에 하드코딩하지 않아야 한다. 반드시 VM 옵션이나 환경변수로 전달한다.

3. 암호문 생성

테스트 코드를 작성하여 암호문을 생성한다.

kotlin
@DisplayName("JasyptConfig 암복호화 테스트")
class JasyptConfigTest {

    private lateinit var encryptor: StringEncryptor

    @BeforeEach
    fun setUp() {
        val jasyptConfig = JasyptConfig("mySecretEncKey")
        encryptor = jasyptConfig.stringEncryptor()
    }

    @Test
    @DisplayName("암호화된 문자열을 복호화하면 원문과 동일하다")
    fun decrypt_shouldReturnOriginalPlainText() {
        // given
        val plainText = "myDatabasePassword!@#"
        val encrypted = encryptor.encrypt(plainText)

        // when
        val decrypted = encryptor.decrypt(encrypted)

        // then
        println("평문: $plainText")
        println("암호문: $encrypted")       // ← 이 값을 ENC()에 넣어 사용
        println("복호문: $decrypted")
        assertThat(decrypted).isEqualTo(plainText)
    }
}

테스트를 실행하면 콘솔에 암호문이 출력된다:

text
평문: myDatabasePassword!@#
암호문: Ckfh13n/jh2gUJ2futzT3UyE0yCNB2AQRI5riQ6bWlI=
복호문: myDatabasePassword!@#

💡 RandomSaltGenerator를 사용하므로 동일한 평문을 암호화해도 매번 다른 암호문이 생성된다. 어떤 암호문이든 같은 키로 복호화하면 원문이 복원된다.

4. application.yml에 암호문 적용

출력된 암호문을 ENC()로 감싸서 yml에 삽입한다.

yaml
# application-live.yml
spring:
  datasource:
    url: jdbc:mysql://my-db-host:3306/mydb
    username: ENC(AYMbwzwz6yKQM/YzEKnvng==)
    password: ENC(Ckfh13n/jh2gUJ2futzT3UyE0yCNB2AQRI5riQ6bWlI=)

Jasypt가 ENC() 패턴을 자동으로 감지하여 런타임에 복호화한다. 암호화하지 않은 프로퍼티는 그대로 평문으로 사용된다.

5. 암호화 키 전달
방법 1: VM 옵션
bash
java -Djasypt.encryptor.password=mySecretEncKey -jar app.jar
방법 2: 환경변수
bash
export JASYPT_ENCRYPTOR_PASSWORD=mySecretEncKey
yaml
jasypt:
  encryptor:
    password: ${JASYPT_ENCRYPTOR_PASSWORD}
방법 3: systemd 서비스 파일 (Linux 서버 배포 시)
ini
[Service]
ExecStart=/usr/bin/java \
  -Djasypt.encryptor.password=mySecretEncKey \
  -jar /opt/app/lifelog.jar
6. 적용 시 주의사항
항목 설명
암호화 키 관리 암호화 키는 소스코드에 포함하지 않으며, 배포 환경에서만 주입
키 분실 키를 분실하면 암호문을 복호화할 수 없으므로 안전하게 보관
알고리즘 변경 한번 암호화한 뒤 알고리즘을 변경하면 기존 암호문이 복호화 불가
RandomSalt 같은 평문이라도 매번 다른 암호문이 생성되므로, Git diff로 값 유출 여부를 판단할 수 없음
디버깅 복호화 실패 시 EncryptionOperationNotPossibleException 발생 — 키가 맞는지 먼저 확인

그리고, spring 하위 프로퍼티에만 이게 먹힌다. 다른 프로퍼티에 넣으면 복호화되지 않는다.

정리

Jasypt는 설정 한 번이면 이후 ENC()만 감싸주면 되므로, 가장 적은 코드로 프로퍼티 보안을 확보할 수 있는 방법이다.

Written by
author
풍우래기

여행을 좋아하는 집돌이 개발자입니다.

블로그에 새로운 글이 발행되었습니다.