스프링 클라우드로 프로젝트를 진행해보고 있으며, 설정 파일을 암호화하는 방법을 알려드리고자 합니다.
간단하게 이론 개념 설명 진행 후 바로 사용 방법을 작성하겠습니다.
Spring Cloud Config Server는 실행 시 yml 같은 환경 설정 파일들을 애플리케이션이 실행할 때 전파합니다. 이런 설정 파일은 보안과 관련된 정보를 가지므로 암호화하여 안전하게 관리할 필요가 있습니다.
일반적으로 암/복호화하는 방식을 크게 대칭키 방식과 비대칭키 방식이 있습니다.
대칭키(Symmetric): 암/복호화하는 키가 동일한 경우입니다.
대표적으로 AES, SEED, ARIA와 같은 알고리즘이 있습니다.
비대칭키(Asymmetric): 암/복호화하는 키가 다른 경우를 의미합니다. 모든 사람이 사용할 수 있는 공개키(public key)와 공개키를 통해 암호화된 데이터를 복호화할 수 있는 개인키(private key)로 구분됩니다.
대표적으로 RSA 알고리즘이 있습니다.
Java는 Java Cryptography Extension(JCE)을 이용해 암호 관련 기능을 제공합니다. Java 11이상부터는 기본적으로 제공하고 있으며 그 밑 버전에서는 해당 라이브러리를 다운받아야 사용이 가능하다.
Java Key Store(JKS)는 JCE를 이용해 만든 키를 저장하고 관리하는 저장소라고 보시면 됩니다.
이제부터 RSA 알고리즘을 이용한 비대칭키 암/복호화 방식을 보여드리겠습니다.
참고로 현재 저는 Java 11, Spring Boot 2.7, MAC 환경입니다.
키를 저장하기를 원하는 디렉토리를 생성해보겠습니다.
저는 keystore 라는 이름의 디렉토리 생성했습니다.
mkdir keystore
아래의 명령어로 key pair를 생성합니다.
keytool -genkeypair -alias {별칭} -keyalg {key알고리즘} -dname "{소프트웨어 서면 정보들}" -keypass "{키 비밀번호}" -keystore {키 스토어이름}.jks -storepass "{키스토어 비밀번호}"
keytool -genkeypair -alias apiEncryptionKey -keyalg RSA -dname "CN=Jiwon Jung, OU=API Development, O=test.co.kr, L=Seoul, C=KR" -keypass "test1234" -keystore apiEncryption.jks -storepass "test1234"
위 명령어 입력하면, 생성되었다고 뜨며, 확인해보면 apiEncryption.jks 이름으로 잘 생성된 것을 확인할 수 있습니다.
아래의 명령어 입력 시, key store password를 입력하라고 나오는데, 좀 전에 key pair 생성하면서 지정했던 키 비밀번호 test1234를 입력합니다.
-v 옵션을 빼면 간략하게 요약된 정보만 출력됩니다.
keytool -list -keystore apiEncryption.jks -v
하이라이트 된 부분을 보시면 PrivateKeyEntry라고 되어 있습니다. private key라고 보시면 됩니다.
암호화/복호화할 때 사용할 수 있습니다.
사실 private key를 만들었고, 이걸가지고 사용할 것이므로 작업은 바로 진행해도 됩니다.
그러나 저는 public key를 만드는 것을 보여드리고자 옵션(4~5)을 추가로 작성했습니다. 따라서 4, 5번은 옵션 입니다.
꺼내보는 것이기 때문에 -export라는 옵션을 사용합니다. 이번에도 keytool로 export 하겠습니다.
# keytool -export -alias {별칭} -keystore {키스토어 이름} -rfc -file {출력하고자 하는 인증서 파일명}
keytool -export -alias apiEncryptionKey -keystore apiEncryption.jks -rfc -file trustServer.cer
위 명령어 입력 후 다시 파일 목록 확인해보면, 지정한 파일명으로 public key가 생성된 것을 확인가능합니다. 결론적으로 trustServer.cer는 인증서 파일이 됩니다.
아래 명령어로 publicKey.jks를 생성합니다.
# keytool -import -alias {별칭} -file {읽을 파일명} -keystore {출력할 파일명}
keytool -import -alias trustServer -file trustServer.cer -keystore publicKey.jks
이게 public key로 생성이 되었는지 아까 만들어둔 private key와 비교해보겠습니다.
이번에 만들어진 publicKey.jks와 apiEncryptionKey.jks를 각 상세정보를 출력해보니, publicKey.jks는 trustecCertEntry가 나옵니다. 공개키로 생성되었다는 것을 알 수 있습니다.
이제 프로젝트에서 암호화 적용을 할 것이라서 해당 라이브러리를 추가합니다.
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'
위에서 키 만들때의 정보를 가지고 아래처럼 알맞게 정보를 넣어줍니다.
encrypt:
key-store:
location: file://${user.home}/{키가 있는 경로 입력}/apiEncryption.jks
password: test1234
alias: apiEncryptionKey
암호화: postman으로 암호화 시킬 문자열 1234를 Body의 raw(텍스트형식)으로 지정후 POST 방식으로 encrypt 요청을 합니다.
복호화: 암호화 하여 나온 값을 그대로 Body에 넣어 POST 방식으로 decrypt 요청하니 1234가 잘 나옵니다.
이제 yml 파일의 중요한 설정 값들을 이런 식으로 암호화하여 사용할 수 있습니다.
주의할 점은 yml파일에 넣을 때는 '{cipher}암호화된값' 형식으로 넣어야 암호화된 값으로 인식가능합니다.
예)
spring:
datasource:
url: jdbc:h2:tcp://localhost/~/test
username: sa
password: '{cipher}AYCEYT3MFiVwZM+m4USiZalskejalfkj' # 암호화된 값이 너무 길어 일부만 넣었습니다.
driver-class-name: org.h2.Driver