DB 칼럼 암호화를 위한 AES 대칭키 암호화 방법
최근 개인정보 보호 및 데이터 보안의 중요성이 커지면서, 데이터베이스 내 민감한 정보를 암호화하는 요구사항이 증가하고 있습니다. 본 포스트에서는 AES (Advanced Encryption Standard) 를 활용하여 DB 칼럼을 암호화하는 방법과 그 구현 예제를 소개합니다.
1. AES란?
AES는 미국 정부에서 채택한 표준 대칭키 암호화 알고리즘입니다.
- 대칭키 암호화: 암호화와 복호화에 동일한 키를 사용합니다.
- 키 사이즈: AES는 128, 192, 256비트 키를 지원하며, 키 길이가 길수록 brute force 공격에 대한 방어력이 향상됩니다.
자세한 내용은 Wikipedia의 AES 문서 를 참고하세요.
2. AES의 구성 요소
AES 암호화를 구현하기 위해 고려해야 할 핵심 요소는 다음과 같습니다.
2.1. 키 사이즈
AES는 128, 192, 256 비트 키를 지원합니다.
키의 길이가 길수록 암호화 강도는 높아지지만, 성능 및 시스템 제약에 따라 적절한 키 길이를 선택해야 합니다.
아래 코드는 Java의 KeyGenerator를 사용하여 지정한 크기의 비밀키를 생성하는 예제입니다.
private static Key getKeyFromKeyGenerator(String cipher, int keySize) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(cipher);
keyGenerator.init(keySize);
return keyGenerator.generateKey();
}
2.2. AES 모드 선택
AES 암호화에는 여러 가지 동작 모드가 있습니다. 대표적인 모드는 다음과 같습니다.
- ECB (Electronic Code Book): 동일한 평문 블록이 동일한 암호문 블록으로 암호화되어 보안상 취약할 수 있음.
- CBC (Cipher Block Chaining): 각 블록이 이전 블록의 암호문과 연계되어 안전성이 향상됨.
- CFB (Cipher Feedback) / OFB (Output Feedback): 스트림 암호화에 가까운 방식.
- CTR (Counter): 병렬 처리가 가능해 성능이 우수함.
- GCM (Galois/Counter Mode): 암호화와 인증을 동시에 제공하여 데이터 무결성을 보장함.
프로젝트의 요구사항에 따라 적절한 모드를 선택해야 합니다.
2.3. IV (Initialization Vector) 생성
CBC, CFB, OFB, CTR, GCM 모드와 같이 일부 모드에서는 동일한 키라도 매번 다른 결과를 도출하기 위해 IV (초기화 벡터) 가 필요합니다.
다음은 SecureRandom을 이용해 16바이트(128비트) IV를 생성하는 예제입니다.
public static IvParameterSpec generateIv() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
2.4. 키의 Base64 인코딩 및 저장
생성한 비밀키를 데이터베이스나 파일 등 안전한 저장소에 보관할 때는 Base64 인코딩을 활용하여 이진 데이터를 문자열로 변환할 수 있습니다.
public static String convertSecretKeyToString(SecretKey secretKey) throws NoSuchAlgorithmException {
byte[] rawData = secretKey.getEncoded();
String encodedKey = Base64.getEncoder().encodeToString(rawData);
return encodedKey;
}
저장된 Base64 인코딩 문자열을 다시 SecretKey로 변환하는 예제는 아래와 같습니다.
public static SecretKey convertStringToSecretKeyto(String encodedKey) {
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
return originalKey;
}
2.5. 암호화 (Encryption)
평문 데이터를 암호화할 때는 지정한 알고리즘, 비밀키, IV를 사용하여 Cipher 객체를 초기화한 후 암호화를 수행합니다.
public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv)
throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] cipherText = cipher.doFinal(input.getBytes());
return Base64.getEncoder().encodeToString(cipherText);
}
암호화 결과는 다시 Base64로 인코딩하여 문자열 형태로 반환됩니다.
2.6. 복호화 (Decryption)
암호문을 복호화할 때는 암호화 시 사용했던 동일한 비밀키와 IV를 사용하여 원래의 평문으로 복원합니다.
public static String decrypt(String algorithm, String cipherText, SecretKey key, IvParameterSpec iv)
throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(plainText);
}
암호문은 Base64 디코딩 후 복호화 과정을 거쳐 평문으로 변환됩니다.
3. 실제 적용 시 고려사항
- 키 관리: 비밀키는 암호화의 핵심이므로 외부에 노출되지 않도록 안전하게 관리해야 합니다. 하드코딩을 피하고 별도의 키 관리 시스템(KMS)을 사용하는 것이 좋습니다.
- IV 재사용 주의: 동일한 키로 여러 데이터를 암호화할 경우, 매번 새로운 IV를 생성해야 합니다. IV가 반복되면 암호문의 안전성이 크게 저하될 수 있습니다.
- 암호 모드 선택: 단순한 ECB 모드는 사용하지 않는 것이 좋으며, 대부분의 경우 CBC, CTR, 또는 GCM 모드를 사용하는 것이 권장됩니다.
- 패딩 (Padding): 평문의 길이가 블록 사이즈의 배수가 아닐 경우 적절한 패딩을 적용해야 하며, 암호화와 복호화 시 동일한 패딩 방식을 사용해야 합니다.
4. 참고 자료
'Java' 카테고리의 다른 글
Tomcat 서버가 JDK compiler 이용하게 설정법 (0) | 2015.04.21 |
---|