Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 797
ketan Avatar asked Jan 29 '12 10:01

ketan


2 Answers

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.

like image 174
Jon Bright Avatar answered Oct 07 '22 18:10

Jon Bright


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.

like image 36
MahdeTo Avatar answered Oct 07 '22 18:10

MahdeTo