현재 구축된 시스템에 PHP5.2인데 JAVA와 호환이 가능한 코드가 필요하여 적어봅니다.
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class AES256Example {
// zero-padding (mcrypt 기본 동작)
private static byte[] zeroPad(byte[] data, int blockSize) {
int remainder = data.length % blockSize;
if (remainder == 0) {
return data; // mcrypt는 블록 크기와 정확히 맞으면 추가 패딩을 하지 않습니다.
}
int paddedLen = data.length + (blockSize - remainder);
byte[] padded = new byte[paddedLen];
System.arraycopy(data, 0, padded, 0, data.length);
// 나머지 바이트는 0x00으로 자동 초기화되므로 따로 채울 필요 없음
return padded;
}
// trailing NUL(0x00) 제거 (PHP의 rtrim(..., "\0")과 동일 동작)
private static byte[] trimTrailingZeros(byte[] data) {
int i = data.length;
while (i > 0 && data[i - 1] == 0) i--;
return Arrays.copyOf(data, i);
}
public static String encrypt(String plainText, String key, String iv) throws Exception {
if (key == null || key.getBytes(StandardCharsets.UTF_8).length != 32) {
throw new IllegalArgumentException("Key must be 32 bytes (AES-256).");
}
if (iv == null || iv.getBytes(StandardCharsets.UTF_8).length != 16) {
throw new IllegalArgumentException("IV must be 16 bytes.");
}
byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
byte[] padded = zeroPad(plainBytes, 16);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); // NoPadding — we 처리한 패딩을 사용
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(padded);
return Base64.getEncoder().encodeToString(encrypted);
}
public static String decrypt(String base64CipherText, String key, String iv) throws Exception {
if (key == null || key.getBytes(StandardCharsets.UTF_8).length != 32) {
throw new IllegalArgumentException("Key must be 32 bytes (AES-256).");
}
if (iv == null || iv.getBytes(StandardCharsets.UTF_8).length != 16) {
throw new IllegalArgumentException("IV must be 16 bytes.");
}
byte[] cipherBytes = Base64.getDecoder().decode(base64CipherText);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decryptedPadded = cipher.doFinal(cipherBytes);
byte[] trimmed = trimTrailingZeros(decryptedPadded);
return new String(trimmed, StandardCharsets.UTF_8);
}
// 테스트 예제
public static void main(String[] args) throws Exception {
String key = "12345678123456781234567812345678"; // 32바이트
String iv = "1234567890123456"; // 16바이트
String plain = "story4some1";
String enc = encrypt(plain, key, iv);
System.out.println("Base64 암호문: " + enc);
String dec = decrypt(enc, key, iv);
System.out.println("복호화: " + dec);
}
/*
Base64 암호문: GK3yp1MRRJaHHfeTQzOMHQ==
복호화: story4some1
*/
}
<?php
function aes256_encrypt($plaintext, $key, $iv) {
// AES-256-CBC 암호화
$ciphertext = mcrypt_encrypt(
MCRYPT_RIJNDAEL_128, // 블록 암호: AES (Rijndael-128)
$key, // 키 (32바이트)
$plaintext, // 평문
MCRYPT_MODE_CBC, // CBC 모드
$iv // IV (16바이트)
);
return base64_encode($ciphertext); // 안전하게 Base64 인코딩
}
function aes256_decrypt($ciphertext_base64, $key, $iv) {
$ciphertext = base64_decode($ciphertext_base64);
$plaintext = mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$key,
$ciphertext,
MCRYPT_MODE_CBC,
$iv
);
return rtrim($plaintext, "\0"); // PKCS#7 패딩 제거
}
// ----------------- 테스트 -----------------
$key = "12345678123456781234567812345678"; // 32바이트 (AES-256)
$iv = "1234567890123456"; // 16바이트 (AES 블록 크기)
$plain = "story4some1";
echo "평문: $plain\n";
$enc = aes256_encrypt($plain, $key, $iv);
echo "암호문 (Base64): $enc\n";
$dec = aes256_decrypt($enc, $key, $iv);
echo "복호화 결과: $dec\n";
/*
평문: story4some1
암호문 (Base64): GK3yp1MRRJaHHfeTQzOMHQ==
복호화 결과: story4some1
*/
?>
참고로 PHP7부터는 mcrypt가 제거되었으므로 다른 방법을 사용해야 합니다.

반응형
'꼰대개발자 > 프로그래밍 언어' 카테고리의 다른 글
| X(구 트위터)에 자동으로 포스팅하기 (0) | 2026.05.13 |
|---|---|
| Laravel 13 세팅할 때 발생한 오류에 대한 정리 (0) | 2026.04.15 |
| PHP5.2와 JAVA에서 호환이 가능한 AES256 암호화(2) (1) | 2025.09.01 |
| 스프링 실무에서 MyBatis와 JPA를 비교해 본다. (feat. 영속성 컨텍스트) (4) | 2025.08.14 |
| 객체 지향이라? 오브젝트 지향이라고 불러다오... (9) | 2025.08.08 |