728x90
공개하지 말아야 하는 값을 암호화 해보자. (jasypt를 사용하기.)
서론
- 최근 노마드 커뮤니티 사이드 프로젝트를 진행 하던 중에, 프로덕션 DB 연결하기 위한 URL, name, password를 application.yml에 넣어야 하는데, 깃헙으로 코드를 관리하고 있던 차라 단순히 올리기가 어려운 문제가 있었습니다.
- AWS의 Parameter Store와 같은 기능을 쓰면 좋지만, 현재 초기 단계이고 빠르게 서버 구축을 해두고 계속해서 배포하면서 QA를 진행하고 MVP를 구현해야 하는 단계에서 Parameter Store를 사용하기 보단, 다른 방법을 사용하는것이 좋겠다. 라고 생각해서 검색을 하다가 jasypt라는 라이브러리를 찾게 되었고 해당 라이브러리로 적용한 방법을 공유합니다.
- 관련 라이브러리 공식 github은 아래와 같습니다.
- 관련 코드는 Kotlin 1.9 / Spring Boot 3.2 버전으로 작성되었습니다.
jasypt
Jasypt Spring Boot provides Encryption support for property sources in Spring Boot Applications. (Jasypt Spring Boot는 Spring Boot 애플리케이션의 속성 소스에 대한 암호화 지원을 제공합니다.)
- 해당 라이브러리 맨 설명 첫 문장은 위와 같습니다.
- 쉽게 생각해서 application.yml, properties에 잇는 값에 대한 암호화 지원을 한다고 생각해주시면 됩니다
Getting Start
- 의존성을 추가합니다.
implementation ("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5")
- Configure 클래스를 추가합니다
@Configuration
@EnableEncryptableProperties
class JasyptConfig {
@Bean("jasyptStringEncryptor")
fun stringEncryptor(): StringEncryptor {
val encryptor = PooledPBEStringEncryptor()
val config = SimpleStringPBEConfig()
config.password = System.getProperty("jasypt.encryptor.password")
config.algorithm = "PBEWithMD5AndDES"
config.setKeyObtentionIterations("1000")
config.setPoolSize("1")
config.providerName = "SunJCE"
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator")
config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator")
config.stringOutputType = "base64"
encryptor.setConfig(config)
return encryptor
}
}
- 위와 같이 Spirng Configure Bean에 등록하고 관련 설정파일을 등록해주면 됩니다.
- System.getProperty란 Spring Boot를 실행할때, property로 해당 key-value를 넣으면 들어가게 됩니다.
- 각 라인들을 살펴보도록 하겠습니다.
Key | required | default | desc | value |
---|---|---|---|---|
password | 필수 | - | 암호화를 하기 위한 key값 | - |
algorithm | 선택 | PBEWITHHMACSHA512ANDAES_256 | 암호화 알고리즘 | PBEWithMD5AndDES / PBEWithMD5AndTripleDES / PBEWithSHA1AndDESede / PBEWithSHA1AndRC2 / PBEWithHmacSHA1AndAES_128 / PBEWithHmacSHA1AndAES_256 / PBEWithHmacSHA256AndAES_128 / PBEWithHmacSHA256AndAES_256 |
KeyObtentionIterations | 선택 | 1000 | 키 획득 이터레이션 수는 암호화의 강도를 결정하는 요소 중 하나입니다. 일반적으로 키 획득 이터레이션 수를 높게 설정하면 암호화가 더 강해집니다. | |
PoolSize | 선택 | 1 | 키 풀 크기는 암호화 성능을 결정하는 요소 중 하나입니다. 일반적으로 키 풀 크기를 크게 설정하면 암호화 성능이 향상됩니다. | |
providerName | 선택 | SunJCE | providerName은 암호화 제공자를 지정하는 문자열입니다. Jasypt는 다음과 같은 제공자를 지원합니다. | BouncyCastle / SunJCE |
providerClassName | 선택 | null | 암호화 제공자 클래스 이름을 지정하는 문자열입니다. | |
SaltGeneratorClassName | 선택 | org.jasypt.salt.RandomSaltGenerator | SaltGeneratorClassName을 지정하는 문자열로서 Salt는 암호화 프로세스에서 추가적인 무작위성을 제공하는 값입니다. | |
IvGeneratorClassName | 선택 | org.jasypt.iv.RandomIvGenerator | IvGeneratorClassName을 지정하는 문자열입니다. IV는 블록 암호화 공식의 사용에 필요한 초기 벡터 생성에 사용됩니다. | |
stringOutputType | 선택 | base64 | 암호화된 문자열의 출력 형식을 지정하는 문자열입니다. | BASE64 / HEX |
proxyPropertySources | 선택 | false | PropertySource를 프록시로 사용할지 여부를 지정하는 값입니다. 프로퍼티 소스를 프록시로 사용하면 Jasypt는 프로퍼티 소스에서 프로퍼티를 읽을 때마다 암호화/복호화를 수행합니다. | |
skipPropertySources | 선택 | [] | Jasypt에서 자동 암호화를 수행하지 않아야 하는 PropertySource 목록을 지정합니다. |
키를 암호화해서 yml에 넣는다.
- 암호화는 해당 홈페이지에서도 가능하며, 아래와 같이 테스트 코드를 넣어서도 가능합니다.
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor import org.junit.jupiter.api.Test internal class JasyptConfigDESTest { @Test fun stringEncryptor() { val url = "db_url" val username = "db_username" val password = "db_password" println(jasyptEncoding(url)) println(jasyptEncoding(username)) println(jasyptEncoding(password)) } fun jasyptEncoding(value: String?): String { val key = "my_jasypt_key" val pbeEnc = StandardPBEStringEncryptor() pbeEnc.setAlgorithm("PBEWithMD5AndDES") pbeEnc.setPassword(key) return pbeEnc.encrypt(value) } }
- 암호화된 값을 아래와같이
ENC({value})
로 같이 넣는다.
spring: datasource: url: ENC(XkqCKlaHWnraWNlmRRKYGWZ6HjM+POHN) username: ENC(XkqCKlaHWnraWNlmRRKYGWZ6HjM+POHN) password: ENC(XkqCKlaHWnraWNlmRRKYGWZ6HjM+POHN)
cf) 예제이기 떄문에 같은 값이 나왓는데 다른 값이라면 다른 값이 나오게 됩니다
결론
- ParameterStore와 같은 기능을 사용하면 좋지만, 급하게 할 경우에는 이와 같이 Jasypt를 통해 암호화를 한다면 github public 저장소에 편히 올릴수가 있습니다.
728x90
728x90
'Backend > Spring' 카테고리의 다른 글
[번역] How to implement a soft delete with Hibernate(어떻게 Hibernate를 사용해 소프트 삭제를 구현하는가) (1) | 2024.01.27 |
---|---|
[번역] Data Transfer Object (DTO) in Spring Boot (0) | 2024.01.25 |
Spring JPA의 @Table 어노테이션에 대해서 알아보자 - name을 어떻게 매핑하는가? (2) | 2023.11.29 |
IntelliJ IDE에서 Spring Initializr를 이용해 프로젝트를 생성해보자. (0) | 2023.04.06 |
Spring의 ResponseEntity에 대해 알아보자 (0) | 2021.12.15 |