关于Java和PHP的AES256

时间:2013-02-13 02:35:40

标签: java php encryption aes

到目前为止,一个快速逃避我的人(漫漫长夜)。我在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_CBCMCRYPT_MODE_CFBMCRYPT_MODE_ECBMCRYPT_MODE_NOFB等等。它们都没有生成Java字符串。

1 个答案:

答案 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中会得到不同的结果。问问自己是否需要这样的加密跨平台。