javax.crypto.BadPaddingException:给定最终块在解密时未正确填充

时间:2017-06-19 13:52:19

标签: java exception encryption cryptography aes

我正在尝试解密java中的文件。解密文件的前16个字节是IV(初始化向量)。请帮助解决上述异常。

我试图在AESFileEncryption()中的输出文件中添加IV,然后在解密时读取它。

谢谢。

public class AESFileEncryption {
public static void encrypt(String path,String pwd) throws Exception {

    FileOutputStream outFile;

    try ( 
            FileInputStream inFile = new FileInputStream(path)) {

        String fileName=path;

        System.out.println(path);

        outFile = new FileOutputStream(fileName+".aes");
        // password to encrypt the file
        String password = pwd;
        byte[] salt = {
        (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
        (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
       };

        SecretKeyFactory factory = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(),salt,65536,128);// user-chosen password that can be used with password-based encryption (PBE).
        SecretKey secretKey = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");//Secret KeySpec is a class and implements inteface SecretKey

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecureRandom random = new SecureRandom();
        byte bytes[] = new byte[16];
        random.nextBytes(bytes);
     IvParameterSpec ivspec = new IvParameterSpec(bytes);   
        cipher.init(Cipher.ENCRYPT_MODE, secret,ivspec);//opmode,key
        outFile.write(bytes);
        byte[] input = new byte[64];
        int bytesRead;
        while ((bytesRead = inFile.read(input)) != -1) {
            byte[] output = cipher.update(input, 0, bytesRead);
            if (output != null)
                Files.write(Paths.get(fileName+".aes"), output, StandardOpenOption.APPEND);

        }   byte[] output = cipher.doFinal();
        if (output != null)
            Files.write(Paths.get(fileName+".aes"), output, StandardOpenOption.APPEND);
    }
    outFile.flush();
    outFile.close();
    File f=new File(path);
    boolean x=f.delete();
    if(x){
        System.out.println("File deleted");
    }
    JOptionPane.showMessageDialog(null,"File Encrypted.");

}
}

解密代码

public class AESFileDecryption {
public static void decrypt(String path,String pwd) throws Exception {

    String password = pwd;
    String fileName=path;
    File file=new File(path);
        //System.out.println(inFile.toString());
        String fileNameWithOutExt = path.replaceFirst("[.][^.]+$", "");
        System.out.println(fileName);
        System.out.println(fileNameWithOutExt);
        byte[] salt = {
        (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
        (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
    };
    System.out.println("1");
    FileInputStream fis = new FileInputStream(path);
    SecretKeyFactory factory = SecretKeyFactory
            .getInstance("PBKDF2WithHmacSHA1");
    KeySpec keySpec = new PBEKeySpec(password.toCharArray(),salt,65536,128);
    SecretKey tmp = factory.generateSecret(keySpec);
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
    System.out.println("2");
    // file decryption
    Cipher cipher=null;
    byte bytes[]=new byte[16];
    fis.read(bytes, 0, 16); 
    IvParameterSpec ivspec = new IvParameterSpec(bytes);

    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
    System.out.println("3");
    FileOutputStream fos = new FileOutputStream(fileNameWithOutExt);
    System.out.println("4");
    byte[] in   = new byte[64];
    int read;
    while ((read = fis.read(in,16,(int)file.length()-16)) != -1) {
        byte[] output = cipher.update(in, 0, read);
        if (output != null)
            fos.write(output);
    }
    try{
    byte[] output = cipher.doFinal();
    if (output != null)
        fos.write(output);
    fis.close();
    fos.flush();
    fos.close();
    System.out.println("File Decrypted.");
}
catch(IOException | BadPaddingException | IllegalBlockSizeException e)
{
    System.out.println(e+"");
}
}
}

1 个答案:

答案 0 :(得分:5)

小例子有一些问题,但最直接的问题就是行

while ((read = fis.read(in,16,(int)file.length()-16)) != -1) {

您似乎对offset read()参数的含义感到困惑。它不是文件的偏移量,而是第一个参数中指定的数组(in)的偏移量。

我看到的其他问题的非详尽清单包括:

  • 使用两个独立机制(FileOutputStream.write()Files.write())写入文件。当我运行你的程序时,这实际上工作正常,但它似乎要求麻烦。这里没有理由使用Files.write()
  • fis.read(bytes, 0, 16);不会检查返回值。

您似乎正在努力寻找一些您熟悉的IO惯用语。或者也许只是试验。冒着为您提供更多选择的风险,您可以考虑调查谷歌的开源Guava库。许多人发现它正是他们所需要的。