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

Pra*_*ngh 0 java encryption cryptography exception 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.");

}
}
Run Code Online (Sandbox Code Playgroud)

解密代码

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+"");
}
}
}
Run Code Online (Sandbox Code Playgroud)

Jam*_*olk 5

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

while ((read = fis.read(in,16,(int)file.length()-16)) != -1) {
Run Code Online (Sandbox Code Playgroud)

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

我看到的其他问题的非详尽列表包括:

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

看起来你正在努力找到一些你习以为常的IO习语.或者也许只是试验.冒着给你更多选择来玩杂耍的风险,你可以考虑调查谷歌的开源Guava库.许多人发现它正是他们所需要的.