Many times when we are building an android application we have to encrypt the data entered by the user within the android application to maintain the data privacy and security of the application. Along with that we also have to decrypt the data to access it. In this article, we will take a look at How to encrypt and decrypt an image file in our android application. A sample video is given below to get an idea about what we are going to do in this article.
Note: This Android article covered in both Java and Kotlin languages.
Step by Step Implementation
Step 1: Create a New Project in Android Studio
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.
Step 2: Working with the activity_main.xml file
Navigate to app > res > layout > activity_main.xml and add the below code to it. Comments are added in the code to get to know in detail.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < RelativeLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".MainActivity" > <!--image view to display an image--> < ImageView android:id = "@+id/idIVimage" android:layout_width = "match_parent" android:layout_height = "300dp" android:layout_margin = "10dp" android:padding = "10dp" /> <!--button to encrypt the image--> < Button android:id = "@+id/idBtnEncrypt" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_below = "@id/idIVimage" android:layout_margin = "10dp" android:text = "Encrypt" /> <!--button to decrypt the image--> < Button android:id = "@+id/idBtnDecrypt" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_below = "@id/idBtnEncrypt" android:layout_margin = "10dp" android:text = "Decrypt" /> </ RelativeLayout > |
Step 3: Working with the MainActivity file
Navigate to app > java > your app’s package name > MainActivity file and add the below code to it. Comments are added in the code to get to know in detail.
Java
package com.gtappdevelopers.encryptionanddecryption; import android.content.ContextWrapper; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; public class MainActivity extends AppCompatActivity { // on below line creating a // variable for image view and button. private ImageView imageView; private Button encBtn, decBtn; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); // on below line initializing the variables. imageView = findViewById(R.id.idIVimage); encBtn = findViewById(R.id.idBtnEncrypt); decBtn = findViewById(R.id.idBtnDecrypt); // on below line adding click listener for encrypt button. encBtn.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // on below line we are picking the image to encrypt it. Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(i, 1 ); } }); // on below line adding click listener for decrypt button. decBtn.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // on below line calling decrypt // method to decrypt our image. try { decrypt(); } catch (Exception e) { // displaying a toast message // if decryption fails. Toast.makeText(MainActivity. this , "Fail to decrypt image" , Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } }); } public void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { // on below line creating and initializing variable for context wrapper. ContextWrapper contextWrapper = new ContextWrapper(getApplication()); // on below line creating a file for getting photo directory. File photoDir = contextWrapper.getExternalFilesDir(Environment.DIRECTORY_DCIM); // on below line creating a new file for encrypted image. File file = new File(photoDir, "encfile" + ".png" ); // on below line creating input stream for file with file path. FileInputStream fis = new FileInputStream(file.getPath()); // on below line creating a file for decrypted image. File decFile = new File(photoDir, "decfile.png" ); // on below line creating an file output stream for decrypted image. FileOutputStream fos = new FileOutputStream(decFile.getPath()); // creating a variable for secret key and passing our secret key // and algorithm for encryption. SecretKeySpec sks = new SecretKeySpec( "KERQIRUDYTH" .getBytes(), "AES" ); // on below line creating a variable // for cipher and initializing it Cipher cipher = Cipher.getInstance( "AES" ); // on below line initializing cipher and // specifying decrypt mode to decrypt. cipher.init(Cipher.DECRYPT_MODE, sks); // on below line creating a variable for cipher input stream. CipherInputStream cis = new CipherInputStream(fis, cipher); // on below line creating a variable b. int b; byte [] d = new byte [ 8 ]; while ((b = cis.read(d)) != - 1 ) { fos.write(d, 0 , b); } // on below line flushing our fos, // closing fos and closing cis. fos.flush(); fos.close(); cis.close(); // displaying toast message. Toast.makeText( this , "File decrypted successfully.." , Toast.LENGTH_SHORT).show(); // on below line creating an image file // from decrypted image file path. File imgFile = new File(decFile.getPath()); if (imgFile.exists()) { // creating bitmap for image and displaying // that bitmap in our image view. Bitmap bitmap = BitmapFactory.decodeFile(imgFile.getPath()); imageView.setImageBitmap(bitmap); } } // on below line creating a method to encrypt an image. private void encrypt(String path) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { // on below line creating a variable for file input stream FileInputStream fis = new FileInputStream(path); // on below line creating a variable for context wrapper. ContextWrapper contextWrapper = new ContextWrapper(getApplication()); // on below line creating a variable for file File photoDir = contextWrapper.getExternalFilesDir(Environment.DIRECTORY_DCIM); // on below line creating a file for encrypted file. File file = new File(photoDir, "encfile" + ".png" ); // on below line creating a variable for file output stream. FileOutputStream fos = new FileOutputStream(file.getPath()); // on below line creating a variable for secret key. // creating a variable for secret key and passing our secret key // and algorithm for encryption. SecretKeySpec sks = new SecretKeySpec( "KERQIRUDYTH" .getBytes(), "AES" ); // on below line creating a variable for cipher and initializing it Cipher cipher = Cipher.getInstance( "AES" ); // on below line initializing cipher and // specifying decrypt mode to encrypt. cipher.init(Cipher.ENCRYPT_MODE, sks); // on below line creating cos CipherOutputStream cos = new CipherOutputStream(fos, cipher); int b; byte [] d = new byte [ 8 ]; while ((b = fis.read(d)) != - 1 ) { cos.write(d, 0 , b); } // on below line closing // our cos and fis. cos.flush(); cos.close(); fis.close(); } @Override protected void onActivityResult( int requestCode, int resultCode, @Nullable Intent data) { super .onActivityResult(requestCode, resultCode, data); // on below line getting image uri if (requestCode == 1 && resultCode == RESULT_OK && null != data) { // on below line getting image uri. Uri imgUri = data.getData(); // on below line getting file path String[] filePath = {MediaStore.Images.Media.DATA}; // on below line creating a cursor and moving to next. Cursor cursor = getContentResolver().query(imgUri, filePath, null , null , null ); cursor.moveToFirst(); // on below line creating an index for column int columnIndex = cursor.getColumnIndex(filePath[ 0 ]); // on below line creating a string for path. String picPath = cursor.getString(columnIndex); // on below line closing our cursor. cursor.close(); // on below line we are encrypting our image. try { encrypt(picPath); // on below line we are encrypting our image. Toast.makeText( this , "Image encrypted.." , Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText( this , "Fail to encrypt image : " + e, Toast.LENGTH_SHORT).show(); } } } } |
Kotlin
package com.gtappdevelopers.bottomsheetexample import android.content.ContextWrapper import android.content.Intent import android.graphics.BitmapFactory import android.os.Bundle import android.os.Environment import android.provider.MediaStore import android.widget.* import androidx.appcompat.app.AppCompatActivity import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.util.* import javax.crypto.Cipher import javax.crypto.CipherInputStream import javax.crypto.CipherOutputStream import javax.crypto.spec.SecretKeySpec class MainActivity : AppCompatActivity() { // on below line creating a variable // for key, image view, and buttons. val key: String = "KERQIRUDYTH" lateinit var imageView: ImageView lateinit var encryptButton: Button lateinit var decryptButton: Button override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_main) encryptButton = findViewById(R.id.idBtnEncrypt) decryptButton = findViewById(R.id.idBtnDecrypt) imageView = findViewById(R.id.idIVImage) encryptButton.setOnClickListener { val i = Intent( Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI ) startActivityForResult(i, 1 ) } decryptButton.setOnClickListener { // on below line calling // method to decrypt image. decrypt() } } fun decrypt() { // on below line creating and initializing // variable for context wrapper. val contextWrapper = ContextWrapper(application) // on below line creating a file for getting photo directory. val photoDir = contextWrapper.getExternalFilesDir(Environment.DIRECTORY_DCIM) // on below line creating a new file for encrypted image. val file = File(photoDir, "encfile" + ".png" ) // on below line creating input stream for file with file path. val fis = FileInputStream(file.path) // on below line creating a file for decrypted image. val decFile = File(photoDir, "decfile.png" ) // on below line creating an file output // stream for decrypted image. val fos = FileOutputStream(decFile.path) val bytes = key.toByteArray() // creating a variable for secret key and passing // our secret key and algorithm for encryption. val sks = SecretKeySpec(bytes, "AES" ) // on below line creating a variable for // cipher and initializing it val cipher = Cipher.getInstance( "AES" ) // on below line initializing cipher and // specifying decrypt mode to decrypt. cipher.init(Cipher.DECRYPT_MODE, sks) // on below line creating a variable // for cipher input stream. val cis = CipherInputStream(fis, cipher) // on below line creating a variable b. var b: Int val d = ByteArray( 8 ) while ((b = cis.read(d)) != - 1 ) { fos.write(d, 0 , b) } // on below line flushing our fos, // closing fos and closing cis. fos.flush() fos.close() cis.close() // displaying toast message. Toast.makeText( this , "Image decrypted successfully.." , Toast.LENGTH_SHORT).show() // on below line creating an image file // from decrypted image file path. val imgFile = File(decFile.path) if (imgFile.exists()) { // creating bitmap for image and displaying // that bitmap in our image view. val bitmap = BitmapFactory.decodeFile(imgFile.path) imageView.setImageBitmap(bitmap) } } // on below line creating a method to encrypt an image. private fun encrypt(path: String) { // on below line creating a // variable for file input stream val fis = FileInputStream(path) // on below line creating a variable for context wrapper. val contextWrapper = ContextWrapper(application) // on below line creating a variable for file val photoDir = contextWrapper.getExternalFilesDir(Environment.DIRECTORY_DCIM) // on below line creating a file for encrypted file. val file = File(photoDir, "encfile" + ".png" ) // on below line creating a variable for file output stream. val fos = FileOutputStream(file.path) // on below line creating a variable for secret key. // creating a variable for secret key and passing our // secret key and algorithm for encryption. val sks = SecretKeySpec(key.toByteArray(), "AES" ) // on below line creating a variable for // cipher and initializing it val cipher = Cipher.getInstance( "AES" ) // on below line initializing cipher and // specifying decrypt mode to encrypt. cipher.init(Cipher.ENCRYPT_MODE, sks) // on below line creating cos val cos = CipherOutputStream(fos, cipher) var b: Int val d = ByteArray( 8 ) while ((b = fis.read(d)) != - 1 ) { fos.write(d, 0 , b) } // on below line // closing our cos and fis. cos.flush() cos.close() fis.close() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super .onActivityResult(requestCode, resultCode, data) // on below line getting image uri if (requestCode == 1 && resultCode == RESULT_OK && null != data) { // on below line getting image uri. val imgUri = data.data // on below line getting file path val filePath = arrayOf(MediaStore.Images.Media.DATA) // on below line creating a cursor and moving to next. val cursor = contentResolver.query(imgUri!!, filePath, null , null , null ) cursor!!.moveToFirst() // on below line creating an index for column val columnIndex = cursor.getColumnIndex(filePath[ 0 ]) // on below line creating a string for path. val picPath = cursor.getString(columnIndex) // on below line closing our cursor. cursor.close() // on below line we are encrypting our image. try { encrypt(picPath) // on below line we are encrypting our image. Toast.makeText( this , "Image encrypted.." , Toast.LENGTH_SHORT).show() } catch (e: Exception) { e.printStackTrace() Toast.makeText( this , "Fail to encrypt image : $e" , Toast.LENGTH_SHORT).show() } } } } |
Step 4: Adding permissions in the AndroidManifest.xml file
Navigate to the AndroidManifest.xml file and add the below permissions to it to read and write to external storage.
XML
< uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" /> < uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" /> |
Now run your application to see the output of it.
Output: