AES를 활용해 암호화 및 복호화하기

프로젝트를 하다보면, 어떠한 중요 개인정보를 사용해야 하는 경우가 있는데요.

워낙 중요하기에, 이를 암호화하여 사용하거나 복호화하여 읽어들이는 상황이 발생합니다.

이러한 상황을 해결하기 위해 Java에서 AES를 사용하는 방법을 알아봅시다! (AES란?)

 


1. AES를 사용한 Java 코드

그럼 본격적으로 AES를 사용하여 Java코드로 작성한 암호화 및 복호화 기능을 만들어 봅시다.

 

import는 다음과 같이 추가해 줍니다.

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

 

암호화 및 복호화를 수행할 때, 사용할 고정된 대칭 키를 입력해 줍시다.

private static final String SECRET_KEY = ""; // 보안 상 값이 있다고 가정
private static final String IV = ""; // 보안 상 값이 있다고 가정

 

그 다음 암호화를 수행할 코드를 작성해 줍시다.

public static String encryptData(String inputText, SecretKeySpec secretKey, byte[] iv) throws Exception {
    Cipher cipherInstance = Cipher.getInstance("AES/CBC/PKCS5Padding");
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    cipherInstance.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
    byte[] encryptedData = cipherInstance.doFinal(inputText.getBytes(StandardCharsets.UTF_8));
    return Base64.getEncoder().encodeToString(encryptedData);
}
  • Cipher cipherInstance = ...Cipher 객체를 생성하고 AES/CBC/PKCS5Padding 모드를 사용해서 초기화합니다.
    • AES : 대칭 키 암호화
    • CBC : 블록 암호화 방식
    • PKCS5Padding : 평문의 길이가 블록 크기와 맞지 않을 경우, 부족한 부분을 패팅으로 채움(AES는 16byte)
  • IvParameterSpec ivSpec = ...초기화 벡터를 생성합니다.
  • chiperInstance.init(...) Cipher 객체를 암호화 모드로 초기화합니다.
  • byte[] encryptedData = ...평문을 byte 배열로 변환한 후, doFinal 메서드로 실제 암호화를 수행합니다.
  • return Base64...암호화된 byte 배열을 Base64로 인코딩하여 문자열로 변환한 후, 반환합니다.

그 다음 복호화를 수행할 코드를 작성합니다.

public static String decryptData(String encryptedText, SecretKeySpec secretKey, byte[] iv) throws Exception {
    Cipher cipherInstance = Cipher.getInstance("AES/CBC/PKCS5Padding");
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    cipherInstance.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
    byte[] decodedData = Base64.getDecoder().decode(encryptedText);
    byte[] decryptedData = cipherInstance.doFinal(decodedData);
    return new String(decryptedData, StandardCharsets.UTF_8);
}
  • Cipher부터 아래로 3줄암호화 때, 입력한 코드와 비슷합니다.
  • byte[] decodeData = ...Base64로 인코딩된 암호문을 디코딩하여, byte 배열로 변환합니다.
  • byte[] decrypteData = ...디코딩된 byte 배열을 doFinal 메서드를 호출하여, 복호화를 수행합니다.
  • return new String(...) 복호화된 byte 배열을 UTF-8 문자열로 변환한 후, 반환합니다.

전부 입력했으면, 다음과 같이 입력하여 실행 코드를 작성합니다.

public static void main(String[] args) {
    try {
        // 고정된 대칭 키로 SecretKeySpec 객체 생성
        SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
        
        // 암호화할 텍스트 생성
        String plainText = "Hello World";
        
        // 텍스트를 암호화
        String encryptedOutput = encryptData(plainText, secretKey, INITIALIZATION_VECTOR.getBytes(StandardCharsets.UTF_8));
        System.out.println("Encrypted Output: " + encryptedOutput);
        
        // 암호화된 텍스트를 복호화
        String decryptedOutput = decryptData(encryptedOutput, secretKey, INITIALIZATION_VECTOR.getBytes(StandardCharsets.UTF_8));
        System.out.println("Decrypted Output: " + decryptedOutput);
    } catch (Exception e) {
        System.out.println("오류 발생: " + e);
    }
}

 

실행하면, 다음과 같이 암호화 및 복호화가 이루어 지는 것을 확인할 수 있어요!

 

전체 코드

AES.java

import java.nio.charset.StandardCharsets;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESTest {
    private static final String AES_KEY = ""; // 보안 상 값이 있다고 가정
    private static final String AES_IV = ""; // 보안 상 값이 있다고 가정

    public static String encryptData(String inputText, SecretKeySpec secretKey, byte[] iv) throws Exception {
        Cipher cipherInstance = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipherInstance.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        byte[] encryptedData = cipherInstance.doFinal(inputText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    public static String decryptData(String encryptedText, SecretKeySpec secretKey, byte[] iv) throws Exception {
        Cipher cipherInstance = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipherInstance.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        byte[] decodedData = Base64.getDecoder().decode(encryptedText);
        byte[] decryptedData = cipherInstance.doFinal(decodedData);
        return new String(decryptedData, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) {
        try {
            SecretKeySpec secretKey = new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), "AES");
            String plainText = "Hello World";
            String encryptedOutput = encryptData(plainText, secretKey, AES_IV.getBytes(StandardCharsets.UTF_8));
            System.out.println("Encrypted Output: " + encryptedOutput);
            
            String decryptedOutput = decryptData(encryptedOutput, secretKey, AES_IV.getBytes(StandardCharsets.UTF_8));
            System.out.println("Decrypted Output: " + decryptedOutput);
        } catch (Exception e) {
            System.out.println("오류 발생: " + e);
        }
    }
}

2. 정리하며

지금까지 AES를 통한 Java 코드에서 암호화 및 복호화하는 과정을 알아보았습니다.

이를 통해, 중요한 정보를 암호화 및 복호화하여 상황에 맞게 안전하게 사용할 수 있을 것 같아요!