如何使用文件输入和输出流从文件中添加特定数量的字节?

时间:2019-01-11 14:17:23

标签: java file encryption

我正在研究一个用于加密/解密大文件的类,因此我试图使用流而不是字节数组来避免OutOfMemory异常。 在加密方法中,我将随机salt和iv添加到加密文件的开头,并且工作正常,这是代码:

public File encryptFile(File inputFile, File outPutFile, String password, ProgressBar progressBar, Label progressPercentage){
        //Create IV
        byte[] ivBytes = new byte[16];
        SecureRandom random1 = new SecureRandom();
        random1.nextBytes(ivBytes);
        IvParameterSpec iv = new IvParameterSpec(ivBytes);


        //Create the key with the salt
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[SALT_SIZE];
        random.nextBytes(salt);

        SecretKeySpec keySpec = generateAesKey(password, salt);

        //Create and Init the cipher
        Cipher c = Cipher.getInstance("AES/CBC/"+padding);
        c.init(Cipher.ENCRYPT_MODE, keySpec, iv);

        byte[] buf = new byte[8192];
        FileInputStream in = new FileInputStream(inputFile);
        FileOutputStream out = new FileOutputStream(outPutFile);
        int nread;
        int progress = 0;

        byte[] ivAndSalt = new byte[ivBytes.length + salt.length];
        System.arraycopy(ivBytes,0, ivAndSalt,0, ivBytes.length );
        System.arraycopy(salt, 0, ivAndSalt, ivBytes.length, salt.length);
        out.write(ivAndSalt);

        while((nread = in.read(buf)) != -1) {
            byte[] enc = c.update(buf, 0, nread);
            out.write(enc);
            progress++;
        }

然后我尝试使用解密方法获得iv和salt,然后使用FileInputStream.getChannel.position()将文件的其余部分解密为输出文件:

 public File decryptFile(File inputFile, File outPutFile, String password, ProgressBar progressBar, Label progressPercentage) {
        //Create and Init Cipher
        Cipher c = Cipher.getInstance("AES/CBC/" + padding);

        FileInputStream in = new FileInputStream(inputFile);
        FileOutputStream out = new FileOutputStream(outPutFile);

        //Getting the iv and salt
        byte[] ivBytes = new byte[16];
        byte[] salt = new byte[SALT_SIZE];
        byte[] ivAndSalt = new byte[ivBytes.length+SALT_SIZE];
        in.read(ivAndSalt, 0, ivBytes.length+SALT_SIZE);
        System.arraycopy(ivAndSalt, 0, ivBytes, 0, ivBytes.length);
        System.arraycopy(ivAndSalt, ivBytes.length, salt, 0, SALT_SIZE);
        IvParameterSpec iv =new IvParameterSpec(ivBytes);
        SecretKeySpec keySpec = generateAesKey(password, salt);
        c.init(Cipher.DECRYPT_MODE, keySpec, iv);


        in.getChannel().position(ivAndSalt.length);

        int nread;
        int progress = 0;
        byte[] buf = new byte[8192];

        while((nread = in.read(buf)) != -1) {
                byte[] enc = c.update(buf, 0, nread);
                out.write(enc);
                progress++;

            /*if (enc.length / 8192 != 0)
                    System.out.println((nread*progress) + "%");*/
        }
        System.out.println("Size of out before doFinal(): " + out.getChannel().size());
        byte[] enc = c.doFinal();
        out.write(enc);
        System.out.println("Size of out after doFinal(): " + out.getChannel().size());
        return  outPutFile;
    } 

我在调用cryptoFile()时没有出错,但是生成的文件已损坏,这意味着解密中存在问题。

1 个答案:

答案 0 :(得分:0)

问题完全是愚蠢的,我忘记在doFinal()之后关闭输入和输出流,并将enc字节数组写入输出:

in.close();
out.close();