使用Base64编码的AES-128加密在Java和PHP中使用较长字符串时的行为不同

时间:2012-03-21 09:28:03

标签: java php android encryption aes

我一直试图让加密/解密在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=。我不确定什么是错的,我对密码学知之甚少。

2 个答案:

答案 0 :(得分:3)

Java代码的主要问题是您没有指定密码模式和使用的填充算法。因此,使用哪种密码模式和填充算法取决于使用的加密提供程序,在此特定细节中,Android的工作方式与J2SE不同。

如果我在J2SE上执行Java代码,我会得到与PHP相同的结果。如果我将代码更改为使用Cipher.getInstance("AES/ECB/PKCS5Padding");,则不会更改。

由于只有密文的最后一个块发生了变化,我认为Android默认使用不同的填充算法。

答案 1 :(得分:2)

对于短字符串和长字符串,您有不同的结果,这表明您在每个实现上使用了不同的padding

确保在java和php实现上使用相同类型的填充。