I am trying to write some methods to handle encryption of zip files, most are very large (over 200 mb). At first it was attempted to load the file into memory, create a Base64encoded string and encrypt that back out to a file. But not nearly enough memory to do that, and generally as files get larger, it would not be possible to support that. So instead I am opting for something like CipherOutputStreams, read in, write out without buffer. on Small files, this is great (smaller than 1 mb) as it happens instantly. But when it get up to the 200MB minimum size of our zips, it takes hours. Is there any way I can speed this up? (See code below)
import java.util.*;
import java.io.*;
import java.util.zip.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class EncryptedZipUtil
{
private static final String ALGO = "DESede";
private static final String CIPHER_ALGO = "DESede/CBC/PKCS5Padding";
private static final byte[] IV_PARAMS = new byte[] {
127, 111, 13, 120, 12, 34, 56, 78
};
private static final String ENCODING = "UTF-8";
private static final byte[] ENCRIPTION_KEY = "Encryption key must be at least 30 characters long".getBytes();
private static Cipher getCipher(int mode) throws Throwable
{
DESedeKeySpec spec = new DESedeKeySpec(ENCRIPTION_KEY);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGO);
SecretKey theKey = keyFactory.generateSecret(spec);
Cipher dcipher = Cipher.getInstance(CIPHER_ALGO);
IvParameterSpec IvParameters = new IvParameterSpec(IV_PARAMS);
dcipher.init(mode, theKey, IvParameters);
return dcipher;
}
public static ZipInputStream getDecryptedZipStream(File f) throws SecurityException, IOException
{
FileInputStream fin = new FileInputStream(f);
return new ZipInputStream(new CipherInputStream(fin,getCipher(Cipher.DECRYPT_MODE)));
}
public static void streamEncryptZipFile(File zipFile, File outzip) throws Throwable
{
FileInputStream fin = new FileInputStream(zipFile);
CipherOutputStream cos = new CipherOutputStream(new FileOutputStream(outzip),getCipher(Cipher.ENCRYPT_MODE));
while(fin.available() != 0)
{
cos.write(fin.read());
}
fin.close();
cos.close();
}
public static void streamDecryptZipFile(File e_zipFile, File outzip) throws Throwable
{
CipherInputStream cin = new CipherInputStream(new FileInputStream(e_zipFile),getCipher(Cipher.DECRYPT_MODE));
FileOutputStream fos = new FileOutputStream(outzip);
int the_byte = -1;
while((the_byte = cin.read()) != -1)
{
fos.write(the_byte);
}
cin.close();
fos.close();
}
public static void main(String[] args) throws Throwable
{
EncryptedZipUtil.streamEncryptZipFile("D:\\ziptest\\original.zip","D:\\ziptest\\encrypted.zip");
EncryptedZipUtil.streamDecryptZipFile("D:\\ziptest\\encrypted.zip","D:\\ziptest\\decrypted.zip");
}
}
Like I said, the code here works great with small files. Quick, correct and simple. My Machine is 2.8ghz P4, with 1024mb Ram, and when I run this on my larger files, it uses 99% CPU and no memory in addition to the standard JVM Heap.
Any advice would be greatly appreciated