使用Base64编码的AES128加密在具有较长字符串的Java和PHP中的作用不同
我一直在努力使加密/解密在Java(Android)和PHP中也能起同样的作用,并为客户机/服务器通信产生同样的结果
我正在使用下面的代码进行加密,但我不知道它出了什么问题。使用相同的密钥和较小的字符串运行这两个函数会产生相同的加密值,但是如果字符串较长,则会得到两个不同的结果。 PHP:
$str = 'test1234test1234';
$key = 'TESTKEYTESTKEY12';
$block = mcrypt_get_block_size('des', 'ecb');
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB));
在Java中(Android上):
public static String encryptTest() {
String cleartext = "test1234test1234";
String key = "TESTKEYTESTKEY12";
byte[] raw = key.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted;
encrypted = cipher.doFinal(cleartext.getBytes());
return new String(Base64.encode(encrypted,Base64.DEFAULT));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
使用字符串test1234
运行此函数在两种实现中都会得到:8i4KEe82TQl0Zdlc14fwAg==
。
使用字符串test1234test1234
但是我用PHP得到4s5a0edsvwWt/3/enRe0wgJQD/0zL45NRb/r3p6L/Is=
,用Java得到4s5a0edsvwWt/3/enRe0wgA0jk78zwWJr1xsosZbYUA=
。我不确定出了什么问题,而且我对密码学的知识也不够
# 1 楼答案
短字符串和长字符串的结果不同这一事实表明,在每个实现中使用不同的padding
确保在java和php实现中使用相同类型的填充
# 2 楼答案
Java代码的主要问题是没有指定密码模式和使用的填充算法。因此,使用哪种密码模式和填充算法取决于使用的加密提供程序,在这一特定细节中,Android的工作方式与J2SE不同
如果我在J2SE上执行Java代码,我会得到与PHP相同的结果。如果我将代码更改为使用
Cipher.getInstance("AES/ECB/PKCS5Padding");
,这一点不会改变由于只有密码文本的最后一块发生了变化,我假设Android默认使用不同的填充算法