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

Creating a Drawing View in Sketchware

How to enable upload from webview in Sketchware?

Get frames in a video in Sketchware

Create a full screen dialog with CropImageView