Jasypt 를 적용할 때 주의할 점

Yoonhwan Kim·2023년 5월 26일
1

결론

https://www.devglan.com/online-tools/jasypt-online-encryption-decryption

  1. 해당 사이트를 통해서 암호화를 했을 경우에는 암호화 알고리즘을 PBEWithMD5AndDES 로 설정해야 한다.

  2. Jasypt 설정으로 등록할 Bean 이름은 jasyptStringEncryptor 로 해야한다.

번외). @EnableEncryptableProperties 가 무조건 필요한지는 모르겠다.
( 저는 없어도 됐습니다. )


Jaspyt 를 사용하는 방법에 대한 글이 많습니다.

Jasypt 를 소개하는 글이 아니라서 사용방법을 굳이 쓰지 않고싶지만 간단하게 작성하면 다음과 같이 쓰면됩니다.

적용 준비설정

build.gradle

implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5")

Configuration Class

해당 클래스에서는 Bean 이름이 중요합니다.

jasyptStringEncryptor 이 이름으로 등록되어야 가능합니다.


@Configuration
internal class JasyptConfig {
@Bean
fun jasyptStringEncryptor(): StringEncryptor? {
    val encryptor = PooledPBEStringEncryptor()
    val config = SimpleStringPBEConfig()
    config.password = encryptionPassword // 암호화할 때 사용하는 키
    config.algorithm = "PBEWithMD5AndDES" // 암호화 알고리즘
    config.setKeyObtentionIterations("1000") // 반복할 해싱 회수
    config.setPoolSize("1") // 인스턴스 pool
    config.providerName = "SunJCE"
    config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") // salt 생성 클래스
    config.stringOutputType = "base64" //인코딩 방식
    encryptor.setConfig(config)
    return encryptor
}
}

application.yml

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: ENC(사이트를 통해 암호화한 값)

상황

현재 저의 상황은 이렇습니다.

1) https://www.devglan.com/online-tools/jasypt-online-encryption-decryption => 해당 사이트에서 평문을 암호화 하였다.

2) 설정을 다음과 같이 했다.

    @Bean
    fun jasyptStringEncryptor(): PooledPBEStringEncryptor {
        val encryptor = PooledPBEStringEncryptor()
        encryptor.setPoolSize(4)
        encryptor.setPassword(encryptionPassword)
        encryptor.setAlgorithm("PBEWithMD5AndTripleDES")
        return encryptor
    }

문제 1

OAuth2 구현 중 Key 를 암호화 하기 위해서 설정 하는 도중에 발생.

💡 Failed to bind properties under 'spring.security.oauth2.client.registration.google.client-id' to java.lang.String:

Reason: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.security.oauth2.client.registration.google.client-id' to java.lang.String

분명 블로그나 참고 자료들을 봤을때랑 설정이 살짝다르긴 하지만
필요한 부분들은 있기때문에 동작하는데는 무리가 없다 생각했습니다.

그런데 바인딩 예외가 발생하는데 디버깅을 해봐도 알 수 없었습니다.


문제는 암호화 알고리즘 에 있었는데요,

💡 By default, Jasypt uses `PBEWithMD5AndDES` encryption algorithm but it provides options to select other stronger encryption options too such as `PBEWithMD5AndTripleDES` The free Jasypt Online Encryption and Decryption tool below provides option for one way as well two way(simple) encryption and [decryption.It](http://decryption.it/) also provides option to compare a plain text with Jasypt encrypted password.

위에 작성한 암호화를 할 수 있는 홈페이지에 작성된 문단을 첨부했습니다.

간단히 요약하면 Jasypt 는 기본적으로 PBEWithMD5AndDES 암호화 알고리즘을 이용하고 있으며, 더 강력한 알고리즘인 PBEWithMD5AndTripleDES 방식 또한 제공한다고 합니다.

비교를 좀 해본결과 해당 홈페이지에서 암호화한 값은 PBEWithMD5AndDES 알고리즘을 통해서 암호화를 하고 있었습니다.

저 같은 경우 설정을 보시다시피 encryptor.setAlgorithm("PBEWithMD5AndTripleDES")
즉, PBEWithMD5AndTripleDES 알고리즘으로 설정을 했기 때문에 암호화 방식이 달라서 제대로된 해석이 불가능했었습니다.

해당 알고리즘을 기본 알고리즘 방식인 PBEWithMD5AndDES 를 설정해서 문제를 해결했습니다.

만약 PBEWithMD5AndTripleDES 를 사용하시려면 테스트 코드를 작성해서 평문을 암호화 시키면 가능한 것으로 봅니다.


추가 사항

내부 동작 관련

설정 도중에 문제가 발생했던 부분은 아니지만, 내부 동작 관련해서 말씀을 드리면.

기본적으로 Jasypt 에서 문자를 암호화하는 과정을 구현한 구현체가 StringEncryptor 로 보고있는데요, Jasypt 는 사실 인코딩 객체의 이름을 jasyptStringEncryptor 으로 고정적으로 사용하고 있습니다.

그래서 설정을 만드실 떄 jasyptStringEncryptorBean 이름을 구성하셔야 자동설정 과정에서 해당 설정을 읽어들입니다.

자동설정을 하는 코드 일부분을 발췌했습니다.

@Configuration
public class EncryptablePropertyResolverConfiguration {

    private static final String ENCRYPTOR_BEAN_PROPERTY = "jasypt.encryptor.bean";
    private static final String ENCRYPTOR_BEAN_PLACEHOLDER = String.format("${%s:jasyptStringEncryptor}", ENCRYPTOR_BEAN_PROPERTY);

@Bean(name = ENCRYPTOR_BEAN_NAME)
    public StringEncryptor stringEncryptor(
            final EnvCopy envCopy,
            final BeanFactory bf) {
        final String customEncryptorBeanName = envCopy.get().resolveRequiredPlaceholders(ENCRYPTOR_BEAN_PLACEHOLDER);
        final boolean isCustom = envCopy.get().containsProperty(ENCRYPTOR_BEAN_PROPERTY);
        return new DefaultLazyEncryptor(envCopy.get(), customEncryptorBeanName, isCustom, bf);
    }
    ....
}

그 이유는 application.yml 파일에 기본적으로 jasypt.encryptor.bean 이라는 propertyjasyptStringEncryptor 의 문자열 값이 들어가서 설정이 되어있기 떄문에 해당 값으로 설정된 Bean 을 읽어들이는 것으로 판단했습니다.

왜냐하면 굳이 @Configuration 으로 설정하지 않아도 application.yml 으로 설정해도 동작이 되기 떄문입니다.

@EnableEncryptableProperties

@EnableEncryptableProperties 어노테이션이 설정 중에 필요한 것으로 알고 있는데, 저는 선언하지 않고도 동작이 잘 됐습니다. 해당 어노테이션이 자동설정을 수행하고 있기는 한데, 없어도 같은 자동설정을 수행하길래 굳이 포함시키진 않았네요.

0개의 댓글