使用AES算法解密的BadPaddingException

时间:2015-10-08 04:43:12

标签: java android encryption cryptography aes

我正在尝试对视频和pdf进行加密。在我获得每个文件的流后,我分成缓冲区,然后我加密每个文件并将所有缓冲区合并为一个加密文件。

对于加密,一切正常,但是当我尝试以相同的方式解密文件时,我在 doFinal 时出现错误

  

{BadPaddingException:pad块损坏   BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:739)}

这是我正在测试的代码

加密

public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
    {

        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        byte[] encrypted = cipher.doFinal(fileData);

        return encrypted;
    }

解密

public static byte[] decodeFile(byte[] key, byte[] fileData)
{
    byte[] decrypted=new byte[0];
    try {
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES");

        cipher.init(Cipher.DECRYPT_MODE, skeySpec);

         decrypted= cipher.doFinal(fileData);
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }

    return decrypted;
}

生成密钥

   public static byte[] generateKey(String password) throws Exception
    {
        byte[] keyStart = password.getBytes("UTF-8");

        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        sr.setSeed(keyStart);
        kgen.init(256, sr);
        SecretKey skey = kgen.generateKey();
        return skey.getEncoded();
    }

这是我如何解密文件

public void decryptStream(String filePath) {

    String outPath = Environment.getExternalStorageDirectory().toString() + "/" + fileName + "de" + "." + fileExtention;
    filePath += "_secured." + fileExtention;
    byte[] data = new byte[1024];
    byte[] decryptData;
    File file = new File((filePath));

    File deFile = new File(outPath);
    InputStream inputStream = null;
    try {
        inputStream = FileUtils.openInputStream(file);
    } catch (IOException e) {
        e.printStackTrace();
    }
    BufferedOutputStream bos = null;
    try {
        bos = new BufferedOutputStream((new FileOutputStream(deFile)));
        while ((inputStream.read(data)) != -1) {
            decryptData = decryptByteArray(data);
            bos.write(decryptData);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}
private byte[]  decryptByteArray(byte[] input) {
    Encryption e=new Encryption();
    byte[]decryptedBytes = new byte[0];
    try {
        byte[] yourKey = e.generateKey("password");
        decryptedBytes = e.decodeFile(yourKey, input);

    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    } catch (Exception e1) {
        e1.printStackTrace();
    }
    return decryptedBytes;
}

1 个答案:

答案 0 :(得分:1)

问题很可能在这里:

    while ((inputStream.read(data)) != -1) {
        decryptData = decryptByteArray(data);
        bos.write(decryptData);
    }

当您读取的文件不是1024字节长的倍数时,最后一次读取将不会完全填充字节数组,但您将整个数组传递到decryptByteArray

另请注意,即使是中间读取,也无法保证read将完全填充数组。始终检查返回值,该值给出实际读取的字节数。

问题没有显示加密是如何完成的。如果在密码中使用填充,则1024字节块的每个加密将长于1024字节(因为添加了填充块)。对于解密,必须一次处理整个密文(包括填充)。只使用前1024个字节将导致BadPaddingException