【问题标题】:Android/Java AES 256 CBC with PKCS5Padding decryption in PHPAndroid/Java AES 256 CBC 与 PHP 中的 PKCS5Padding 解密
【发布时间】:2014-07-11 15:19:20
【问题描述】:

我正在对我的 Android 应用程序中的一些数据进行加密,然后将其发送到 PHP 页面进行解密和处理。

使用的密码是"AES/CBC/PKCS5Padding"

现在一切正常(经过大量挖掘信息)。 但是,生成的解密数据在末尾添加了许多新行,这些行在应用程序发送的原始数据中不存在。

我假设这是 PHP 不支持 PKCS5Padding 的副作用。 假设结尾总是在字符串后面附加换行符或空格,我感到很不舒服。

如果我尝试使用mcrypt docs 中建议的代码,加密缓冲区将被清空。

是否有更好的解决方法来取消填充?


编辑:根据要求添加代码

PHP

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, "", MCRYPT_MODE_CBC, "");
if($cipher === false)
{
    trigger_error("AES compatible cipher missing", E_USER_WARNING);
    exit;
}
$InitResult = mcrypt_generic_init($cipher, $AesPassword, $AesIv);
if($InitResult !== 0)
{
    trigger_error("AES cipher init failed", E_USER_WARNING);
    exit;
}
// now do the decryption
$DataBlock = mdecrypt_generic($cipher, $EncryptedBlock);
// close down mcrypt
mcrypt_generic_deinit($cipher);
mcrypt_module_close($cipher);

安卓/Java:

String strEncrypted = null;
Cipher cipher = null;
IvParameterSpec ivSpec = null;
byte[] btEncrypted = null;

try
{
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    ivSpec = new IvParameterSpec(m_btIV);

    cipher.init(Cipher.ENCRYPT_MODE, m_KeySpec, ivSpec);
    btEncrypted = cipher.doFinal(strData.getBytes(m_strCharSet));
    strEncrypted = Base64.encodeToString(btEncrypted, Base64.NO_PADDING | Base64.NO_WRAP);
}
catch(Exception e)
{
    e.printStackTrace();
}

return strEncrypted;

注意key和iv是在Android中计算出来的,并在POST数据中传输到服务器。

这有帮助吗?

【问题讨论】:

  • 你能告诉我们你的PHP代码吗?我以为我有答案,但事后看来这可能不是问题。

标签: java php android aes padding


【解决方案1】:

很遗憾,Java SE 提供程序不支持 PHP 填充。 Bouncy Castle 也不支持这种填充,因为 Bouncy Castle 始终填充至少 1 个字节,即使是零填充也是如此。


所以经过大量调整,这是我能想到的最好的:

/**
 * Pads data with zero valued bytes until the next block boundary is met.
 * Does not pad if the number of blocks is already on a boundary. This
 * method is not safe for binary data that may end with zero valued bytes as
 * they may be removed by the unpadding method.
 * If available, try and use PKCS#7 compatible padding instead.
 * 
 * @param data
 *            the binary data to pad, never null
 * @param blocksize
 *            the block size in bytes of the block cipher
 * @return the padded binary data as a copy
 * @throws NullPointerException
 *             if data is null
 */
public static byte[] phpPad(final byte[] data, final int blocksize) {
    if (data.length == 0) {
        return data;
    }

    final int blocks = (data.length - 1) / blocksize + 1;
    return Arrays.copyOf(data, blocks * blocksize);
}

/**
 * Unpads data removing zero valued bytes, removing up to blocksize - 1
 * bytes of padding. The input of the unpad method should consist of n times
 * the blocksize.
 * 
 * @param data
 *            the binary data to unpad, never null
 * @param blocksize
 *            the block size in bytes of the block cipher
 * @return the unpadded binary data as a copy
 * @throws NullPointerException
 *             if data is null
 * @throws IllegalArgumentException
 *             if the data is not n times the blocksize
 */
public static byte[] phpUnpad(final byte[] data, final int blocksize) {
    if (data.length % blocksize != 0) {
        throw new IllegalArgumentException(
                "Padded data should dividable by the block size");
    }

    if (data.length == 0) {
        return data.clone();
    }

    int padBytes = 0;
    for (; padBytes < blocksize; padBytes++) {
        if (data[data.length - padBytes - 1] != 0x00) {
            break;
        }
    }

    return Arrays.copyOf(data, data.length - padBytes);
}

【讨论】:

  • 您好 owlstead,感谢您为此所做的工作。但是,我在这里有点困惑。加密缓冲区来自已请求 PKCS#5 填充的 android java - 你是说 android java 不会产生正确的 PKCS#5 填充吗?或者,您是说它将用空字节填充?因此上面的两个 PHP 函数?
  • 啊,也许我做错了,PKCS#5/7 填充更好,所以在 PHP 中使用它是更好的解决方案。我通常会遇到无法更改 PHP 代码的问题……但在这种情况下,you cannot go wrong with Paũlo
猜你喜欢
  • 2022-11-16
  • 2014-01-13
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 2021-08-13
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多