Jasypt는 자바에서 암호화를 쉽게 할 수 있도록 도와주는 라이브러리이다.
When?
Spring에서 datasource를 연동할 때, application.yml 파일에 다음과 같이 설정할 수 있다.
spring:
datasource:
url: jdbc:mysql://...
username: user123
password: pass123
driver-class-name: com.mysql.cj.jdbc.Driver
이 때, password: pass123과 같이 외부에 노출되면 안되는 정보이다.
특히 깃허브같은 원격 저장소에 등록할 때는 더욱 주의해야 한다.
이와 같이 특정 프로퍼티에 대한 암호화가 필요할 때, Jasypt를 사용할 수 있다.
How?
<dependency 추가>
gradle project 기준
implementation "com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3"
<Jasypt Bean 설정>
@Configuration
class JasyptConfig {
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("test"); // encrypt key
config.setAlgorithm("PBEWITHMD5ANDDES");
config.setPoolSize("1");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
Jasypt 암호기를 설정하는 부분이다.
쉽게 말해서, 암호화 하고 싶은 모든 String은 이 암호기를 거쳐서 암호화가 되는 것이다.
여기서 중요한 부분은 config.setPassword() 메서드이다. 여기에는 암호에 필요한 key 값을 넣는 것이다.
이 암호화 key 값에 따라서 특정 String이 암호화가 된다.
+) 암호화 key와 암호화하고자 하는 실제 password와 다른 것이다. 헷갈리지 말자.
<application.yml 설정 추가>
...
jasypt:
encryptor:
bean: jasyptStringEncryptor
방금 코드의 @Bean("빈 이름")과 동일하게 설정해준다.
<암호화된 String 확인>
이제 특정 String에 대해 Jasypt를 통한 암호화된 값을 확인해보자.
간단한 코드를 통해 확인할 수 있다.
public class JasyptTest {
public static void main(String[] args) {
String password = "pass123";
StandardPBEStringEncryptor jasypt = new StandardPBEStringEncryptor();
jasypt.setPassword("test");
jasypt.setAlgorithm("PBEWITHMD5ANDDES");
String encryptedText = jasypt.encrypt(password);
String decryptedText = jasypt.decrypt(encryptedText);
System.out.println("encryptedText = " + encryptedText);
System.out.println("decryptedText = " + decryptedText);
}
}
결과
encryptedText = QD5EZJeFSJYWIDmi75dmYQ==
decryptedText = pass123
이렇게 암호화된 값(encryptedText)를 얻을 수 있고 복호화 역시 가능하다.
<암호화된 값 적용>
이제 암호화를 통해 얻은 String을 기존 password와 교체하자.
spring:
datasource:
url: jdbc:mysql://...
username: user123
password: ENC(QD5EZJeFSJYWIDmi75dmYQ==)
driver-class-name: com.mysql.cj.jdbc.Driver
이 때, 코드처럼 ENC()로 암호하된 값을 감싸줘야 한다.
이렇게 Jasypt 암호화를 통해 중요한 정보를 외부에 노출하지 않을 수 있다.
주의점
Jasypt 라이브러리를 사용하면서 의아한 점이 생겼다.
코드를 다시 보자.
@Configuration
class JasyptConfig {
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("test"); // encrypt key
config.setAlgorithm("PBEWITHMD5ANDDES");
config.setPoolSize("1");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
Jasypt는 이처럼 내가 직접 설정한 encrypt key에 따라 암호화를 진행한다.
public class JasyptTest {
public static void main(String[] args) {
String password = "pass123";
StandardPBEStringEncryptor jasypt = new StandardPBEStringEncryptor();
jasypt.setPassword("test");
jasypt.setAlgorithm("PBEWITHMD5ANDDES");
String encryptedText = jasypt.encrypt(password);
String decryptedText = jasypt.decrypt(encryptedText);
System.out.println("encryptedText = " + encryptedText);
System.out.println("decryptedText = " + decryptedText);
}
}
그리고 이 encrypt key만 알면 암호값을 다시 복호화 시킬 수 있다.
-> 그렇다면 encrypt key가 노출되어 있으면 암호를 다시 복호화 시킬 수 있기 때문에 암호화가 의미 없는 것 아닌가?
그렇다. 결국 Jasypt 설정에 사용되는 encrypt key 역시 노출되지 않게 설정이 필요하다.
여러 검색을 통해 몇 가지 방법을 찾아냈다.
1. 환경 변수 사용
encrypt key를 프로젝트 내부가 아니라 구동 서버의 환경변수로 존재하게끔 하는 것이다.
export JASYPT_ENCRYPTOR_PASSWORD=test
이렇게 환경 변수를 지정하고
System.getenv("JASYPT_ENCRYPTOR_PASSWORD)이렇게 환경 변수를 꺼내서 사용하면 된다는데...
나의 경우는 로컬에서 환경 변수를 등록해도 getenv로 조회할 수가 없었다... 뭔가 놓치고 있는게 있나
찾다보니 인텔리제이 자체에서 환경 변수를 등록하는 방법이 있었다. 만약, 인텔리제이를 사용한다면 아래 글을 참고하자.
https://gksdudrb922.tistory.com/146
2. VM Options 사용
Intellij에서는 JVM Option을 설정할 수 있다.
우측 상단에 실행 파일 목록을 클릭한 뒤, "Edit Configurations" 클릭
Environment - VM options에서 "-D변수이름=변수값" 으로 encrypt key를 지정할 수 있다.
코드는 다음과 같이 수정할 수 있다.
@Configuration
class JasyptConfig {
@Value("${jasypt.encryptor.password}")
private String encryptKey;
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(encryptKey); //encrypt key
config.setAlgorithm("PBEWITHMD5ANDDES");
config.setPoolSize("1");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
-> 현재 프로젝트에서 이 방법을 사용 중이다.
3. AWS Parameter Store
만약 프로젝트를 AWS EC2에 등록한다면, AWS Parameter Store를 통해 직접 변수 값을 등록하고 이를 Spring Cloud와 연동해서 사용할 수 있다고 한다.
이 방법에 대해서는 조금 더 공부가 필요할 것 같다.
이렇게 encrypt key를 암호화 하는 방법에 대해서 몇 가지 추려봤는데, 여러 문서들을 참고하며 자신에게 맞는 방법을 찾아보자.
'java > spring' 카테고리의 다른 글
[Spring] AWS S3, csv 파일 읽어서 DB에 저장 (0) | 2021.08.05 |
---|---|
[Spring] AWS S3에서 Spring Boot로 파일 다운로드 (0) | 2021.08.05 |
[Spring] 스프링 부트, 라이브러리 버전 맞추기 (0) | 2021.05.23 |
타임리프(Thymeleaf) - 스프링 뷰 템플릿 (0) | 2021.05.12 |
[SpringMVC] 스프링 MVC - 웹 페이지 만들기 (0) | 2021.05.12 |