Springboot - DB Datasource 암호화/복호화(application.properties)

2019. 8. 5. 14:43Web/Spring

 

이번 포스팅에서 다루어볼 내용은 spring boot project에서 DB Access관련 설정을 application.properties에 설정 해 놓는데, 기존처럼 평문으로 username/password를 넣는 것이 아니라 특정 알고리즘으로 암호화된 문자열을 넣고 애플리케이션 스타트업 시점에 복호화하여 DB Access를 하는 것입니다. 바로 예제로 들어가겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.example.demo;
 
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
 
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
import org.junit.Test;
 
public class EncryptTest {
 
    @Test
    public void encrypt() throws Exception {
        
        String str = "ENCRYPT!@1234";
        String encStr = encAES(str);
        System.out.println(encStr);
        System.out.println(decAES(encStr));
        
    }
    
    public Key getAESKey() throws Exception {
        String iv;
        Key keySpec;
 
        String key = "encryption!@1234";
        iv = key.substring(016);
        byte[] keyBytes = new byte[16];
        byte[] b = key.getBytes("UTF-8");
 
        int len = b.length;
        if (len > keyBytes.length) {
           len = keyBytes.length;
        }
 
        System.arraycopy(b, 0, keyBytes, 0, len);
        keySpec = new SecretKeySpec(keyBytes, "AES");
 
        return keySpec;
    }
 
    // 암호화
    public String encAES(String str) throws Exception {
        Key keySpec = getAESKey();
        String iv = "0987654321654321";
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes("UTF-8")));
        byte[] encrypted = c.doFinal(str.getBytes("UTF-8"));
        String enStr = new String(Base64.getEncoder().encode(encrypted));
 
        return enStr;
    }
 
    // 복호화
    public String decAES(String enStr) throws Exception {
        Key keySpec = getAESKey();
        String iv = "0987654321654321";
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes("UTF-8")));
        byte[] byteStr = Base64.getDecoder().decode(enStr.getBytes("UTF-8"));
        String decStr = new String(c.doFinal(byteStr), "UTF-8");
 
        return decStr;
    }
}
 
cs

 

위의 소스는 암복호화 단위테스트 코드입니다. AES-128 방식으로 암복호화하였으며 CBC 방식으로 진행하였습니다. 암호화 알고리즘에 대해서는 추후 포스팅하도록 하겠습니다.

 

1
2
3
#AES128_Encrypt
spring.datasource.username=T7Me97L7JW9YXubNVtNfpQ==
spring.datasource.password=/Wm/Ubs7CniQuA+5Mzq7Qg==
cs

 

위는 암호화된 형태소 Datasource 정보를 넣은 것입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package com.example.demo.config;
 
import java.security.Key;
import java.util.Base64;
import java.util.Properties;
 
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;
 
public class EncryptEnvPostProcessor implements EnvironmentPostProcessor {
 
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        
        Properties props = new Properties();
        try {
            props.put("spring.datasource.password", decAES(environment.getProperty("spring.datasource.password")));
            props.put("spring.datasource.username", decAES(environment.getProperty("spring.datasource.username")));
        } catch (Exception e) {
            System.out.println("DB id/password decrypt fail !");
        }
 
        environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));
 
    }
    
    public Key getAESKey() throws Exception {
        String iv;
        Key keySpec;
 
        String key = "encryption!@1234";
        iv = key.substring(016);
        byte[] keyBytes = new byte[16];
        byte[] b = key.getBytes("UTF-8");
 
        int len = b.length;
        if (len > keyBytes.length) {
           len = keyBytes.length;
        }
 
        System.arraycopy(b, 0, keyBytes, 0, len);
        keySpec = new SecretKeySpec(keyBytes, "AES");
 
        return keySpec;
    }
 
    // 암호화
    public String encAES(String str) throws Exception {
        Key keySpec = getAESKey();
        String iv = "0987654321654321";
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes("UTF-8")));
        byte[] encrypted = c.doFinal(str.getBytes("UTF-8"));
        String enStr = new String(Base64.getEncoder().encode(encrypted));
 
        return enStr;
    }
 
    // 복호화
    public String decAES(String enStr) throws Exception {
        Key keySpec = getAESKey();
        String iv = "0987654321654321";
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes("UTF-8")));
        byte[] byteStr = Base64.getDecoder().decode(enStr.getBytes("UTF-8"));
        String decStr = new String(c.doFinal(byteStr), "UTF-8");
 
        return decStr;
    }
 
}
 
cs

 

위 소스는 springboot application 기동 시점에 암호화된 username/password를 복호화하여 Datasource 객체를 생성하기 위한 후처리 프로세서입니다. EnvironmentPostProcessor라는 인터페이스를 구현한 클래스를 하나 생성하여 오버라이딩된 메소드에 복호화하는 로직을 구현해주시면 됩니다.

 

여기서 중요한 것은 그냥 후처리 프로세서를 등록하면 끝나는 것이 아니라 설정 파일을 넣어 주어야 합니다.

 

 

src/main/resources/META-INF/spring.factories 파일을 생성하여 아래와 같은 정보를 기입해줍니다.

 

1
2
# post processor 적용
org.springframework.boot.env.EnvironmentPostProcessor=com.example.demo.config.EncryptEnvPostProcessor
cs

EncryptEnvPostProcessor라는 클래스의 패키지네임을 포함한 Full Path를 해당 설정파일에 기입해주시면 됩니다.

 

여기까지 application.properties에 암호화된 정보를 넣어 복호화하는 예제를 진행해봤습니다. 사실 Datasource 외에도 다른 설정파일에도 적용가능한 예제입니다. 활용하시길 바랍니다!