Programming/스프링 부트(Spring Boot)

[Spring Boot] - jasypt 을 사용하여 암/복호화 하기

귀찮은 개발자 2024. 2. 20. 13:09

jasypt란

양방향 암호화를 사용할 수 있는 Java 라이브러리이다.

시스템 환경변수와 마찬가지로 소스코드가 외부에 반출되더라도 중요한 Access/Secret key 등 중요한 정보가 평문으로 노출되는 것을 방지하고자 하는 목적으로 사용된다. 

Dependency 추가 방법

Maven

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

Gradle

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

Jasypt 설정 및 Bean 등록

System.getenv("ENCRYPTOR_PASSWORD"); 라고 작성되어 있는 부분이 암호화된 ENC 을 디코딩하기 위한 Key 이다. 

java -jar 명령어를 사용하여 시스템 환경변수 ENCRYPTOR_PASSWORD 에  value 을 저장하여 사용한다.

JasyptConfig Been 등록

package com.wable.user_api.global.config;

import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableEncryptableProperties
public class JasyptConfigAES {

    @Bean("jasyptEncryptorAES")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        String jasyptPassword = System.getenv("ENCRYPTOR_PASSWORD");

        config.setPassword(jasyptPassword); // 암호화키
        config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256"); // 알고리즘
        config.setKeyObtentionIterations("1000"); // 반복할 해싱 회수
        config.setPoolSize("1"); // 인스턴스 pool
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); // salt 생성 클래스
        config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
        config.setStringOutputType("base64"); //인코딩 방식
        encryptor.setConfig(config);
        return encryptor;
    }
}

application.properties

cloud:
  ...
  private:
    group:
      secretKey: ENC(iGUPWEyRfu6vTBYdFeAa91gXWRpxAObYy9eSxZC8mlACtWTFFocdRj/ajb2BjZ//CvZXbNZkEtupSUZja4Quo5CF5Y03eauouKayLTBEwETy4w6w3WY9i0cVpT0UrpytZjsjdoWj+FwrQxgp5kcJ4w==)
      validityMillis: ENC(8aPdvU+zDbp/VUAcQTx/L83Q5+WNwo0kA8D5bAjrY1OtbcnX+mi1fIE5l1TmYqZS)

@value 어노데이션 사용 시

@Component
public class TokenGenerator {

    @Value("${cloud.private.group.secretKey}")
    private String secretKey;

    @Value("${cloud.private.group.validityMillis}")
    private long validityMillis;

    public String generateJwtToken() {
        long nowMillis = System.currentTimeMillis();
        long expMillis = nowMillis + validityMillis;

        return Jwts.builder()
                .setExpiration(new Date(expMillis))
                .signWith(SignatureAlgorithm.HS256, secretKey.getBytes())
                .compact();
    }

테스트를 통해 암호화 Value 생성

package com.wable.user_api.domain.card.repository;

import io.jsonwebtoken.security.Keys;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.iv.RandomIvGenerator;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;

import java.util.Date;

class JasyptConfigAESTest {

    @Test
    void stringEncryptor() {
        String url = "jdbc:mysql://localhost:3306/default";
        String username = "root";
        String password = "password";

        System.out.println("ENC(" + jasyptEncoding(url) + ")");
        System.out.println("ENC(" + jasyptEncoding(username) + ")");
        System.out.println("ENC(" + jasyptEncoding(password) + ")");
    }

    public String jasyptEncoding(String value) {
        String jasyptPassword = System.getenv("ENCRYPTOR_PASSWORD");
        System.out.println(jasyptPassword);
        StandardPBEStringEncryptor pbeEnc = new StandardPBEStringEncryptor();
        pbeEnc.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
        pbeEnc.setPassword(jasyptPassword);
        pbeEnc.setIvGenerator(new RandomIvGenerator());
        return pbeEnc.encrypt(value);
    }

결과