I am developing an android app that secures images and videos like Vaulty and Keep safe. I am trying to use AES-128 encryption/decryption technique to store images and videos. I tried it by taking 3 sample images of size 5.13, 4.76 and 5.31 respectively. But the time it is consuming to encrypt is 25s, 22s, 27s respectively and time to decrypt is 31s, 30s, 34s respectively. I am testing it on HTC One X.
Such speed wont be feasible for my app as users will scroll and view images quickly without interruption. Can you please suggest me how can I improve the performance(speed) or should i switch to other algorithms? Can you please suggest me any other techniques through which i can encrypt/decrypt images and videos quickly without compromising security too much.
I tried Vaulty and Keep safe, and they are very quick. Vaulty is said to be using AES-256, but it is still very fast and responsive in terms of encrypting and viewing images. How is it possible that vaulty is that quick using AES-256?
Code I am using is:
static void encrypt(String filename) throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
// Here you read the cleartext.
File extStore = Environment.getExternalStorageDirectory();
startTime = System.currentTimeMillis();
Log.i("Encryption Started",extStore + "/5mbtest/"+filename);
FileInputStream fis = new FileInputStream(extStore + "/5mbtest/"+filename);
// This stream write the encrypted text. This stream will be wrapped by
// another stream.
FileOutputStream fos = new FileOutputStream(extStore + "/5mbtest/"+filename+".aes", false);
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(),
"AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
stopTime = System.currentTimeMillis();
Log.i("Encryption Ended",extStore + "/5mbtest/"+filename+".aes");
Log.i("Time Elapsed", ((stopTime - startTime)/1000.0)+"");
}
static void decrypt(String filename) throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
File extStore = Environment.getExternalStorageDirectory();
Log.i("Decryption Started",extStore + "/5mbtest/"+filename+".aes");
FileInputStream fis = new FileInputStream(extStore + "/5mbtest/"+filename+".aes");
FileOutputStream fos = new FileOutputStream(extStore + "/5mbtest/"+"decrypted"+filename,false);
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(),
"AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, sks);
startTime = System.currentTimeMillis();
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
stopTime = System.currentTimeMillis();
Log.i("Decryption Ended",extStore + "/5mbtest/"+"decrypted"+filename);
Log.i("Time Elapsed", ((stopTime - startTime)/1000.0)+"");
fos.flush();
fos.close();
cis.close();
}
As shown above, even with a supercomputer, it would take 1 billion billion years to crack the 128-bit AES key using brute force attack. This is more than the age of the universe (13.75 billion years).
Decrypting your harddisk of 90GB should take no more than 5 minutes on a modern high end gaming computer.
XTS mode is the most common if you are encoding a random accessible data (like a hard disk or RAM). OCB is by far the best mode, as it allows encryption and authentication in a single pass.
Yes, with AES-128-CBC, it is possible to decrypt just a single block of cyphertext. Each block is 128 bits (16 bytes).
One thing that is making your code run slow is the size of your buffer:
byte[] d = new byte[8];
You should bump it up by a few orders of magnitude if you want it to run fast. Given the size of your files I would suggest using at least 1 MB but nowadays you can realistically set it to a few MBs, even on Android. Try changing it to:
byte[] d = new byte[1024 * 1024];
and let us know how much did that improve the speed by.
Use a larger buffer as suggested by @MikeLaren, and also wrap the FileOutputStream
in a BufferedOutputStream.
When decrypting, wrap the FileInputStream
in a BufferedInputStream
. Or do both in both cases: no harm done.
No need for heroic buffer sizes like a megabyte: 8k or 32k is sufficient.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With