Reputation: 61
I am doing some file encryption related work. I am able to encrypt/decrypt the files but facing a major performance issue. When I simply read/write a video file of 700 MB size, my code performs at around 27-28 MB/s. But when I perform encryption(I am currently using PBEWithMD5AndDES, which I would be changing later) code shows speeds at 9 MB/s. Please advise as to where can I improve.
Code snippet:
int c = 0, BUF_SIZE = 8192;
byte[] b = new byte[BUF_SIZE];
FileInputStream fis;
DataInputStream dis;
FileOutputStream fos;
DataOutputStream dos;
CipherOutputStream cos;
try {
// Create PBE parameter set
pbeParamSpec = new PBEParameterSpec(salt, iterationCount);
// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance(algorithm);
// get key
key = generateKeyFromPassword(password);
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.ENCRYPT_MODE, key, pbeParamSpec);
fis = new FileInputStream(inFile);
dis = new DataInputStream(fis);
fos = new FileOutputStream(outFile);
dos = new DataOutputStream(fos);
cos = new CipherOutputStream(fos, pbeCipher);
while ((c = dis.read(b)) > 0) {
cos.write(b);
//dos.write(b);
}
fis.close();
dis.close();
//dos.close();
cos.close();
} catch (Exception e) {
e.printStackTrace();
}
Stats without encryption:
Speed is around 27.97 MB/s
Exact Time = 25.02 sec
File Size = 700 MB
Stats with encryption:
Speed is around 9.69 MB/s
Exact Time = 72.171 sec
File Size = 700 MB
Upvotes: 6
Views: 3670
Reputation: 37506
Have you tried BouncyCastle as an alternative? Everywhere I've seen Java cryptography used, it was used instead of the builtin APIs.
Upvotes: 0
Reputation: 13738
Firstly: if at all possible, don't do this yourself. Encryption is very (very!) easy to mess up in ways that lead to the results being insecure. If at all possible, use an external component or library to do as much of the encryption work as is practical.
Secondly, if you're going to do this yourself as now, don't use DES. DES is no longer a strong-enough cipher. Triple-DES is OK, but what you really want to be using is AES. It's regarded as secure, modern CPUs were kept in mind during its design, you get a choice of key lengths to balance security against performance and modern CPUs have hardware acceleration for AES (AES-NI). (I don't know whether Java uses this, but if it doesn't, it certainly might start to in future, whereas the chances of that for Triple-DES are zero.)
Thirdly, you're reading and writing a byte at a time. Whilst encryption is going to be CPU-intensive in any event, doing it as you are at the moment is going to be slower than necessary. Reading and writing via a byte[]
of 4kB or so should see much better performance.
Upvotes: 4
Reputation: 11184
Try wrapping the data input stream with a buffered input stream for starters. Also check this link for a performance comparison of different algorithms in java. AES will indeed yield a considerably faster result than DES.
Upvotes: 2
Reputation:
Encryption just is CPU intensive. Maybe you can find a more efficient implementation and shave a couple of % off the run time, or use a dedicated hardware engine and get better performance for quite a few dollars.
The first thing I would ensure though is that your application is able to cope with the fact that this will just take a while. This means putting the crypto into background operations, preparing content in advance of its use and similar design considerations.
Upvotes: 0