ルーチンException
内で可能なものを単純に飲み込まなかった場合は、何が起こっているのかをよりよく理解できたはずです。encrypt()
関数が戻ってきた場合は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 Java文字であり、デフォルトのエンコーディングでは11バイトになります。
mcrypt_encrypt
PHP関数が実際に何をするかを確認する必要があります。それが機能するので、それは明らかにいくつかのパディングスキームを使用しています。あなたはそれがどれであるかを見つけて、あなたのJavaコードでそれを使う必要があります。
わかりました-のマニュアルページを調べましたmcrypt_encrypt
。それは言う:
指定された暗号とモードで暗号化されるデータ。データのサイズが。でないn * blocksize
場合、データには。が埋め込まれ\0
ます。
したがって、Javaでそれを複製する必要があります。これが1つの方法です:
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日):Java 8の時点で、JavaSEは最終的に文書化されたbase64コーデックとともに出荷されます。だから代わりに
return new sun.misc.BASE64Encoder().encode(encrypted);
あなたは次のようなことをする必要があります
return Base64.Encoder.encodeToString(encrypted);
commons-codec
または、文書化されていない内部メソッドを使用するのではなく、base64のエンコード/デコードにサードパーティのライブラリ(など)を使用します。