Hi i am creating a sample to lock file or folder in android. I have a issue when i encrypt or decrypt large size (more than 1 GB) file it takes too much time.
Please help me to encrypt and decrypt file fastly.
Here i am attaching code which i am using on below
if (!isEncrypted) {
FileInputStream fis = new FileInputStream(path);
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream(path + ".abcd");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("abcdefghijklmnop".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[1024];
try {
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
new File(path).deleteOnExit();
isEncrypted = true;
runOnUiThread(new Runnable() {
#Override
public void run() {
btnEncrypt.setText("Decrypt Path");
deleteMyFile(path);
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
FileInputStream fis = new FileInputStream(path + ".abcd");
FileOutputStream fos = new FileOutputStream(path);
SecretKeySpec sks = new SecretKeySpec("abcdefghijklmnop".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[1024];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
isEncrypted = false;
runOnUiThread(new Runnable() {
#Override
public void run() {
deleteMyFile(path + ".abcd");
btnEncrypt.setText("Encrypt Path");
}
});
}
} catch (final Exception e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setMessage(e.getMessage());
}
});
I hope you found a way to do this. But, here is how I do it.
I realized that writing our own AES classes in java Or C is not recommendable way if you are especially just focused on the end result. Java is pretty slow in comparison with C, but in java you can use multithreading whereas in C you can't. Of course there are aes c programs which do a better job. But using them is difficult. You said you want to encrypt 1GB file under a minute. So, do this.
Install Userland Or Termux and install openssl. Next cd to your file storage location and try aes encrypt command. To automate it, write a bash script and run it. Openssl can easily do 23 MBps to 68 MBps.
Related
Is it possible to download a PDF from server and save in format that only my application can read?
This is my working example used in my app ....hope this help you
Is it possible to download pdf from server and save
Yes i have use retrofit library to download pdf file from server you can use Volly or Loopj AsyncTask as well
After downloading pdf file you will get InputeStream object of file than encrypt that and store in app private folder (so no other application can able to use it)
public static File encryptAndSaveFileInPrivateFolder(
Context context, String albumName, InputStream inputStream, String fullFileName) {
File file = null;
try {
// Get the directory for the app's private pictures directory.
File fileDirectory = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES),""+albumName);
if (!fileDirectory.exists()) {
fileDirectory.mkdirs();
}
file = new File(fileDirectory,""+fullFileName);
if (file.exists()) {
file.delete();
}
FileOutputStream output = new FileOutputStream(file);
encrypt(inputStream,output);
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
This method encrypt your file
public static void encrypt(InputStream fis,FileOutputStream fos ) throws IOException, NoSuchAlgorithmException
, NoSuchPaddingException, InvalidKeyException {
// Here you read the cleartext.
//FileInputStream fis = new FileInputStream("data/cleartext");
// This stream write the encrypted text. This stream will be wrapped by another stream.
// FileOutputStream fos = new FileOutputStream("data/encrypted");
String password ="passwordProtectd";
// Length is 16 byte
byte[] inputByte = password.getBytes("UTF-8");
SecretKeySpec sks = new SecretKeySpec(inputByte, "AES");
// SecretKeySpec sks = new SecretKeySpec(password.getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
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();
}
Than show pdf using intent
public void decryptFileAndShow(Context context,File mFile) {
try{
if (null != mFile) {
String parentPath = mFile.getAbsoluteFile().getParent();//Actual encrypted file path
File tempFile = new File(parentPath, "report.pdf"); //Created new file that decrypted format after view we will delete this
//tempFile =File.createTempFile("prefix","TestMyPDF.pdf", context.getExternalFilesDir(""));
Utilities.decrypt( new FileInputStream(mFile), new FileOutputStream(tempFile));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(tempFile), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
context.startActivity(intent);
tempFile.deleteOnExit();
}
}catch (Exception e){
e.printStackTrace();
}
}
Last the method used for decryption
public static void decrypt(FileInputStream fis,FileOutputStream fos ) throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
// FileInputStream fis = new FileInputStream("data/encrypted");
// FileOutputStream fos = new FileOutputStream("data/decrypted");
String password ="passwordProtectd";
byte[] inputByte = password.getBytes("UTF-8");
SecretKeySpec sks = new SecretKeySpec(inputByte, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
Is it possible to download pdf from server.
Yes, it is possible. Download your pdf and encrypt and decrypt your file accordingly.
You can try like this using CipherOuputStream and CipherInputStream:
byte[] buf = new byte[1024];
Encryption:
public void encrypt(InputStream in, OutputStream out) {
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
}
}
Decryption:
public void decrypt(InputStream in, OutputStream out) {
try {
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
}
}
If I understand your question correctly, you want your application to be the only application that reads this particular PDF files. You want to know how you can ensure that you do that.
Since your requirement is not genuine(hacky), the solution also has to be a bit hacky.
You can download the file and store it with your own custom extension (eg. file.mypdf)
Have an intent filter, that supports mimetypes matching .mypdf files
You could have the server encrypt the download and your client side app decrypt it using a public/private key pair. This would prevent anyone with a snooping proxy from observing and saving your content, but it wouldn't deter the most determined users from stealing these documents as they would eventually exist in decrypted form somewhere. To achieve that you'd probably ave to create your own PDF viewer and damage the bytes of the PDF in a way that your viewer can do, but no other viewer can recover
So the scenario of my problem is in my application I am fetching some file from the internet then I put them in internal storage then when user wants to access these file User can access them through my application.
I did all the thing but I want to provide some security in my application So what I want is?
User can see my file only in my application. User unable to access them from the file manager. Don't tell me the solution to put dot
before file name or folder name I did that the problem with this
solution is when I access them by putting dot before file name the
file are again visible .
I also want that when the user open my file ,just like a pdf in pdf reader He/She restricted to save or download them through pdf
reader or another application.
Any Kind of help is appreciated by me.
You can encrypt that file so user won't be able to access them. here is the encryption method which works for me.
public void encrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
// Here you read your file.
FileInputStream fis = new FileInputStream("Path Of your file");
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream("Path Of your file");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
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();
}
Here is the method for decryption of particular file.
public void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream("Path Of your file");
FileOutputStream fos = new FileOutputStream("Path Of your file");
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();}
you can encrypt your files with an encryption algorithm and save them with your custom file extension then you can make an intent filter for opening them from File Manager and for more security i prefer the JNI For whole Encryption system .
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();
}
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.
IN our application we are getting byte array from server if login gets success. We are converting those byte array into PDF format and storing those files into DB which using internal memory.If files are in KB , application works properly but of files size get increase in MB then application gives out of memory error.Please tell me how to handle this scenario?How to store files into SD card to maintain security also.It should not visible to outside user.
Please do help.
Thanks,
AA.
You should take a look at:
CipherInputStream and CipherOutputStream. They are used to encrypt and decrypt byte streams.
EDIT: So here you go!
I have a file named cleartext. The file contains:
Hi, I'm a clear text.
How are you?
That's awesome!
Now, you have an encrypt() function:
static void encrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
// Here you read the cleartext.
FileInputStream fis = new FileInputStream("data/cleartext");
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream("data/encrypted");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
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();
}
After you execute this function, there should be a file names encrypted. The file contains the encrypted characters.
For decryption you have the decrypt function:
static void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream("data/encrypted");
FileOutputStream fos = new FileOutputStream("data/decrypted");
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
After the execution of decrypt, there should be a file named decrypted. This file contains the free text.
Edit: You write you're a "noob" but depending on the use-case of encryption you could do a lot of harm if you're not doing it the right way. Know your tools!
Usage of CipherOutputStream Oracle documentation:
SecretKeySpec skeySpec = new SecretKeySpec(y.getBytes(), "AES");
FileInputStream fis;
FileOutputStream fos;
CipherOutputStream cos;
// File you are reading from
fis = new FileInputStream("/tmp/a.txt");
// File output
fos = new FileOutputStream("/tmp/b.txt");
// Here the file is encrypted. The cipher1 has to be created.
// Key Length should be 128, 192 or 256 bit => i.e. 16 byte
SecretKeySpec skeySpec = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
Cipher cipher1 = Cipher.getInstance("AES");
cipher1.init(Cipher.ENCRYPT_MODE, skeySpec);
cos = new CipherOutputStream(fos, cipher1);
// Here you read from the file in fis and write to cos.
byte[] b = new byte[8];
int i = fis.read(b);
while (i != -1) {
cos.write(b, 0, i);
i = fis.read(b);
}
cos.flush();
Thus, the encryption should work. When you reverse the process, you should be able to read the decrypted bytes.
Storing on the SD card will make the file accessible to savvy users. Storing in the db will give you errors like you mentioned. Probably the best idea would be to go to internal storage. This isn't perfect (rooted users can browse to the files), but it's probably the best option.
http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
I am developing a file encryption and decryption app and to show the user a little progress bar of the file encryption and decryption. I need to implement a progress bar. How do I do that ? For the below code.
public void main(String[] args) throws Exception
{
// File to decrypt.
filename = "/file.enc";
String password = "codecodecode";
inFile = new FileInputStream(new File(Environment.getExternalStorageDirectory()+ filename));
outFile = new FileOutputStream(new File(Environment.getExternalStorageDirectory()+ filename + ".txt"));
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFactory =
SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey passwordKey = keyFactory.generateSecret(keySpec);
// Read in the previouly stored salt and set the iteration count.
byte[] salt = new byte[8];
inFile.read(salt);
int iterations = 100;
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations);
// Create the cipher and initialize it for decryption.
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.DECRYPT_MODE, passwordKey, parameterSpec);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inFile.read(input)) != -1)
{
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
outFile.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
outFile.write(output);
inFile.close();
outFile.flush();
outFile.close();
}
Check the tutorial on progress bars: https://developer.android.com/guide/topics/ui/dialogs.html#ShowingAProgressBar
There is also the "Example ProgressDialog with a second thread" - nice to check.
Also consider using AsyncTask for such kind of things, it has a built in support for publishing progress update events on UI thread.