Java에서 AES를 사용하기 위해 key, iv 등 생성하는 코드
- 알고리즘은 AES-128, AES-192, AES-256 어떤 걸 사용하느냐에 따라 key, iv자체의 size가 달라질 수 있습니다
- 본 글에서는 AES/CBC/PKCS5Padding 256 을 기반으로 했습니다.
Java에서 암복호화에 사용하기 위한 key, iv 는 어떻게 만들까?
- 현업에서는 key, iv를 데이터 제공 측과 소비측에서 양쪽에서 key, iv를 공유하는데
key, iv를 만드는 방법도 다양했습니다.
- 본 글에서 다양한 케이스를 코드로 처리한 내용을 적어봅니다.
- 대체로 key,iv는 base64혹은 hex등으로 encode해서 저장하고, runtime에 decode해서 쓰는 것이 일반적입니다.
key 만들기 다양한 방법
- base64등 encode 없이 그냥 문자열로 만들기
public String generateRandomString() {
String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+";
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < 32; i++) {
sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
}
return sb.toString();
}
- base64는 java.util 을 쓰기도 하고 apache.commons.codec.binary등을 쓸 수 있습니다.
public void keyGenerator() throws NoSuchAlgorithmException {
// 1. Secret Key 생성 (AES-256)
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256); // AES-256 사용
SecretKey secretKey = keyGenerator.generateKey();
// 2. IV 생성 (AES CBC 모드에서는 16바이트 IV 필요)
byte[] iv = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(iv);
// 3. Base64로 인코딩하여 출력
System.out.println("Secret Key (Base64): " + Base64.getEncoder().encodeToString(secretKey.getEncoded()));
System.out.println("IV (Base64): " + Base64.getEncoder().encodeToString(iv));
}
public void generateBase64RandomKey() {
int AES_KEY_SIZE = 32; //256 bit
int IV_SIZE = 16;
byte[] secretKeyBytes = new byte[AES_KEY_SIZE];
byte[] ivBytes = new byte[IV_SIZE];
new SecureRandom().nextBytes(secretKeyBytes);
new SecureRandom().nextBytes(ivBytes);
log.info("secretKeyBytes: {}", Base64.getEncoder().encodeToString(secretKeyBytes));
log.info("ivBytes: {}", Base64.getEncoder().encodeToString(ivBytes));
}
public void generateHexRandomKey() {
int AES_KEY_SIZE = 32; //256 bit
int IV_SIZE = 16;
byte[] secretKeyBytes = new byte[AES_KEY_SIZE];
byte[] ivBytes = new byte[IV_SIZE];
new SecureRandom().nextBytes(secretKeyBytes);
new SecureRandom().nextBytes(ivBytes);
log.info("secretKeyBytes: {}", bytesToHex(secretKeyBytes));
log.info("ivBytes: {}", bytesToHex(ivBytes));
}
- 32byte(256bit) 랜덤 문자열 만들고, base64 encode 하기
public void generateRandomStringAndGenerateKey() {
int size = 32;
String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+";
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder(size);
for (int i = 0; i < size; i++) {
sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
}
String secretKeyBase64 = Base64.getEncoder().encodeToString(sb.toString().getBytes());
String ivBase64 = Base64.getEncoder().encodeToString(sb.substring(0,16).getBytes());
}
- 32byte 문자열을 사용해서 base64 encode 하기
public void generateKeyWithString() {
String input = "YOUR 32자리 문자열";
String secretKeyBase64 = Base64.getEncoder().encodeToString(input.getBytes());
String ivBase64 = Base64.getEncoder().encodeToString(input.substring(0,16).getBytes());
String decoded = new String(Base64.getDecoder().decode(secretKeyBase64));
}