PHP功能:
$privateKey = "1234567812345678"; $iv = "1234567812345678"; $data = "Test string"; $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateKey, $data, MCRYPT_MODE_CBC, $iv); echo(base64_encode($encrypted)); Result: iz1qFlQJfs6Ycp+gcc2z4w==
Java函数
public static String encrypt() throws Exception{ try{ String data = "Test string"; String key = "1234567812345678"; String iv = "1234567812345678"; javax.crypto.spec.SecretKeySpec keyspec = new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES"); javax.crypto.spec.IvParameterSpec ivspec = new javax.crypto.spec.IvParameterSpec(iv.getBytes()); javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, keyspec, ivspec); byte[] encrypted = cipher.doFinal(data.getBytes()); return new sun.misc.BASE64Encoder().encode(encrypted); }catch(Exception e){ return null; }
}
返回null。
请注意,我们不允许更改PHP代码。有人可以帮助我们在Java中获得相同的结果吗?非常感谢。
如果您不只是简单地Exception将encrypt()例程中的可能内容吞噬掉,那么您将对发生的事情有了更好的了解。如果函数正在返回,null那么显然发生了异常,您需要知道它是什么。
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个字节。
您需要检查PHP mcrypt_encrypt函数的实际作用。由于它有效,因此显然使用了一些填充方案。您需要找出它是哪一个,并在Java代码中使用它。
mcrypt_encrypt
好的-我查找了手册页mcrypt_encrypt。它说:
将使用给定的密码和模式加密的数据。如果数据大小n * blocksize不足,数据将被填充\0。
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日) :从Java 8开始,JavaSE最终随附了已记录的base64编解码器。所以代替
return new sun.misc.BASE64Encoder().encode(encrypted);
你应该做类似的事情
return Base64.Encoder.encodeToString(encrypted);
或者,使用第三方库(例如commons-codec)进行base64编码/解码,而不要使用未公开的内部方法。
commons-codec