Best way to store pdf files in android - android

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

Related

Online AES Encrypted Stream with ExoPlayer in Android

So I am a beginner to ExoPlayer, and I'm using ExoPlayer v2.11.3 to play encrypted videos.
I've checked this question here, but it did not help me to do it since it is an old post since 2017!
What I think, that I need to create a custom DataSource from "DefaultHttpDataSource".
I'm using this "Encrypt()" method to do the AES encryption:
private static void encrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
if (hasFile()) {
Log.d("Encrypt", "encrypted file found, no need to recreate");
return;
}
// Video Reading.
FileInputStream fis = new FileInputStream(toBeEncryptedFile);
// This stream write the encrypted video. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream(encryptedFile);
// Create cipher
cipher = Cipher.getInstance(AES_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
byte[] buffer = new byte[1024 * 1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
cos.write(buffer, 0, bytesRead);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
}
You can create custom DataSource while overriding Open() and close(). You can create data input stream with the cipher initiated in the same method.

How can I lock a file in android?

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 .

Android AES-128 encryption/decryption of file is very slow. How can I increase the speed

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.

How to lock Android folder programmatically?

I am making an Android application, and I want to prevent users from opening some folder. In that folder user can store image or video files. It would be great if I could protect that folder with password.
Which is the best way to do that?
Here is Both function for encrypt and decrypt file in Sdcard folder.
we can not lock folder but we can encrypt file using AES in Android, it may help you.
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();
}
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();
}
You should save this information on the internal storage. Normally other apps can't access these files. From the quideliness:
You can save files directly on the device's internal storage. By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user). When the user uninstalls your application, these files are removed.
See the link: http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
Insted of LOCK i will saggest you make folder with . like foldername -> .test
user cant see that folder here is code
File direct = new File(Environment.getExternalStorageDirectory() + "/.test");
if(!direct.exists())
{
if(direct.mkdir())
{
//directory is created;
}
}
above code is create folder with name ".test" (in SD CARD) then save your data(file, video.. whatever) in this folder user cant access it.
if you create folder in internal storage then if user clear data of your app then that folder may EMPTY!

How to encrypt file from SD card using AES in Android?

I want to encrypt image from the sd card and store it again in SD card again using AES. The main idea is the application browse an image, then encrypt it when I push a button, then store it in sd card. so my image would be secure.
I already succeed do string encryption using AES from this tutorial http://www.androidsnippets.com/encryptdecrypt-strings, but I don't have idea how to do this with an image, not string.
This is how I do it with a string:
public static String encrypt(String seed, String cleartext) throws Exception
{
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
Can anyone help me give example code how to encrypt an image with AES?
maybe it must using I/O file stream but I don't have an idea how to implement with this code.
If you take user input for the password make sure to read this answer.
You should take a look at:
CipherInputStream and CipherOutputStream. They are used to encrypt and decrypt byte streams.
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
// Careful when taking user input!!! https://stackoverflow.com/a/3452620/1188357
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.
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.
Starting android 10, there have been huge storage restrictions, so DocumentFile is going to be common compared to File class. So I am also providing answer using Uri.
fun Activity.encrypt(curLocUri: Uri, newLocUri: Uri, password: String, salt: String) : Boolean{
// opening file input/outputStreams
val fis = contentResolver.openInputStream(curLocUri) ?: return false
val fos = contentResolver.openOutputStream(newLocUri) ?: return false
try {
var key: ByteArray = ("$salt$password").toByteArray(Charsets.UTF_8)
val sha: MessageDigest = MessageDigest.getInstance("SHA-1")
key = sha.digest(key)
key = key.copyOf(16)
val sks = SecretKeySpec(key, "AES")
val cipher: Cipher = Cipher.getInstance("AES")
cipher.init(Cipher.ENCRYPT_MODE, sks)
val cos = CipherOutputStream(fos, cipher)
var b: Int
val d = ByteArray(8)
while (fis.read(d).also { b = it } != -1) {
cos.write(d, 0, b)
}
cos.flush()
cos.close()
return true
} catch (e: Throwable){
fis.close()
fos.close()
return false
}
}
fun Activity.decrypt(curLocUri: Uri, newLocUri: Uri, password: String, salt: String): Boolean {
// opening file input/outputStreams
val fis = contentResolver.openInputStream(curLocUri) ?: return false
val fos = contentResolver.openOutputStream(newLocUri) ?: return false
try {
var key: ByteArray = ("$salt$password").toByteArray(Charsets.UTF_8)
val sha = MessageDigest.getInstance("SHA-1")
key = sha.digest(key)
key = Arrays.copyOf(key, 16)
val sks = SecretKeySpec(key, "AES")
val cipher = Cipher.getInstance("AES")
cipher.init(Cipher.DECRYPT_MODE, sks)
val cis = CipherInputStream(fis, cipher)
var b: Int
val d = ByteArray(8)
while (cis.read(d).also { b = it } != -1) {
fos.write(d, 0, b)
}
fos.flush()
fos.close()
cis.close()
return true
} catch (e: Throwable){
fos.flush()
fos.close()
return false
}
}
Here Uri s are the one received from file picker from onActivityResult.
For examples, you can find it here

Categories

Resources