{"id":1956,"date":"2022-05-07T20:09:27","date_gmt":"2022-05-07T20:09:27","guid":{"rendered":"https:\/\/flutter4fun.com\/?p=1956"},"modified":"2022-05-07T20:11:19","modified_gmt":"2022-05-07T20:11:19","slug":"challenge-8","status":"publish","type":"post","link":"https:\/\/flutter4fun.com\/challenge-8\/","title":{"rendered":"Challenge 8 \u2013 Show encrypted images in Flutter"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"2160\" height=\"1254\" src=\"https:\/\/flutter4fun.com\/wp-content\/uploads\/2022\/05\/Challenge-8.jpg\" alt=\"\" class=\"wp-image-1978\" srcset=\"https:\/\/flutter4fun.com\/wp-content\/uploads\/2022\/05\/Challenge-8.jpg 2160w, https:\/\/flutter4fun.com\/wp-content\/uploads\/2022\/05\/Challenge-8-300x174.jpg 300w, https:\/\/flutter4fun.com\/wp-content\/uploads\/2022\/05\/Challenge-8-1024x594.jpg 1024w, https:\/\/flutter4fun.com\/wp-content\/uploads\/2022\/05\/Challenge-8-768x446.jpg 768w, https:\/\/flutter4fun.com\/wp-content\/uploads\/2022\/05\/Challenge-8-1536x892.jpg 1536w, https:\/\/flutter4fun.com\/wp-content\/uploads\/2022\/05\/Challenge-8-2048x1189.jpg 2048w\" sizes=\"auto, (max-width: 2160px) 100vw, 2160px\" \/><\/figure>\n\n\n\n<p>Hi there.<\/p>\n\n\n\n<p>I was trying to implement a feature that faced me with a great challenge. <\/p>\n\n\n\n<p>When I solved it, I decided to share it with you.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. The challenge:<\/h3>\n\n\n\n<p>The challenge was to show an encrypted image file in the <a href=\"http:\/\/flutter.dev\/\">Flutter<\/a>.<\/p>\n\n\n\n<p>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).<\/p>\n\n\n\n<p>To make it simple, let&#8217;s suppose we have an abstract <code>EncryptionHelper<\/code> class with two abstract functions. <code>encrypt<\/code> and <code>decrypt<\/code> (Implementation doesn&#8217;t matter here)<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">abstract class EncryptionHelper {\n  Future&lt;Uint8List> encrypt(Uint8List key, Uint8List rawBytes);\n  Future&lt;Uint8List> decrypt(Uint8List key, Uint8List encryptedBytes);\n}<\/pre>\n\n\n\n<p>They both are <a rel=\"noreferrer noopener\" href=\"https:\/\/api.dart.dev\/stable\/2.16.2\/dart-async\/Future-class.html\" target=\"_blank\">Future<\/a> functions. It means they work asynchronously.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<p>(<a rel=\"noreferrer noopener\" href=\"https:\/\/api.flutter.dev\/flutter\/dart-typed_data\/Uint8List-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/dart-typed_data\/Uint8List-class.html\" target=\"_blank\">Uint8List<\/a> is a built-in byte array data structure in the <a rel=\"noreferrer noopener\" href=\"https:\/\/dart.dev\/\" data-type=\"URL\" data-id=\"https:\/\/dart.dev\/\" target=\"_blank\">dart<\/a> language)<\/p>\n<\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">2. My initial thoughts<\/h3>\n\n\n\n<p>At first, I came up with a simple solution. <\/p>\n\n\n\n<p>We can load all files and decrypt them in our domain layer. Then we can pass a list of decrypted image bytes (something like <code>final List&lt;Uint8List&gt; images;<\/code> to our presentation layer. <\/p>\n\n\n\n<p>Then we can use <code>Image.memory(bytes)<\/code> to show each image in a list.<\/p>\n\n\n\n<p>That works! But as you might know, there is a big problem with memory usage.<\/p>\n\n\n\n<p>For example, if we have 1000 images to show, we need to keep all 1000 images in our memory to show them.<\/p>\n\n\n\n<p>That&#8217;s why I started to think about another solution.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><meta charset=\"utf-8\">3. My solution using ImageProvider:<\/h3>\n\n\n\n<p>As you know, flutter has a built-in <a rel=\"noreferrer noopener\" href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/Image\/Image.file.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/widgets\/Image\/Image.file.html\" target=\"_blank\">Image.file()<\/a> constructor which we can pass an image file directly, and it shows the image properly. <br>But the problem is that it works with raw (non-encrypted) image files. In our case, we have some encrypted image files.<\/p>\n\n\n\n<p>I tried to read the source code. Then I realized that it uses a <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/flutter\/flutter\/blob\/5464c5bac7\/packages\/flutter\/lib\/src\/painting\/image_provider.dart#L856\" data-type=\"URL\" data-id=\"https:\/\/github.com\/flutter\/flutter\/blob\/5464c5bac7\/packages\/flutter\/lib\/src\/painting\/image_provider.dart#L856\" target=\"_blank\">FileImage<\/a> class that extends the <a rel=\"noreferrer noopener\" href=\"https:\/\/api.flutter.dev\/flutter\/painting\/ImageProvider-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/painting\/ImageProvider-class.html\" target=\"_blank\">ImageProvider<\/a> class.<\/p>\n\n\n\n<p>There is a <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/flutter\/flutter\/blob\/5464c5bac742001448fe4fc0597be939379f88ea\/packages\/flutter\/lib\/src\/painting\/image_provider.dart#L887\" data-type=\"URL\" data-id=\"https:\/\/github.com\/flutter\/flutter\/blob\/5464c5bac742001448fe4fc0597be939379f88ea\/packages\/flutter\/lib\/src\/painting\/image_provider.dart#L887\" target=\"_blank\">_loadAsync()<\/a> function in the <meta charset=\"utf-8\"><a rel=\"noreferrer noopener\" href=\"https:\/\/api.flutter.dev\/flutter\/painting\/ImageProvider-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/painting\/ImageProvider-class.html\" target=\"_blank\">ImageProvider<\/a> class, which loads a byte array (Uint8List) from the provided file and passes it to another component.<\/p>\n\n\n\n<p>The idea is to create a class that works exactly like <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/flutter\/flutter\/blob\/5464c5bac7\/packages\/flutter\/lib\/src\/painting\/image_provider.dart#L856\" target=\"_blank\">FileImage<\/a> 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.<\/p>\n\n\n\n<p>Let&#8217;s call our new class <code><meta charset=\"utf-8\"><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/Flutter4Fun\/challenge-8\/blob\/master\/lib\/encrypted_file_image.dart\" target=\"_blank\">EncryptedFileImage<\/a><\/code>. It extends ImageProvider. Check the below code:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class EncryptedFileImage extends ImageProvider&lt;EncryptedFileImage> {\n  Future&lt;ui.Codec> _loadAsync(\n      EncryptedFileImage key, DecoderCallback decode) async {\n    \/\/ ...\n\n    final encryptedBytes = await file.readAsBytes();\n    final bytes = EncryptionHelper().decrypt(encryptedBytes, myKey);\n\n    \/\/ Instead of:\n    \/\/ final bytes = await file.readAsBytes();\n\n    \/\/ ...\n  }\n}<\/pre>\n\n\n\n<p>As you see, I commented <code>final bytes = await file.readAsBytes();<\/code> line to rewrite it with our customized logic. Now it reads an <code>encryptedBytes<\/code> from our file and decrypts it asynchronously, then it fills the bytes parameter to let the class work with the default behavior.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Use <code>EncryptedFileImage<\/code> in the app<\/h3>\n\n\n\n<p>Now we can use our customized <meta charset=\"utf-8\"><code><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/Flutter4Fun\/challenge-8\/blob\/master\/lib\/encrypted_file_image.dart\" target=\"_blank\">EncryptedFileImage<\/a><\/code> (which extends <meta charset=\"utf-8\"><a rel=\"noreferrer noopener\" href=\"https:\/\/api.flutter.dev\/flutter\/painting\/ImageProvider-class.html\" data-type=\"URL\" data-id=\"https:\/\/api.flutter.dev\/flutter\/painting\/ImageProvider-class.html\" target=\"_blank\">ImageProvider<\/a>) in the app just like the other built-in image providers such as <a rel=\"noreferrer noopener\" href=\"https:\/\/api.flutter.dev\/flutter\/painting\/AssetImage-class.html\" target=\"_blank\">AssetImages<\/a> and <a rel=\"noreferrer noopener\" href=\"https:\/\/api.flutter.dev\/flutter\/painting\/FileImage-class.html\" target=\"_blank\">FileImage<\/a>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@override\nWidget build(BuildContext context) {\n  return Scaffold(\n    body: Center(\n      child: Image(\n        image: EncryptedFileImage(encryptedImageFile),\n      ),\n    ),\n  );\n}<\/pre>\n\n\n\n<p>Or<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@override\nWidget build(BuildContext context) {\n  return Scaffold(\n    body: Container(\n      decoration: BoxDecoration(\n        shape: BoxShape.circle,\n        image: DecorationImage(\n          image: EncryptedFileImage(encryptedImageFile),\n        ),\n      ),\n    ),\n  );\n}<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>I tried to show how it works in a real app. You can check the source code <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/Flutter4Fun\/challenge-8\" data-type=\"URL\" data-id=\"https:\/\/github.com\/Flutter4Fun\/challenge-8\" target=\"_blank\">here<\/a>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Don&#8217;t forget to subscribe and write your comment about this article.<\/p>\n\n\n\n<p>Stay safe!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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, [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":1978,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"wp_social_preview_title":"","wp_social_preview_description":"","wp_social_preview_image":0,"footnotes":""},"categories":[34],"tags":[],"class_list":["post-1956","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-challenge"],"_links":{"self":[{"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/posts\/1956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/comments?post=1956"}],"version-history":[{"count":35,"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/posts\/1956\/revisions"}],"predecessor-version":[{"id":2021,"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/posts\/1956\/revisions\/2021"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/media\/1978"}],"wp:attachment":[{"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/media?parent=1956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/categories?post=1956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/flutter4fun.com\/wp-json\/wp\/v2\/tags?post=1956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}