到目前为止,一个快速逃避我的人(漫漫长夜)。我在PHP和Java中比较AES256并注意到差异。为简单起见,请忽略ascii键和null IV,这些将在生产中被替换。但我需要首先解决这个问题,无法弄清楚我在哪里犯错:
PHP:
echo base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
"1234567890ABCDEF1234567890ABCDEF",
"This is a test",
MCRYPT_MODE_CBC,
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
)
);
爪哇
byte[] key = "1234567890ABCDEF1234567890ABCDEF".getBytes("UTF-8");
byte[] iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
SecretKeySpec newKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
byte[] results = cipher.doFinal("This is a test".getBytes("UTF-8"));
return Base64.encodeToString(results,Base64.DEFAULT);
PHP输出:0KwK+eubMErzDaPU1+mwTQ==
Java输出:DEKGJDo3JPtk48tPgCVN3Q==
不是我期待的o_O!
我还尝试了MCRYPT_MODE_CBC
,MCRYPT_MODE_CFB
,MCRYPT_MODE_ECB
,MCRYPT_MODE_NOFB
等等。它们都没有生成Java字符串。
答案 0 :(得分:1)
PHP使用\0
填充输入字节,使其成为块大小的倍数。 Java中的等价物就是这个(假设您要加密的字符串在data
中):
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] inputBytes = data.getBytes();
int byteLength = inputBytes.length;
if (byteLength % blockSize != 0) {
byteLength = byteLength + (blockSize - (byteLength % blockSize));
}
byte[] paddedBytes = new byte[byteLength];
System.arraycopy(inputBytes, 0, paddedBytes, 0, inputBytes.length);
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
byte[] results = cipher.doFinal(paddedBytes);
作为对此的警告 - 不需要基于零的填充。无法确定字符串末尾的\0
个字符与实际填充之间的区别。最好使用PKCS5Padding,但在PHP中会得到不同的结果。问问自己是否需要这样的加密跨平台。