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

Popular posts from this blog

Simple car racing android game in Sketchware

Simple Audio recorder app in Sketchware

How to enable upload from webview in Sketchware?

Retrieve contact list in Sketchware

Creating a Drawing View in Sketchware