尝试在 Java 中使用 AES 加密时出错

问题描述

我正在尝试构建一个压缩文件,然后使用 AES 加密对文件进行加密的 Java 程序。但是,我在加密过程中收到以下错误

Exception in thread "main" java.security.NoSuchAlgorithmException: Cannot find any provider supporting PBKDF2WithHmacSHA256
at java.base/javax.crypto.Cipher.getInstance(Cipher.java:574)
at MyJavaProject.zip.encryptFile(zip.java:75)
at MyJavaProject.zip.main(zip.java:58)

我在下面包含了我的代码。它应该压缩我指向它的文件,然后加密它,并保存盐和 IV 的字节,以便我以后可以解密。我使用的是 Java 16,我的 JRE 是 JavaSE-12。

class zip {
    public static void main(String[] args) throws IOException,InvalidKeyException,NoSuchPaddingException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,BadPaddingException,IllegalBlockSizeException,InvalidKeySpecException {
        FileInputStream fis = new FileInputStream("texty.txt");
        FileOutputStream fos = new FileOutputStream("texty(comp)");
        DeflaterOutputStream dos = new DeflaterOutputStream(fos);

        int data;
        while ((data = fis.read()) != -1) {
            dos.write(data);
        }

        fis.close();
        dos.close();

        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16];
        random.nextBytes(salt);
        SecretKey key = getKeyFromPassword("Password",salt.toString());
        String algorithm = "AES/CBC/PKCS5Padding";
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        IvParameterSpec Iv = new IvParameterSpec(iv);
        encryptFile(algorithm,key,Iv,new File("texty(comp)"),new File("texty(compNenc)"));
        FileOutputStream fs = new FileOutputStream(new File("intravenus"));
        bufferedoutputstream bos = new bufferedoutputstream(fs);
        bos.write(iv);
        bos.close();
        FileOutputStream fs2 = new FileOutputStream(new File("pepper"));
        bufferedoutputstream bos2 = new bufferedoutputstream(fs2);
        bos2.write(salt);
        bos2.close();
    }

    public static void encryptFile(String algorithm,SecretKey key,IvParameterSpec iv,File inputFile,File outputFile)
            throws IOException,IllegalBlockSizeException {

        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE,iv);
        FileInputStream inputStream = new FileInputStream(inputFile);
        FileOutputStream outputStream = new FileOutputStream(outputFile);
        byte[] buffer = new byte[64];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            byte[] output = cipher.update(buffer,bytesRead);
            if (output != null) {
                outputStream.write(output);
            }
        }
        byte[] outputBytes = cipher.doFinal();
        if (outputBytes != null) {
            outputStream.write(outputBytes);
        }
        inputStream.close();
        outputStream.close();
    }

    public static SecretKey getKeyFromPassword(String password,String salt)
            throws NoSuchAlgorithmException,InvalidKeySpecException {

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(password.tochararray(),salt.getBytes(),65536,256);
        SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(),"AES");
        return secret;
    }

}

更新: 感谢@that 其他人帮助我解决了最初的错误,但现在我有一个新的,我还不够先进,无法理解。当我尝试下载为 salt 和 IV 存储的字节并尝试解密文件时,我收到以下错误消息:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2091)
at MyJavaProject.unzip.decryptFile(unzip.java:99)
at MyJavaProject.unzip.main(unzip.java:52)

我的解密文件代码如下。如果有人可以提供帮助,我将不胜感激。

class unzip {
    public static void main(String[] args)
            throws IOException,InvalidKeySpecException,IllegalBlockSizeException {

        byte[] fileData = new byte[16];
        DataInputStream dis = null;

        dis = new DataInputStream(new FileInputStream(new File("intravenus")));
        dis.readFully(fileData);
        if (dis != null) {
            dis.close();
        }
        byte[] iv = fileData;
        IvParameterSpec Iv = new IvParameterSpec(iv);
        byte[] fileData2 = new byte[16];
        DataInputStream dis2 = null;

        dis2 = new DataInputStream(new FileInputStream(new File("pepper")));
        dis2.readFully(fileData2);
        if (dis2 != null) {
            dis2.close();
        }
        byte[] salt = fileData2;
        SecretKey key = getKeyFromPassword("Password",salt.toString());
        String algorithm = "AES/CBC/PKCS5Padding";

        decryptFile(algorithm,new File("texty(compNenc)"),new File("texty(compNdec)"));

        // assign Input File : file2 to FileInputStream for reading data
        FileInputStream fis = new FileInputStream("texty(compNdec)");

        // assign output file: file3 to FileOutputStream for reading the data
        FileOutputStream fos = new FileOutputStream("texty(decompNdec)");

        // assign inflaterInputStream to FileInputStream for uncompressing the data
        InflaterInputStream iis = new InflaterInputStream(fis);

        // read data from inflaterInputStream and write it into FileOutputStream
        int data;
        while ((data = iis.read()) != -1) {
            fos.write(data);
        }

        // close the files
        fos.close();
        iis.close();

    }

    public static SecretKey getKeyFromPassword(String password,"AES");
        return secret;
    }

    public static void decryptFile(String algorithm,File encryptedFile,File decryptedFile) throws IOException,IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE,iv);
        FileInputStream inputStream = new FileInputStream(encryptedFile);
        FileOutputStream outputStream = new FileOutputStream(decryptedFile);
        byte[] buffer = new byte[64];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            byte[] output = cipher.update(buffer,bytesRead);
            if (output != null) {
                outputStream.write(output);
            }
        }
        byte[] output = cipher.doFinal();
        if (output != null) {
            outputStream.write(output);
        }
        inputStream.close();
        outputStream.close();
    }

}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)