ketan
ketan

Reputation: 61

Advise on file encryption performance in Java

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

Answers (4)

Mike Thomsen
Mike Thomsen

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

Jon Bright
Jon Bright

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

MahdeTo
MahdeTo

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

user23743
user23743

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

Related Questions