CipherInputStream只能读取16个字节(AES/Java)



我正在使用CipherInputStream和CipherOutputStream使用AES加密文件。

encrypt(...)似乎工作正常,但我的decrypt(...)函数只解密文件的前 16 个字节。

这是我的班级:

public class AESFiles {
    private byte[] getKeyBytes(final byte[] key) throws Exception {
        byte[] keyBytes = new byte[16];
        System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length));
        return keyBytes;
    }
    public Cipher getCipherEncrypt(final byte[] key) throws Exception {
        byte[] keyBytes = getKeyBytes(key);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        return cipher;
    }
    public Cipher getCipherDecrypt(byte[] key) throws Exception {
        byte[] keyBytes = getKeyBytes(key);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        return cipher;
    }
    public void encrypt(File inputFile, File outputFile, byte[] key) throws Exception {
        Cipher cipher = getCipherEncrypt(key);
        FileOutputStream fos = null;
        CipherOutputStream cos = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(inputFile);
            fos = new FileOutputStream(outputFile);
            cos = new CipherOutputStream(fos, cipher);
            byte[] data = new byte[1024];
            int read = fis.read(data);
            while (read != -1) {
                cos.write(data, 0, read);
                read = fis.read(data);
                System.out.println(new String(data, "UTF-8").trim());
            }
            cos.flush();
        } finally {
            fos.close();
            cos.close();
            fis.close();
        }
    }
    public void decrypt(File inputFile, File outputFile, byte[] key) throws Exception {
        Cipher cipher = getCipherDecrypt(key);
        FileOutputStream fos = null;
        CipherInputStream cis = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(inputFile);
            cis = new CipherInputStream(fis, cipher);
            fos = new FileOutputStream(outputFile);
            byte[] data = new byte[1024];
            int read = cis.read(data);
            while (read != -1) {
                fos.write(data, 0, read);
                read = cis.read(data);
                System.out.println(new String(data, "UTF-8").trim());
            }
        } finally {
            fos.close();
            cis.close();
            fis.close();
        }
    }
    public static void main(String args[]) throws Exception {
        byte[] key = "mykey".getBytes("UTF-8");
        new AESFiles().encrypt(new File("C:\Tests\secure.txt"), new File("C:\Tests\secure.txt.aes"), key);
        new AESFiles().decrypt(new File("C:\Tests\secure.txt.aes"), new File("C:\Tests\secure.txt.1"), key);
    }
}

所以我的问题是,为什么decrypt函数只读取前 16 个字节?

这是

非常微妙的。 你的问题是你在cos之前关闭了你的fos。 在encrypt(...)方法中,您正在执行以下操作:

} finally {
    fos.close();
    cos.close();
    fis.close();
}

这会从CipherOutputStream下方关闭FileOutputStream,因此加密输出的最终填充块永远不会写入输出文件。 如果在cos关闭fos,则代码应该可以正常工作。

真的,你应该考虑做这样的事情:

    FileOutputStream fos = null;
    CipherOutputStream cos = null;
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(inputFile);
        fos = new FileOutputStream(outputFile);
        cos = new CipherOutputStream(fos, cipher);
        // once cos wraps the fos, you should set it to null
        fos = null;
        ...
    } finally {
        if (cos != null) {
           cos.close();
        }
        if (fos != null) {
           fos.close();
        }
        if (fis != null) {
           fis.close();
        }
    }

仅供参考:org.apache.commons.io.IOUtils有一个很棒的closeQuietly(...)方法,可以处理null检查并为您捕获异常。

相关内容

  • 没有找到相关文章

最新更新