没有填充解密的Android AES,字符串末尾的未知字符“NUL”

时间:2014-07-15 03:16:33

标签: java php android encryption cryptography

我已经使用代码来解密用Java mcrypt函数加密的Java文件。

private String iv = "MYKEYHERE";//Dummy iv (CHANGE IT!)
private String SecretKey = "MYKEYHERE";//Dummy secretKey (CHANGE IT!)

private byte[] decrypt(String code)
{
    byte[] decrypted = null;
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
        SecretKeySpec keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
        if(code == null || code.length() == 0)
            throw new Exception("Empty string");

        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

        decrypted = cipher.doFinal(hexToBytes(code));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return decrypted;
}

private static byte[] hexToBytes(String str) {
    if (str==null) {
        return null;
    } else if (str.length() < 2) {
        return null;
    } else {
        int len = str.length() / 2;
        byte[] buffer = new byte[len];
        for (int i=0; i<len; i++) {
            try {
                buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
            } catch (NumberFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return buffer;
    }
}

我正在从SDCARD读取和写入文件

String encyptedData = readFileFromSDCard(params[0]);

byte[] decryptedByteArray = decrypt(encyptedData);

File rootFile = new File(Constants.folioTempLocation+params[1]);
rootFile.mkdirs();

File outFile = new File(rootFile,  new File(params[0]).getName());
FileOutputStream out = new FileOutputStream(outFile);
//IOUtils.write(decryptedByteArray, out);
out.write(decryptedByteArray);
out.flush();
out.close();

解密并将文件写回SD_CARD没有问题。但是我在每个文件的末尾加上未知字符,这限制了整个解密文件的正常运行。

我附加了连接到字符串结尾的未知字符的屏幕截图。我还为想要使用此文件测试代码的任何人附加encrypted_html_file

截图 sample image

2 个答案:

答案 0 :(得分:3)

CBC是一种阻止模式,必须使用适当的填充方案。

PHP的mcrypt使用zero padding - 它将\0个字符附加到输入数据,使其长度为块大小的倍数。显然,你在解密时会得到这些零字节。

mycrypt页面提供了一个如何在用户注释中实现正确的PKCS#7填充方案的示例。其他mcrypt padding个问题How to add/remove PKCS7 padding from an AES encrypted string?提供了类似的示例。

答案 1 :(得分:0)

由于我不知道问题的原因,我只能提供一种解决方法来删除尾随空值(NUL)。

public static byte[] removeTrailingNulls(byte[] source) {
    int i = source.length;
    while (source[i - 1] == 0x00) {
        i--;
    }

    byte[] result = new byte[i];
    System.arraycopy(source, 0, result, 0, i);

    return result;
}

在解密文件后立即尝试

byte[] decryptedByteArray = removeTrailingNulls(decrypt(encyptedData));

警告: 这可能会影响性能(特别是在移动设备上),因为它几乎占用了两倍的内存使用量。

此解决方法并不完美,因为它始终会删除尾随空值,无论原始数据如何。使用风险自负