본문 바로가기
spring & boot/Spring & Spring Boot

[Spring Boot]Jasypt 원리 및 사용방법(yml 설정 암복호화, Boot 3.x^) +String Util Class

by lucas_owner 2024. 8. 14.

 

 

Jasypt 암복호화 라이브러리

프로그래밍 공부를 하고 있는 사람들이라면, 보안에 관련된 수많은 얘기들을 듣고는 한다. 

각종 정보들은 보안에 신경써야 한다고 말이다. (DB 접속정보, 사용자 정보, 파라미터 등등)

서버간 통신시 암호화가 필요한 경우 라이브러리를 사용하기도 하고, 직접 암복호화 유틸을 만들어서 사용하기도 한다.

 

우리는 yml 의 DB 정보에 대해서 암호화를 진행해보고, 원리를 간단하게 살펴 보도록 하겠다.

 

공식문서를 살펴보며 유틸이나, 다른 활용방법에 대해서도 보면 좋을것 같다. 해당글에서는 다루지 않겠다.

http://www.jasypt.org/general-usage.html

 

암호화에 대한 정보는 아래의 글에서 확인!

https://lucas-owner.tistory.com/70

 

AES-256 - Encrypt(암호화) For Java

얼마전, 외부 서비스 업체에서 제공하는 데이터를 DB 에 적재해야 하는 신규 기능 개발이 있었고,필수 요구사항중에서 'AES256 암호화 필수 (Base64)' 항목이 존재 했고 설계,분석,개발 과정에서 알

lucas-owner.tistory.com

 

 

설정 및 사용방법

* Gradle

implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4'// jasypt

 

* Maven 

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

해당 버전은 2021년도에 배포 되었고, 가장 최신 버전은 3.0.5 이고 2022년 배포 이후 새로운 버전은 배포되지 않았다.


* 2024.09.17 추가: Spring boot 3.x^ 버전에서는 Jasypt 사용시 오류가 발생한다. (Encrypt, Decrypt, StringUtill 등등 ...)

그럴 경우 해당 Dependency 의 버전을 `3.0.4 -> 3.0.5` 로 수정 후 Refresh 하면 해결 된다. 

 

https://github.com/ulisesbocchio/jasypt-spring-boot/releases/tag/jasypt-spring-boot-parent-3.0.5

 

해당 Release Note 에서 Spring Boot 3 Supprt update 부분에서 확인할 수 있다.

 

대략적으로 Spring Boot 3 로 버전이 올라가면서, AutoConfiguration 의 설정 추가, Test 에서의 @LocalServerPort 가 

Test Package 로 이동됨으로써, DefaultPropertyResolverTest  에 미리 정의된 port 사용으로 해결한것으로 보인다.

 


Jasypt 를 적용하는 순서는 크게 아래와 같다.
  1. JasyptConfig Class 생성 및 설정
  2. Test Class 생성 후 암호화 키 생성
  3. application.yml 혹은, application.properties 파일에 암호화 키 적용

암복호화에 필요한 SecretKey 를 기본적으로 감춰야 한다. (환경변수, GitSecretKey 등등 방법 사용)

 

1. JasyptConfig Class

@Configuration
public class JasyptConfig {

    @Value("${jasypt.encryptor.password}")
    private String encryptKey;

    @Bean(name = "jasyptEncryptor")
    public SimpleStringPBEConfig encryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(encryptKey); // 암호화할 때 사용하는 키
        config.setAlgorithm("PBEWithMD5AndDES"); // 암호화 알고리즘 default
        config.setKeyObtentionIterations("1000"); // 반복할 해싱 회수 default
        config.setPoolSize("1"); // 인스턴스 pool default
        config.setProviderName("SunJCE"); // default
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); // salt 생성 클래스 default
        config.setStringOutputType("base64"); //인코딩 방식
        encryptor.setConfig(config);
        return config;
    }
}

Jasypt 라이브러리를 설정을 담당하는 클래스이고, 기본적으로 Jasypt가 암복화에 필요한 설정을 정의하는 클래스이다. 

암복호화에 관련된 설정을 해당 클래스에서만 변경하면 되므로 복잡성이 줄어든다. 

 

주석의 default 가 붙은 설정들은 기본적으로 해당 값들이 설정됩니다. 해당 예제에서는 예시로 작성.

 

encryptKey 전역변수를 보게되면 @Value 어노테이션으로 암복호화에 필요한 비밀키를 가져오는것을 알 수 있다. 

