EncryptionHelper for encrypting json file
Add below code in a Java file named EncryptionHelper.java.
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.util.Base64;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptionHelper {
// Derive AES SecretKey from passphrase
public static SecretKey deriveKeyFromPassphrase(String passphrase, byte[] salt) throws Exception {
int iterations = 100000;
int keyLength = 256;
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, iterations, keyLength);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] keyBytes = factory.generateSecret(spec).getEncoded();
return new SecretKeySpec(keyBytes, "AES");
}
// Encrypt file
public static void encryptSelectedFile(Context context, Uri inputUri, SecretKey secretKey, String outputFileName) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] iv = cipher.getIV();
ContentValues values = new ContentValues();
values.put(MediaStore.Downloads.DISPLAY_NAME, outputFileName);
values.put(MediaStore.Downloads.MIME_TYPE, "application/octet-stream");
values.put(MediaStore.Downloads.IS_PENDING, 1);
ContentResolver resolver = context.getContentResolver();
Uri collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri fileUri = resolver.insert(collection, values);
try (
ParcelFileDescriptor pfd = resolver.openFileDescriptor(fileUri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher);
InputStream inputStream = resolver.openInputStream(inputUri)
) {
fileOutputStream.write(iv);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
cipherOutputStream.write(buffer, 0, bytesRead);
}
cipherOutputStream.flush();
}
values.clear();
values.put(MediaStore.Downloads.IS_PENDING, 0);
resolver.update(fileUri, values, null, null);
Toast.makeText(context, "File encrypted to: " + fileUri.toString(), Toast.LENGTH_LONG).show();
}
// Decrypt encrypted file and save output to Downloads
public static void decryptSelectedFile(Context context, Uri encryptedFileUri, SecretKey secretKey, String outputFileName) throws Exception {
ContentResolver resolver = context.getContentResolver();
try (InputStream inputStream = resolver.openInputStream(encryptedFileUri)) {
byte[] iv = new byte[12];
if (inputStream.read(iv) != iv.length) {
throw new IllegalArgumentException("Invalid IV in encrypted file");
}
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec);
ContentValues values = new ContentValues();
values.put(MediaStore.Downloads.DISPLAY_NAME, outputFileName);
values.put(MediaStore.Downloads.MIME_TYPE, "application/octet-stream");
values.put(MediaStore.Downloads.IS_PENDING, 1);
Uri collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri decryptedFileUri = resolver.insert(collection, values);
try (
ParcelFileDescriptor pfd = resolver.openFileDescriptor(decryptedFileUri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher)
) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
}
fileOutputStream.flush();
}
values.clear();
values.put(MediaStore.Downloads.IS_PENDING, 0);
resolver.update(decryptedFileUri, values, null, null);
Toast.makeText(context, "File decrypted to: " + decryptedFileUri.toString(), Toast.LENGTH_LONG).show();
}
}
// Decrypt the file to a String
public static String decryptToString(InputStream encryptedInputStream, SecretKey secretKey) throws Exception {
// Read the 12-byte IV from the beginning of the encrypted input
byte[] iv = new byte[12];
if (encryptedInputStream.read(iv) != iv.length) {
throw new IllegalArgumentException("Invalid IV in encrypted input");
}
// Initialize AES-GCM Cipher for decryption
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec);
// Use CipherInputStream to decrypt the input stream
try (
CipherInputStream cipherInputStream = new CipherInputStream(encryptedInputStream, cipher);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
return outputStream.toString(StandardCharsets.UTF_8.name());
}
}
// Get file name from Uri
public static String getFileNameFromUri(Context context, Uri uri) {
String result = null;
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (nameIndex != -1) {
result = cursor.getString(nameIndex);
}
}
} finally {
cursor.close();
}
}
return result;
}
}
Comments
Post a Comment