使用 AES 算法解密的 BadPaddingException java

BadPaddingException with decryption using AES algorithm java

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

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

{BadPaddingException : pad block corrupted 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;
}

问题最有可能出现在这里:

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

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

另请注意,即使是中间读取,也不能保证 read 会完全填满数组。始终检查 return 值,它给出了实际读取的字节数。

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