Spring 암호화/복호화 하기

Hannah·2023년 2월 3일
0
post-thumbnail

🔒 암호화

@Slf4j
@Component
public class KeyEncrypt {

    private final static String shaAlg = "SHA-256";
    private final static String aesAlg = "AES/CBC/PKCS5Padding";
    private final static String key = "MyTestCode-32Character-TestAPIKey";
    private final static String iv = key.subString(0, 16);

    public String encrypt(String text) {
        try {
            String shaKey = getShaKey(text);
            return getAesKey(shaKey);
        } catch (Exception e) {
            throw new RuntimeException("암호화 처리중에 에러가 발생했습니다. e = {}", e.getMessage());
        }
    }

	// SHA-256 키 만들기
    private String getShaKey(String text) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance(shaAlg);
        md.update(text.getBytes());
        return bytesToHex(md.digest());
    }

	// AES 키 만들기
    private String getAesKey(String text) throws Exception {
        Cipher cipher = Cipher.getInstance(aesAlg);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);

        byte[] encodedBytes = cipher.doFinal(text.getBytes());
        byte[] encrypted = Base64.getEncoder().encode(encodedBytes);
        return new String(encrypted).trim();
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        for (byte b : bytes) {
            builder.append(String.format("%02x", b));
        }
        return builder.toString();
    }

}
  • 주의할 점
    • SHA-256
      • 바이트를 이진수로 변환해야 합니다
    • AES
      • key는 16, 24, 32 바이트(영문 32자), iv는 16 바이트 이어야합니다

🔑 복호화

❗️ SHA 알고리즘은 해싱을 통해 암호화를 하기 때문에 복호화가 불가능 합니다

@Component
public class KeyDecrypt {

    private final static String alg = "AES/CBC/PKCS5Padding";
    private final static String key = "MyTestCode-32Character-TestAPIKey";
    private final static String iv = key.subString(0, 16);

    public String decrypt(String clientKey) {
        try {
            Cipher cipher = Cipher.getInstance(alg);
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);

            byte[] decoedBytes = Base64.getDecoder().decode(clientKey.getBytes());
            byte[] decrypted = cipher.doFinal(decoedBytes);
            return new String(decrypted).trim();
        } catch (Exception e) {
            throw new RuntimeException("복호화 처리중에 에러가 발생했습니다. e = {}", e.getMessage());
        }
    }

}

TMI 😂

  • 개발중 만났던 exception들
    • IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
      • Base64로 디코딩을 하지 않고, AES 알고리즘으로 복호화 했을 때 나타난 인셉션입니다
      • 복호화를 해야하는데 Chiper 모드를 암호화로 설정하고 디코딩을 했을 때에도 나타났습니다
    • InvalidKeyException: Parameters missing
      • iv를 사용하지 않고, AES로 암/복호화를 시도했을 때 나타난 에러입니다
        AES 알고리즘을 암호화할때는 iv를 지정해주지 않으면, 자동적으로 랜덤 iv를 만들어서 사용해버리기 때문에 복호화가 불가능한 상태가 됩니다
        따라서 AES 암호화를 할 때는 꼭 iv를 설정해야합니다!

👉🏻 docs

profile
backend developer

0개의 댓글