Java

암호화, 오류 Error attempting to apply AttributeConverter

greenyellow-s 2025. 3. 25. 16:57
728x90
반응형


오류 발생

Caused by: jakarta.persistence.PersistenceException: Error attempting to apply AttributeConverter

 

[ 전체 목록 조회 ]

사용자 비밀번호를 양방향 암호화로 저장하고 저장된 모든 데이터를 출력하려고 할 때,

발생한 오류이다.


의미

JPA에서 엔티티의 속성을 데이터베이스로 변환할 때 AttributeConverter에서 문제가 발생

이 오류는 주로 엔티티 속성에 대한 변환기(@Convert)가 제대로 작동하지 않을 때 발생한다.

 


문제 원인

 

  1. 잘못된 키 사용 (Bad Key)
    • 암호화와 복호화는 같은 키를 사용해야 한다. 만약 암호화할 때 사용한 키와 복호화할 때 사용한 키가 다르면 패딩 오류가 발생할 수 있다.
    • secretKey 값이 암호화와 복호화 과정에서 동일한지 확인 필요
  2. IV (Initialization Vector) 문제
    • AES CBC 모드에서는 IV(초기화 벡터)가 필요하다. 암호화할 때 사용한 IV와 복호화할 때 사용한 IV가 다르면 패딩 오류가 발생할 수 있다.
    • 암호화할 때 생성된 IV를 복호화할 때 정확하게 사용하고 있는지 확인
  3. 패딩 관련 설정
    • AES 암호화에서 패딩 방식에 맞지 않게 데이터를 처리할 경우에도 BadPaddingException이 발생할 수 있다.
    • 사용하고 있는 PKCS5Padding이 올바르게 적용되었는지 확인

 


원인 찾기

1. @Slf4j - log.info()를 통해서 현재 오류가 나는 부분 찾았다.

String cipherText = encryptedText.substring(IV_STRING_LENGTH);
byte[] encryptedBytes = HexFormat.of().parseHex(cipherText);
byte[] plainBytes = cipher.doFinal(encryptedBytes);
String plainText = new String(plainBytes, StandardCharsets.UTF_8);

 

 

 

encryptedBytes까지는 로그가 잘 나온다.

plainBytes부터 로그가 안나오고 에러문구가 출력된다.

 

즉, 복호화가 안되고 있다는 의미..

 

하지만 저장도 잘되고 코드에는 별 이상이 없다.

 

 

2. JPA 구문을 변경해 보았다.

 

findAll() - 500 오류 발생

Page<UserMasterAuth.UserMasterAuthDTO> userMasterAuthDTO = this.userMasterAuthRepository
  .findAll(pageable)
  .map(entity -> ModelConverter.MODEL_MAPPER.map(entity, UserMasterAuth.UserMasterAuthDTO.class));

 

findByTheDay() - 200 조회 성공

LocalDate theDay = LocalDate.now();
Page<UserMasterAuth.UserMasterAuthDTO> userMasterAuthDTO = this.userMasterAuthRepository
  .findByTheDay(theDay, pageable)
  .map(entity -> ModelConverter.MODEL_MAPPER.map(entity, UserMasterAuth.UserMasterAuthDTO.class));

 

날짜에 조건을 넣어 일부만 조회하니 가져온다.

 

 

3. 전체 조회만 안되는 이유 찾기

Chat GPT

findAll() 메서드에서 오류가 발생하는 이유는 @Convert 어노테이션으로 설정된 UserMasterAuthEntityConverter.MasterPasswordConverter가 암호화된 값을 처리하는데 문제가 생기기 때문일 수 있습니다.
특히, findByTheDay와는 다르게 findAll()은 UserMasterAuthEntity 전체 데이터를 조회하는데, 그 중에서 masterPassword 필드를 암호화 및 복호화하는 과정에서 문제가 발생하는 경우가 많습니다.

문제의 원인
- 암호화와 복호화 문제: masterPassword는 암호화된 상태로 저장되어 있으며, findAll()을 사용할 때 @Convert 어노테이션을 사용하여 복호화를 시도할 때 BadPaddingException 또는 다른 암호화 관련 오류가 발생할 수 있습니다.
- 페이지 네이게이션: findAll() 메서드는 페이지네이션 없이 데이터를 모두 가져오고, 그 과정에서 복호화가 이루어집니다. 이때 데이터가 많아지면 복호화가 제대로 처리되지 않거나 키 문제, 패딩 문제 등이 발생할 수 있습니다.

 

 

이때 데이터가 많아지면 복호화가 제대로 처리되지 않거나 키 문제, 패딩 문제 등이 발생할 수 있다?

 

@Query를 사용해서 가져오면 잘 될까 해서 시도 - 오류

@Query("SELECT u FROM UserMasterAuthEntity u")
Page<UserMasterAuthEntity> findAllUserMasterAuth(Pageable pageable);

 

 

 

 

4. 일부분은 복호화가 되고 일부분은 복호화가 안되고 있어서 발생하는 오류 같아 예외처리를 넣어보기로 함

 

암호화되어 저장된 데이터를 복호화해서 가져오는 구문에서

복호화 과정이 오류가 나면 "error_decryption"을 복호화 비밀번호 대신 반환하도록 수정

 

→ 오류 발생하지 않고 모든 데이터가 조회된다.

 

 

5. 결론

 

앞서 있던 데이터가 현재 작성된 복호화 기준과 맞지 않아 복호화 과정에서 오류가 난것 같다.


해결

try{
  // 암호화 문자에서 IV 추출
  String ivText = encryptedText.substring(0, IV_STRING_LENGTH);
  byte[] ivBytes = HexFormat.of().parseHex(ivText);
  IvParameterSpec iv = new IvParameterSpec(ivBytes);

  ...
  
  // 평문 응답
  return plainText;
} catch (Exception e){
  return "error_decryption";
}

 

728x90
반응형