Challenge 8 – Show encrypted images in Flutter

Hi there.

I was trying to implement a feature that faced me with a great challenge.

When I solved it, I decided to share it with you.

1. The challenge:

The challenge was to show an encrypted image file in the Flutter.

Suppose you have some image files that are encrypted with a specific algorithm, and you are able to decrypt them programmatically in dart (no matter what algorithm you are using).

To make it simple, let’s suppose we have an abstract EncryptionHelper class with two abstract functions. encrypt and decrypt (Implementation doesn’t matter here)

abstract class EncryptionHelper {
  Future<Uint8List> encrypt(Uint8List key, Uint8List rawBytes);
  Future<Uint8List> decrypt(Uint8List key, Uint8List encryptedBytes);
}

They both are Future functions. It means they work asynchronously.

(Uint8List is a built-in byte array data structure in the dart language)

2. My initial thoughts

At first, I came up with a simple solution.

We can load all files and decrypt them in our domain layer. Then we can pass a list of decrypted image bytes (something like final List<Uint8List> images; to our presentation layer.

Then we can use Image.memory(bytes) to show each image in a list.

That works! But as you might know, there is a big problem with memory usage.

For example, if we have 1000 images to show, we need to keep all 1000 images in our memory to show them.

That’s why I started to think about another solution.

3. My solution using ImageProvider:

As you know, flutter has a built-in Image.file() constructor which we can pass an image file directly, and it shows the image properly.
But the problem is that it works with raw (non-encrypted) image files. In our case, we have some encrypted image files.

I tried to read the source code. Then I realized that it uses a FileImage class that extends the ImageProvider class.

There is a _loadAsync() function in the ImageProvider class, which loads a byte array (Uint8List) from the provided file and passes it to another component.

The idea is to create a class that works exactly like FileImage class, except where it loads the bytes array and passes it to another component. We can modify our customized class to decrypt the bytes and pass the decrypted bytes to another component.

Let’s call our new class EncryptedFileImage. It extends ImageProvider. Check the below code:

class EncryptedFileImage extends ImageProvider<EncryptedFileImage> {
  Future<ui.Codec> _loadAsync(
      EncryptedFileImage key, DecoderCallback decode) async {
    // ...

    final encryptedBytes = await file.readAsBytes();
    final bytes = EncryptionHelper().decrypt(encryptedBytes, myKey);

    // Instead of:
    // final bytes = await file.readAsBytes();

    // ...
  }
}

As you see, I commented final bytes = await file.readAsBytes(); line to rewrite it with our customized logic. Now it reads an encryptedBytes from our file and decrypts it asynchronously, then it fills the bytes parameter to let the class work with the default behavior.

4. Use EncryptedFileImage in the app

Now we can use our customized EncryptedFileImage (which extends ImageProvider) in the app just like the other built-in image providers such as AssetImages and FileImage.

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: Image(
        image: EncryptedFileImage(encryptedImageFile),
      ),
    ),
  );
}

Or

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Container(
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        image: DecorationImage(
          image: EncryptedFileImage(encryptedImageFile),
        ),
      ),
    ),
  );
}

I tried to show how it works in a real app. You can check the source code here.

Don’t forget to subscribe and write your comment about this article.

Stay safe!

Comments (2)
Add Comment
  • Abu Saad Papa

    How to encrypt the images ?
    Please inform me the steps to encrypt the images. As of now I am not able to encrypt images to use in the app. I want to encrypt the images outside the app using python or some other code and use the encrypted images in the Flutter code. The encrypted images I am using is not working in this app.

    Thank You.

    • Iman Khoshabi

      You’re welcome.
      You can search “python AES encrypt images” (You can use any encryption method you want, I used AES as an example)