encrypt()
루틴 내에서 가능한 한 Exception
을 삼가 지 않으면 어떤 일이 벌어 졌는지 더 잘 알았을 것입니다. 함수가 null
을 반환하면 분명히 예외가 발생했고 그 내용을 알아야합니다.
사실, 예외는 다음과 같습니다
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:854)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:828)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at Encryption.encrypt(Encryption.java:20)
at Encryption.main(Encryption.java:6)
그리고 확실히 충분히, 당신의 일반 텍스트는 기본 인코딩으로, 11 바이트 것이다, 단지 11 자바 자입니다.
PHP mcrypt_encrypt
기능이 실제로 무엇인지 확인해야합니다. 작동하기 때문에, 그것은 약간의 패딩 방식을 사용하고 있습니다. Java 코드에서 어떤 코드인지 찾아야합니다.
Ok - mcrypt_encrypt
에 대한 설명서 페이지를 조회했습니다. 그것은 :
주어진 암호와 모드로 암호화 될 데이터입니다. 데이터의 크기가 n * blocksize
이 아니면 데이터에 \0
이 채워집니다.
그래서 Java에서 복제해야합니다. 여기에 한 가지 방법입니다 :
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encryption
{
public static void main(String args[]) throws Exception {
System.out.println(encrypt());
}
public static String encrypt() throws Exception {
try {
String data = "Test string";
String key = "1234567812345678";
String iv = "1234567812345678";
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
// We need to pad with zeros to a multiple of the cipher block size,
// so first figure out what the size of the plaintext needs to be.
byte[] dataBytes = data.getBytes();
int plaintextLength = dataBytes.length;
int remainder = plaintextLength % blockSize;
if (remainder != 0) {
plaintextLength += (blockSize - remainder);
}
// In java, primitive arrays of integer types have all elements
// initialized to zero, so no need to explicitly zero any part of
// the array.
byte[] plaintext = new byte[plaintextLength];
// Copy our actual data into the beginning of the array. The
// rest of the array is implicitly zero-filled, as desired.
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return new sun.misc.BASE64Encoder().encode(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
을 그리고 내가 얻을 실행하면
iz1qFlQJfs6Ycp+gcc2z4w==
하는 당신의 PHP 프로그램을 가지고 것입니다.
업데이트 (2016 6월 12일) : 문서화 된 base64로 코덱 자바 (8)으로, JavaSE 마지막으로 제공됩니다. 그래서 그 대신
return new sun.misc.BASE64Encoder().encode(encrypted);
의 당신은 오히려 문서화되지 않은 내부 방법을 사용하는 것보다 Base64 인코딩/디코딩을위한 제 3 자 라이브러리 (예 : commons-codec
)를 사용, 또는
return Base64.Encoder.encodeToString(encrypted);
같은 것을해야한다.
고맙습니다. QuantumMechanic. 아주 잘 설명했다. – user812120
데이터의 끝에있는 0 바이트와 패딩을 구별 할 수 없으므로 일반적으로 0 기반 패딩이 사용되지 않습니다.대신 PKCS # 7 패딩을 사용해야합니다 (Java에서 "PKCS5Padding"). 또한 sun. * 기능을 사용하면 모든 Java 호환성 지침에 실패합니다. –