Post View

Jasypt를 이용하여 Spring Properties 정보 암호화하기

Spring 설정 정보를 properties로 분리하기 글에서 여러 설정에 사용하는 정보를 별도의 properties 파일로 관리하는 방법을 알아보았습니다.
그런데 이 방식으로 설정 정보를 관리하는 경우 비밀번호와 같은 중요 정보들이 그대로 노출되는 문제가 발생합니다.
이번에는 Jasypt 라이브러리를 사용해서 중요 정보를 암호화하는 방법을 알아보겠습니다.

암호화 된 문자열 만들기

먼저 https://github.com/jasypt/jasypt에서 Download distributable 옆의 링크를 눌러 jasypt encrypt tool을 다운로드합니다.
제가 다운로드 받은 버전은 jasypt 1.9.3입니다.

다운로드 된 zip 파일의 압축을 풀어 jasypt-1.9.3 폴더로 들어가보면 bin 폴더가 있습니다.

윈도우 환경
CMD로 jasypt-1.9.3/bin 폴더 이동

encrypt.bat input=kre1234 password=customPassword algorithm=PBEWithHmacSHA512AndAES_256 ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator keyObtentionIterations=1000000

리눅스 혹은 맥 환경
Terminal로 jasypt-1.9.3/bin 폴더 이동

chmod +x encrypt.sh
./encrypt.sh input=kre1234 password=customPassword algorithm=PBEWithHmacSHA512AndAES_256 ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator keyObtentionIterations=1000000

encrypt bat과 sh 파일은 암호화된 문자열을 리턴해주는 프로그램인데, 이걸 이용해서 암호화된 문자열을 만들 예정입니다.

위의 예제와 같이 입력하시되 input은 실제 암호화를 할 문자열(properties에 입력했던 값)을 입력해주시고 password는 공개되면 안되는 값이므로 임의로 입력하고 기억하시면 됩니다.
algorithm은 대칭키 암호화에 사용될 알고리즘을 나타내는데, 저는 AES256 방식을 사용하였습니다.

ivGeneratorClassName은 대칭키 암호화 작업 중 필요한 IV(Initialization Vector)란 값을 처리할 class명을 지정하는데 위에 작성된 org.jasypt.iv.RandomIvGenerator를 입력해주시면 됩니다.

keyObtentionIterations는 password의 값을 key로 사용하기 전에 해시 암호화를 하는 횟수로 100만회, 실제 서버 환경설정에는 200만회로 설정했습니다.
이 횟수에 따라 암호화를 하는 시간이 오래 걸리게 되는데 제 PC 기준 백만회의 암호화 시간이 약 1초정도 걸립니다.
이 시간이 오래걸릴수록 Brute force(무차별대입) 공격에서 안전해지므로 서버 성능에 따라 조절하여 사용하시면 될 것 같습니다.

해당 명령어를 치면 "urUt4OuvSr+UV4XbrdArR2zq+jpqh7WyvoElZ5C9egtygfRt5j4kMrTrG0GLw3ko"와 같은 암호화된 문자열이 나오는데, 암호화된 문자열은 매번 달라지니 참고하시기 바랍니다.

jasypt 라이브러리 디펜던시 추가

먼저 암호화를 위해 jasypt 라이브러리를 추가해줘야합니다.
제가 작업하는 블로그는 스프링 5 기반으로 작업을 하고 있는데, 검색을 해보니 jasypt-spring4 버전까지밖에 없더라구요?
그런데 다른 예제들을 보니 여전히 낮은 버전을 사용하는게 보여서 jasypt-spring4 버전을 스프링 5에 적용해보니 작동해서 jasypt-spring4를 사용하기로 했습니다.

먼저 mvnrepository에서 디펜던시를 찾았습니다.
https://mvnrepository.com/artifact/org.jasypt/jasypt-spring4/1.9.3

<!-- https://mvnrepository.com/artifact/org.jasypt/jasypt -->
<dependency>
    <groupId>org.jasypt</groupId>
    <artifactId>jasypt-spring4</artifactId>
    <version>1.9.3</version>
</dependency>

제가 작업중인 블로그는 maven을 사용하니 pom.xml에 디펜던시를 추가했습니다.

config.properties 정보 변경

이제 암호화된 문자열로 config.properties에 입력해뒀던 password들을 대체해줘야 하는데, 암호화되는 문자열은 "ENC(암호화문자열)"과 같이 감싸주어야 해당 정보를 복호화하여 사용하게 됩니다.

properties 복호화 설정하기

이제 암호화된 문자열을 복호화할 수 있도록 설정을 변경해보겠습니다.
기존에 config.properties를 가져오는 설정을 복호화가 가능하도록 변경해야합니다.
Spring 설정 정보를 properties로 분리하기에서 설정했던 root-context.xml를 열고 기존 설정을 삭제한 후 아래의 설정으로 변경합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- Root Context: defines shared resources visible to all other web components -->
	<!-- <context:property-placeholder location="classpath:/properties/*.properties" /> -->
	<bean id="encryptorConfig" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
		<property name="algorithm" value="PBEWithHmacSHA512AndAES_256" />
		<!-- jasypt의 encrypt.bat 혹은 encrypt.sh에 입력한 password 값을 입력한다.-->
		<!-- <property name="password" value="customPassword"/>-->
		<!-- 혹은 환경변수에 해당 password 값을 등록하고, 환경변수명을 value에 추가한다. -->
		<property name="passwordEnvName" value="KRE_ENC_KEY" />
		<property name="ivGeneratorClassName" value="org.jasypt.iv.RandomIvGenerator" />
		<property name="keyObtentionIterations" value="1000000" />
	</bean>

	<bean id="encryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
		<property name="config" ref="encryptorConfig" />
	</bean>

	<bean id="propertyConfigurer" class="org.jasypt.spring4.properties.EncryptablePropertyPlaceholderConfigurer">
		<constructor-arg ref="encryptor" />
		<property name="locations" value="classpath:/properties/*.properties" />
	</bean>
</beans>

수정된 사항을 보면 "암호화 된 문자열 만들기" 부분에서 설정했던 algorithm, ivGeneratorClassName, keyObtentionIterations가 동일하게 포함되어있는걸 볼 수 있습니다.
하지만 password는 암호화/복호화를 위한 Key 값이기 때문에 <property name="password" value="customPassword"/>와 같이 직접 입력하게 되면 굳이 properties에 암호화를 한 의미가 없어져버립니다.

<property name="passwordEnvName" value="KRE_ENC_KEY" />

그래서 위와 같이 환경변수를 이용한 방법을 사용해야하는데, 각 OS별 환경변수 설정은 아래의 링크들을 참고하시기 바랍니다.

윈도우 10 환경변수 설정
리눅스 환경변수 설정
맥OS 환경변수 설정

환경변수로 KRE_ENC_KEY=customPassword로 입력하신 후 서버를 실행하면 됩니다. 만약 개발툴(Intelli J 등)을 이용해서 서버를 실행하시려면 개발툴 내에 별도의 환경변수를 설정하는 곳이 있을 수 있으니 참고하시기 바랍니다.

이제 서버를 실행해보겠습니다.

암호화 설정 후 로컬에서 정상적으로 실행되는 것을 확인할 수 있습니다.

추후 회원가입 기능을 만들 예정인데, 그 때를 위해서 이런 보안 작업을 진행하고 있습니다.
어려운 부분이 있다면 댓글에 남겨주시기 바랍니다.

Comments