스프링 부트

[SpringBoot] JasyptEncryptor 적용하기

h__hj 2022. 8. 6. 20:11

Spring Boot JasyptEncryptor 적용하기

 노출이 되면 안되는 Spring Boot 환경 설정 값을 JasyptEncryptor 로 암호화하여 서버 기동하기!

# 환경

/**
 * tool: sts 4.13.0 
 * vers: 2.7.3-SNAPSHOT
 * java: 1.8
 * type: maven
 */

# pom.xml

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

# application.yml

jasypt:
  encryptor:
    bean: jasypt
    algorithm: PBEWithMD5AndDES
    password: ${initKey:NONE}

# Configuration

@Configuration
public class JasyptConfig {
	
	// application에 설정한 password
	@Value("${jasypt.encryptor.password}")
	private String jasyptPassword;
    
	// application에 설정한 algorithm
	@Value("${jasypt.encryptor.algorithm}")
	private String jasyptAlgorithm;
	
	// application에 설정한 bean
	@Bean(name = "jasypt")
	public StringEncryptor init() {
		SimpleStringPBEConfig config = new SimpleStringPBEConfig();
		// 암호화 패스워드
		config.setPassword(jasyptPassword);
		// 암호화 알고리즘
		config.setAlgorithm(jasyptAlgorithm);
		// 반복할 해싱 횟수
		config.setKeyObtentionIterations("1000");
		// 인스턴스 pool
		config.setPoolSize("1");
		config.setProviderName("SunJCE");
		// salt 생성 클래스
		config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
		// 인코딩 방식
		config.setStringOutputType("base64");
    
		PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
		encryptor.setConfig(config);
		
		return encryptor;
 	}
    
 	/**
	 * JASYPT ENCRYPTOR
	 */
	@Bean(name = "jasyptEncryptor")
	public StandardPBEStringEncryptor jasyptEncryptor() {

		StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
		encryptor.setPassword(jasyptPassword);
		encryptor.setAlgorithm(jasyptAlgorithm);
        
		return encryptor;
	}
}

# Run 설정

  • Boot Dashboard → 해당 프로젝트 우클릭 → Open Config → Environment > Add
  • Variable은 application.yml에 등록한 KEY
  • Value는 Jasypt 암호화에 사용되는 Password
  • 암호화 적용 후 initKey가 다를 경우 서버 기동이 불가

# 테스트

@SpringBootTest
public class EncrptServiceTest {

	// #Configuration에서 설정한 Bean
	@Autowired
	private StandardPBEStringEncryptor jasyptEncryptor;
	
	@Test
	public void jasyptEncryptTest() {
		String jdbcUrl = "jdbc:oracle:thin:@localhost:1521/XE";
		
		String encryptJdbcUrl1 = jasyptEncryptor.encrypt(jdbcUrl);
		String encryptJdbcUrl2 = jasyptEncryptor.encrypt(jdbcUrl);
		
		String decryptJdbcUrl1 = jasyptEncryptor.decrypt(encryptJdbcUrl1);
		String decryptJdbcUrl2 = jasyptEncryptor.decrypt(encryptJdbcUrl2);
		
		boolean isEqual = decryptJdbcUrl1.equals(decryptJdbcUrl2);
        
		System.out.println("[JASYPT] [TEST] ENC 1: " + encryptJdbcUrl1);
		System.out.println("[JASYPT] [TEST] ENC 2: " + encryptJdbcUrl2);
		System.out.println("[JASYPT] [TEST] DEC 1: " + decryptJdbcUrl1);
		System.out.println("[JASYPT] [TEST] DEC 2: " + decryptJdbcUrl2);
		System.out.println("[JASYPT] [TEST] EQUAL: " + isEqual);
    }
}
  • #Configutaion 에 생성한 Bean을 선언.
  • 암호화된 값으로 노출이 되면 안되는 환경값의 적용한다.

# 테스트 결과

[JASYPT] [TEST] ENC 1: UzJR84MFVrkC1X1QrMLAb0uhbV3gk3QYQV1q6ZkBnDa5tjLxHLZ+OdIXIJ2alQf0
[JASYPT] [TEST] ENC 2: WM3UpkIo/sX6NUt2DndoUN1Se4YlrjFs0Ho8AY12jWd5tSakkryCDQx+giB9cZav
[JASYPT] [TEST] DEC 1: jdbc:oracle:thin:@localhost:1521/XE
[JASYPT] [TEST] DEC 2: jdbc:oracle:thin:@localhost:1521/XE
[JASYPT] [TEST] EQUAL: true

# 적용

spring:
  # Database
  datasource:
    # 예시
    driver-class-name: ENC(UzJR84MFVrkC1X1QrMLAb0uhbV3gk3QYQV1q6ZkBnDa5tjLxHLZ+OdIXIJ2alQf0)
    url: ENC(encryptUrl)
    username: ENC(encryptUsername)
    password: ENC(encryptPassword)

# 내용

  • 프로젝트 생성 시 꼭 필요한 작업으로 생각함.
  • jasypt는 값을 암호화 할때마다 다른 값이 나오지만, 복호화하면 값은 같다.
  • 환경값들은 암호화 되지만, 정작 jasypt의 패스워드는 암호화가 안된다.
  • environment에 입력값을 이용하면 jasypt의 패스워드도 노출 될 일이 없다.