JWT Payload를 암호화해야하는 이유
보통 jwt는 사용자의 고유id, email, 이름같은 중요한 정보를 담고있다.
그런데 이 기본jwt는 이 정보를 Base64로만 인코딩하기때문에 누구나 jwt.io에서 쉽게 디코딩해서 볼 수 있다.
보통 이 jwt토큰은 개발자 도구에서 쉽게 접근가능하기 때문에 중요한 정보가 이런식으로 노출된다면 골치아파진다.
그래서 저 PAYLOAD를 암호화한다는 거다.
암호화 방법에는 AES, RSA, AES+RSA 등 다양한 방법이 존재하는데
이 중 AES암호화가 대중적인 이유는 보통 RSA보다 100배 이상 빠르기 때문이다.
jwt토큰은 거의 모든 요청마다 검증되어야 하기에 서버 부하를 크게 줄일 수 있다.
java에서의 AES 암호화/복호화
secret key와 암호화 대상을 함께 Ciper로 암호화하면 끝이다. java코드로도 쉽게 구현가능하다
public String encrypt(String plainText) {
try {
String aesSecretKey = jwtSecurityProperties.getSecret().getAesKey();
SecretKeySpec secretKey = new SecretKeySpec(aesSecretKey.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encryptedBytes);
} catch (Exception e) {
throw new EncryptException(ServerErrorCode.TOKEN_ENCRYPTION_FAILED);
}
}
public String decrypt(String encryptedText) {
try {
String aesSecretKey = jwtSecurityProperties.getSecret().getAesKey();
SecretKeySpec secretKey = new SecretKeySpec(aesSecretKey.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decodedBytes = Base64.getDecoder().decode(encryptedText);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes);
} catch (Exception e) {
throw new UnAuthorizedException(AuthErrorCode.TOKEN_DECRYPTION_FAILED);
}
}
자바에서 Ciper기능을 제공해주기때문에 환경변수 등에서 secretKey를 가져와서 정해진 틀에 따라 암호화-복호화 가능하다.
이걸 spring에서 사용할 때는 암호화와 복호화가 필요한 각각 시점을 생각하면 적용하기 쉽다.
일반적으로,
1. Jwtfilter: 요청을 받는 곳은 보통 jwtfilter이고, 이곳에서 복호화된 토큰으로 필터링을 거쳐야 한다.
2. JwtUtil: token을 생성하거나 jwt를 파싱을 담당하므로 메인 encrypt와 decrypt는 이곳에서 진행된다.
jwtUtil의 토큰 생성을 담당하는 메서드다.
원래는 userId와 role을 각각 jwtBuilder에 넣었는데 이젠 aes암호화 과정을 거친 후 같이 저장된다.
이렇게 encryptedPayload 통째로 넣으면 된다
암호화 된 토큰을 복호화 할 때는 똑같이 aes256Util.decrypt 과정을 거치고
암호화 할 때 userId와 role사이에 : 를 넣어줬으므로 이걸 split로 배열로 만들고 편히 사용하면 된다
결과
평소처럼 auth/login을 하면 외형은 평소와 같지만
이제 Payload가 암호화 된 것을 볼 수 있다
여담으로 속도차이가 궁금해서 이전 기록을 찾아봤는데 티도 안 난다
aes 적용 이전이나 이후나 300-400ms정도 걸리는 듯
'팀 프로젝트 > 최종 프로젝트' 카테고리의 다른 글
DB에 데이터 랜덤하게 삽입하기 (2) 동기화 문제 해소 (0) | 2025.02.22 |
---|---|
DB에 데이터 랜덤하게 삽입하기 (1) 커스텀 스케줄 어노테이션 구현 (0) | 2025.02.21 |
IP와 Email 차단을 DB로 옮기고 IP 전역 밴 추가하기 (0) | 2025.02.20 |