解密期间读取CipherInputStream时出现BadPaddingException

问题描述 投票:0回答:1

我是 Java 加密技术的新手,不知道为什么在尝试解密已成功加密的文件(使用相同的密钥和 IV)时不断收到 BadPaddingException。我将 16 字节 IV 添加到密文文件的开头,然后尝试在解密过程中读取它。这和秘密密钥的初始化似乎有效,所以我不确定我哪里出了问题。

我使用

javac -g FileEncryptor.java Util.java
进行编译,使用
java FileEncryptor enc 90F6seEyxAK9cxblqsKJGQ== input.txt ciphertext.enc
java FileEncryptor dec 90F6seEyxAK9cxblqsKJGQ== ciphertext.enc decrypted.txt
分别进行加密和解密。

感谢帮助:)

我已经检查了 IV 和密钥是否为 16 字节,以及 IV 是否正确地前置(在加密期间)和读取(在解密期间)。在调试过程中,一旦到达包含

decryptStream.read(bytes)
的 for 循环,我总是会得到异常。

注意:并非所有代码都是我的。我用它作为学习练习。

public class FileEncryptor {
    private static final Logger LOG = Logger.getLogger(FileEncryptor.class.getSimpleName());

    private static final String ALGORITHM = "AES";
    private static final String CIPHER = "AES/CBC/PKCS5PADDING";

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IOException, Exception {

        SecureRandom sr = new SecureRandom();
        byte[] key = new byte[16];
        sr.nextBytes(key); // 128 bit key
        byte[] initVector = new byte[16];
        sr.nextBytes(initVector);
        String mode = args[0];
        String hexSkey;

        IvParameterSpec iv = new IvParameterSpec(initVector);
        SecretKeySpec skeySpec = new SecretKeySpec(key, ALGORITHM);
        Cipher cipher = Cipher.getInstance(CIPHER);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        final Path currentPath = Paths.get("");

        if (mode.equals("enc")) {

            System.out.println("initVector=" + Util.bytesToHex(initVector));

            skeySpec = new SecretKeySpec(Base64.getDecoder().decode(args[1]), ALGORITHM);

            final Path encryptedPath = currentPath.resolve(args[3]);// idk if this is necessary imo,

            // args[1] becomes base64 encoded skey
            // args[2] = input.txt
            // args[3] = output encrypted file
            try (InputStream fin = FileEncryptor.class.getResourceAsStream(args[2]);

                    OutputStream fout = Files.newOutputStream(encryptedPath);
                    CipherOutputStream cipherOut = new CipherOutputStream(fout, cipher) {
                    }) {
                final byte[] bytes = new byte[1024];
                fout.write(initVector);// write the IV to the first 16 bytes of the encrypted file
                for (int length = fin.read(bytes); length != -1; length = fin.read(bytes)) {
                    cipherOut.write(bytes, 0, length);
                }
                cipherOut.close();
            } catch (IOException e) {
                LOG.log(Level.INFO, "Unable to encrypt", e);
            }
            return;
        } else if (mode.equals("dec")) {
            String encodedFile = args[2], decodedFile = args[3];
            skeySpec = new SecretKeySpec(Base64.getDecoder().decode(args[1]), ALGORITHM);
            final Path decryptedPath = currentPath.resolve(decodedFile);

            try (InputStream encryptedData = Files.newInputStream(Path.of(encodedFile));
                    OutputStream decryptedOut = Files.newOutputStream(decryptedPath)) {
                byte[] storedIV = new byte[16];
                int first16bytes = encryptedData.read(storedIV);
                if (first16bytes != storedIV.length) {
                    // FIXME: edit error here
                }
                cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(storedIV));

                System.out.println("key check " + storedIV.length);
                final byte[] bytes = new byte[1024];

                CipherInputStream decryptStream = new CipherInputStream(encryptedData, cipher);
                for (int length = decryptStream.read(bytes); length != -1; length =
                decryptStream.read(bytes)) {
                System.out.println("reached");
                decryptedOut.write(bytes, 0, length);
                }
                decryptStream.close();
            } catch (IOException ex) {
                Logger.getLogger(FileEncryptor.class.getName()).log(Level.SEVERE, "Unable to decrypt", ex);
            }
            LOG.info("Decryption complete, open " + decryptedPath);
            return;// delete later
        }
    }
}
java encryption aes ecb javax.crypto
1个回答
0
投票

您正在生成一个随机密钥并在密码中使用它,而不是使用提供的密钥。这将产生一个错误的填充异常。

© www.soinside.com 2019 - 2024. All rights reserved.