오류 발생
Caused by: jakarta.persistence.PersistenceException: Error attempting to apply AttributeConverter
[ 전체 목록 조회 ]
사용자 비밀번호를 양방향 암호화로 저장하고 저장된 모든 데이터를 출력하려고 할 때,
발생한 오류이다.
의미
JPA에서 엔티티의 속성을 데이터베이스로 변환할 때 AttributeConverter에서 문제가 발생
이 오류는 주로 엔티티 속성에 대한 변환기(@Convert)가 제대로 작동하지 않을 때 발생한다.
문제 원인
- 잘못된 키 사용 (Bad Key)
- 암호화와 복호화는 같은 키를 사용해야 한다. 만약 암호화할 때 사용한 키와 복호화할 때 사용한 키가 다르면 패딩 오류가 발생할 수 있다.
- secretKey 값이 암호화와 복호화 과정에서 동일한지 확인 필요
- IV (Initialization Vector) 문제
- AES CBC 모드에서는 IV(초기화 벡터)가 필요하다. 암호화할 때 사용한 IV와 복호화할 때 사용한 IV가 다르면 패딩 오류가 발생할 수 있다.
- 암호화할 때 생성된 IV를 복호화할 때 정확하게 사용하고 있는지 확인
- 패딩 관련 설정
- 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";
}
'Java' 카테고리의 다른 글
Java, 동등성과 동일성 정의 및 활용 예시 (VO 사용 예시) (0) | 2025.04.02 |
---|---|
Java, Immutable 불변 객체란? (0) | 2025.04.02 |
암호화, AES-256-CBC를 이용해서 암호화/복호화 하는 방법 (1) | 2025.03.24 |
암호화, 양방향 vs 단방향 암호화 (0) | 2025.03.24 |
Java, 채팅하기(Chat) (0) | 2024.08.16 |