1. AES 256 암호화
- AES 256은 키가 256bit 즉 32바이트 문자열 이어야 합니다.
- 이 예제에서는 임의의 길이의 키 문자열을 받아서 랜덤 salt 를 첨가해서 해시하여 256bit 키를 생성합니다.
- 암호화 모드는 CBC를 사용하고, 길이를 일정하게 하는데 PKCS5 패딩을 사용합니다.
- salt를 사용하므로 동일한 값을 암호화 하더라도 암호된 값이 동일하지 않습니다.
- 결과값에는 salt와 iv값을 추가하여 Base64로 엔코딩 하여 반환합니다.
- Java 8에는 Base64 기능이 포함되어 있지만, 그 이전 버전의 JDK를 사용한다면 apache common codec 라이브러리 등을 사용하여 Base64 엔코딩 기능을 사용할 수 있습니다.
public static String encryptAES256(String msg, String key) throws Exception {
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
byte[] saltBytes = bytes;
// Password-Based Key Derivation function 2
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
// 70000번 해시하여 256 bit 길이의 키를 만든다.
PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, 70000, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// 알고리즘/모드/패딩
// CBC : Cipher Block Chaining Mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
// Initial Vector(1단계 암호화 블록용)
byte[] ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(msg.getBytes("UTF-8"));
byte[] buffer = new byte[saltBytes.length + ivBytes.length + encryptedTextBytes.length];
System.arraycopy(saltBytes, 0, buffer, 0, saltBytes.length);
System.arraycopy(ivBytes, 0, buffer, saltBytes.length, ivBytes.length);
System.arraycopy(encryptedTextBytes, 0, buffer, saltBytes.length + ivBytes.length, encryptedTextBytes.length);
return Base64.getEncoder().encodeToString(buffer);
}
2. 암호화된 내용을 복호화
public static String decryptAES256(String msg, String key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
ByteBuffer buffer = ByteBuffer.wrap(Base64.getDecoder().decode(msg));
byte[] saltBytes = new byte[20];
buffer.get(saltBytes, 0, saltBytes.length);
byte[] ivBytes = new byte[cipher.getBlockSize()];
buffer.get(ivBytes, 0, ivBytes.length);
byte[] encryoptedTextBytes = new byte[buffer.capacity() - saltBytes.length - ivBytes.length]; buffer.get(encryoptedTextBytes);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, 70000, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = cipher.doFinal(encryoptedTextBytes);
return new String(decryptedTextBytes);
}
3. 실행예제
public class CryptoTest { public static void main(String[] args) throws Exception {
String plainText = "Hello, World!";
String key = "secret key";
System.out.println("MD5 : " + plainText + " - " + CryptoUtil.md5(plainText));
System.out.println("SHA-256 : " + plainText + " - " + CryptoUtil.sha256(plainText));
String encrypted = CryptoUtil.encryptAES256("Hello, World!", key);
System.out.println("AES-256 : enc - " + encrypted); System.out.println("AES-256 : dec - " + CryptoUtil.decryptAES256(encrypted, key));
}
}
참조 : https://offbyone.tistory.com/286
'게으른 개발자의 끄적거림' 카테고리의 다른 글
Java 암호화 복호화 간단 코드(feat. AES) (0) | 2023.05.24 |
---|---|
Java Xss 대처 방안 (0) | 2023.05.23 |
JSTL 설명 및 사용 방법 (0) | 2023.05.21 |
이클립스 자주 쓰는 단축키 모음 (0) | 2023.05.18 |
VPN 프로그램으로 IP 지역 우회 방법 꿀팁 (0) | 2023.05.17 |