application.yml

위의 사진처럼 yml 에 정의해서 SecretKey 를 가져올 수 있다. 

 

Q. secretKey 는 숨겨져야 하는거 아닌가요?

 

맞습니다. 알고리즘이나, 다른 설정까지 맞아야 하지만 기본적으로 외부에 노출하지 않는게 좋습니다. 

GItSecretKey 를 사용하거나, 환경변수 설정을 통해 숨김이 가능합니다. 

혹은 Private한 원격 저장소를 사용하고 있다면, 위의 사진과 같이 사용하는 방법도 있습니다. 

 

* .yml - 환경 변수 사용시 

jasypt:
  encryptor:
    password:${환경변수}

 

2. 암호화 Test Class 및 yml 적용

@Test
    @DisplayName("1. Encrypt Test")
    void test1() {
        String secretKey = "ThisIsTestSecretKey";

        String targetText = "This Is Target Text!!";

        // Using Jasypt
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(secretKey);
        encryptor.setAlgorithm("PBEWithMD5AndDES"); //Default

        String encryptedText = encryptor.encrypt(targetText);
        System.out.println("encryptedText = " + encryptedText);

        String decryptedText = encryptor.decrypt(encryptedText);
        System.out.println("decryptedText = " + decryptedText);

        Assertions.assertThat(decryptedText).isEqualTo(targetText);
    }

암호화에 대한 기본적인 설정은 마쳤으니, 실제 암호화를 진행해보도록 합니다. 

Test Result

여기서 encryptedText 의 출력된 내용이 암호화 값이고, 해당 값을 yml 에 적용하면 됩니다. 

 

암호화값 적용 - yml

암호화된 문자열을 적용하는 방법은 정말 쉽다. ENC(암호화 문자열) 을 원하는 설정에 넣어주면 끝난다. 

 

yml 적용

해당 사진 예시에서는 password 만 암호화 해줬다. 하지만 url, username 까지 모두 암호화 해주면 더 강력하게 보안을 신경쓸 수 있다.

  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: ENC(ejoa6pqPy+asdsgrlm212CKqPadfPbEr5YHrrvXNfF6jurcT1MaY)
    username: ENC(ejoa6pqPy+JTAsdjhi1u2SDYcA5gE55CKqPadfPbEr5YHrrvXNfF6jurcT1MaY)
    password: ENC(ejoa6pqPy+JT2q9e5HPK9DwgSYcASDJBBfPbEr5YHrrvXNfF6jurcT1MaY)

 

 

원리 및 추가 사용방법

Jasypt 는 Spring의 실행 시점에 설정파일에서 "ENC(" 문자열을 찾는다, 설정 파일에 해당 문자열이 존재한다면

Jasypt 에서 만든 암호화 문자열이라고 판단하여 복호화를 진행 하게 된다. 

 

PropertyValueEncryptionUtils 클래스에서 ENC( 키워드에서 실제 암호화 문자열을 추출하여 암호화 및 복호화를 진행하는 UtilClass 이다.

 

해당 Class 는 EncryptableProperties class 에서 사용되게 되는데,  Properties 클래스를 extends 하고 있다. 

즉 설정 파일의 정보를 가져온 후 아래의 decode 메서드를 통해, Jasypt 를 통해 생성된 암호화 문자열을 복호화 진행한다.

 

또한 공식문서를 봤다면 알 수 있는 Util 이 더 존재한다. 데이터의 타입별로 별도로 암호화가 가능하다.

  1. Password
  2. Number
  3. Binaries
  4. Text

해당 타입별 암복호화는 공식문서를 참고 하기 바란다. 

 

필자의 경우는 JasyptUtil 클래스를 별도로 작성하여, 간단한 Text 들을 암호화 할때 사용하고 있다. 

해당 클래스를 통해, String 타입과, Map 타입에 대해서 간단하게 암복화가 필요한곳에서 사용 하고 있다. 

 

@Test
    @DisplayName("3. Encrypt Util Test")
    void test3() {
        String targetText = "This is a secret message";
        String encrypt = JasyptEncryptUtil.encrypt(targetText);
        System.out.println("encrypt = " + encrypt);

        String decrypt = JasyptEncryptUtil.decrypt(encrypt);
        System.out.println("decrypt = " + decrypt);
        Assertions.assertThat(decrypt).isEqualTo(targetText);
    }

 

Util Test Result

반응형

댓글