프로젝트/장기 프로젝트

Hustle #8. Jasypt 암호화 라이브러리 적용

Chipmunks 2023. 9. 3. 22:08
728x90

 

안녕하세요.

저번 포스팅까지는 AWS 인프라 설정을 세 차례나 진행했습니다.

AWS 인프라 설정에 꽤 긴 시간을 공들였는데요.

이번 포스팅에선 허슬 프로젝트에 Jasypt 암호화 라이브러리를 적용해보고자 합니다.

 

왜 Jasypt 암호화 라이브러리를 적용하나요?

지난 번에 스프링 부트에서 Jasypt 암호화 라이브러리를 적용해 본 포스팅을 올렸습니다.

2023.06.20 - [Back-End/Spring 자료실] - [스프링 부트] Jasypt 설정 암호화로 Github Repo 에 안전하게 올리기

 

[스프링 부트] Jasypt 설정 암호화로 Github Repo 에 안전하게 올리기

안녕하세요. 스프링 부트에서 Jasypt 라이브러리를 사용해서 설정을 암호화하는 방법을 알아봅시다. application.yml 파일에 아래와 같이 DB 접속 정보를 저장해둔다면, Github 레포에 올리지 못하겠죠?

itchipmunk.tistory.com

팀원이 application.yml 을 .gitignore 에 포함시키고 단체방에 아래처럼 application.yml 내용을 공유했는데요.

위 포스팅에서 나온 대로 역시나, application.yml 설정이 변경 되는 대로 수시로 팀원 4명이 다 업데이트 해야 하는 불편함이 있었습니다.

단체방에서 공유한 application.yml

암호화된 채로 깃허브 레포지토리에도 안전하게 올릴 수 있으면

더 이상 수동으로 업데이트하지 않아도 됩니다.

 

Jasypt 암호화 라이브러리를 사용하면 어떻게 되나요?

Jasypt 암호화 라이브러리를 사용하면 아래처럼 암호화를 시킬 수 있습니다.

spring:
  jpa:
    hibernate:
      ddl-auto: none
  datasource:
    driver-class-name: ENC(4zv7k66bl0S9CkPE2DhjRaIxsA8E9l+kWvMMPExbdHg==)
    url: ENC(n4BgVC45DNHZ7Dv+eIGHp6NmDrt9UOq+Eb4lRi9oP6by9eJ3NuZGKrnk1QUdrQ4J2QFWMTvqV9AuCG2y500vtLwPJngcLnbAz1JxooZAJoNCxYOyW1HwFnOY0zEqGA45hhAZxCpZEKn4IPiX8JOxYZpl13BDw/qoExcYplGW3GJVD3mhD1Yqy2B)
    username: ENC(3IlDHh9Hevic4hySvk20q)
    password: ENC(Z9yNmaE1Sk5DKZerehtnl+GNz3obGfbaLU=)

 

암호화 키는 팀 내부에서 공유하고 관리됩니다.

깃허브에 올려도 다른 사람은 암호화 키를 모르기에 원래 문자열(평문)이 무엇인지 알 수 없습니다.

 

Jasypt 암호화 라이브러리 적용

build.gradle 에 아래 jasypt 의존성을 추가합니다.

dependencies {
	...
	// jasypt
	implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'
    	...
}

JasyptConfig 설정 빈을 등록합니다.

package com.sporthustle.hustle.common.config;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JasyptConfig {
  @Value("${jasypt.encryptor.password}")
  private String key;

  private static final String ALGORITHM = "PBEWithMD5AndDES";

  @Bean("jasyptStringEncryptor")
  public StringEncryptor stringEncryptor() {
    PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
    SimpleStringPBEConfig config = new SimpleStringPBEConfig();
    config.setPassword(key);
    config.setAlgorithm(ALGORITHM);
    config.setKeyObtentionIterations("1000");
    config.setPoolSize("1");
    config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
    config.setStringOutputType("base64");
    encryptor.setConfig(config);
    return encryptor;
  }
}

암호화 키는 외부에서 주입합니다.

application.yml 에 넣으면 암호화 키가 그대로 노출되는데요.

그 대신 서버를 구동할 때 jasypt.encryptor.password 키로 주입합니다.

 

허슬 팀 같은 경우엔 암호화 키는 아래처럼 노션에 공유했습니다.

 

이제부터 빌드할 때나 Jar 파일을 실행할 때 jasypt.encryptor.password 값을 주입해야 합니다.

# 허슬 프로젝트 빌드
$ ./gradlew build -Djasypt.encryptor.password=''
# Jar 파일 실행
$ nohup java -jar hustle-v0.0.1.jar --jasypt.encryptor.password='' &

 

암호화된 문자열은 어떻게 얻나요?

그렇다면 암호화된 문자열은 어떻게 얻는걸까요?

허슬 서버를 구동할 때마다 암호화 된 문자열을 얻는 코드를 작성해야 할까요?

하나의 방법일 순 있지만 실제 서버 실행에 필요한 코드가 아니고 매 번 주석 처리 하기도 번거로울 것 같습니다.

다른 방법은 무엇이 있을까요?

바로 테스트 코드를 활용합니다.

package com.sporthustle.hustle.jasypt;

import static org.assertj.core.api.Assertions.assertThat;

import com.sporthustle.hustle.common.config.JasyptConfig;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.junit.jupiter.api.Test;

public class JasyptTest extends JasyptConfig {

  @Test
  public void 평문_암호화_결과_출력() {
    String encryptKey = System.getProperty("jasypt.encryptor.password");

    // 암호화할 평문 작성하기
    String plainText = "";

    StandardPBEStringEncryptor jasypt = new StandardPBEStringEncryptor();
    jasypt.setPassword(encryptKey);

    String encryptedText = jasypt.encrypt(plainText);
    String decryptedText = jasypt.decrypt(encryptedText);

    // 테스트 결과에서 암호문 확인 가능
    System.out.println(encryptedText);

    assertThat(plainText).isEqualTo(decryptedText);
  }
}

 

테스트 코드를 작성하고 실행할 때 마다 테스트 결과에서 암호화된 문자열을 얻을 수 있게 합니다.

plainText 변수에 평문을 입력하고 테스트를 실행합니다.

테스트 결과에서 암호문을 확인합니다.

 

테스트 코드를 실행할 때에도 jasypt.encryptor.password 을 주입해야 합니다.

build.gradle 에서 Gradle 빌드 시 테스트 코드를 실행하는 테스트 단계에서 프로퍼티를 가져와야 합니다.

tasks.named('test') {
	useJUnitPlatform()
	systemProperty "jasypt.encryptor.password", System.getProperty("jasypt.encryptor.password")
}

인텔리제이 IDE 에서 실행할 때 메인 어플리케이션 클래스와 테스트 클래스에 VM Options 을 추가하여 적용합니다.

-Djasypt.encryptor.password=암호화키

마무리

이제 .gitignore 에서 다시 application.yml 파일이 추가되도록 수정합니다.

암호화 키를 노출되지 않도록 주의하기만 하면 됩니다.

더 이상 단체방에서 매 번 application.yml 파일을 수정하지 않아도

안심하면서 깃허브 레포지토리에 올려 형상 관리를 할 수 있게 했습니다.

 

단체방에서 공유하던 팀원도, 처음에는 왜 Jasypt 를 적용하는 지 이해를 못했었어요.

의존성 하나 추가하고 설정만 조금 건드리면 모두가 편한 걸 경험하니

Jasypt 의 편리함을 알게 되고 application.yml 이 수정할 때 마다 공유하지 않아도 된다는 점이

무척 편하다고 하셨습니다. ☺️