4

I am creating Blazor WebAssembly App and trying to figure how can i Encrypt/Protect data stored in Session Storage/ Local Storage ?

NSS
  • 1,835
  • 2
  • 29
  • 66
  • Why would you do that? The .NET assemblies are being downloaded to the client, so the code that decrypts (as well as the key) can easily be decompiled anyway... – C. Augusto Proiete Jul 08 '20 at 03:49
  • 1
    Well i get your point but isn't making it harder a better than leaving it plain text ? – NSS Jul 08 '20 at 20:09
  • Better for what? What are you trying to do/stop people from doing? People that are technical enough to read data from the local storage, most likely can also decompile a .NET assembly... – C. Augusto Proiete Jul 08 '20 at 22:49
  • 2
    it like saying because thieves can break the locks, it is better to leave doors open no need to put locks. – NSS Jul 11 '20 at 20:38
  • 1
    No, it's like saying "_[Security by obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity) is not a good strategy_" and it's not worth your time and effort (IMO). If the information must be secured, it should be stored on the server-side instead – C. Augusto Proiete Jul 12 '20 at 00:33
  • 5
    Come on folks! He can make use of some obfuscate tools in order to protect the code from being decompiled. So, I think it worth while having some way do encrypt the data, right ? Well friend, take a look at this post: https://www.npmjs.com/package/secure-web-storage And here: https://stackoverflow.com/questions/17280390/can-local-storage-ever-be-considered-secure You can find some solutions. Hope it helps. Let me know if is enough. – Fábio Marcos Euzébio Sep 02 '20 at 20:53
  • @HenkHolterman In my reading about MS's protectedlocalstorage, you must do that on the server side. It seeems to rely on building your app using the blazor server app template. – silverfox1948 Nov 01 '20 at 17:21
  • Yes, it is server-side. I didn't realize that then. – H H Nov 04 '20 at 07:37

1 Answers1

2

First things that you need to know is that blazor wasm model till .net 5 does not support crypto library. (as my knowledge)

in .net 6 you can use Blazor.SubtleCrypto

but you can inject AES method into it with javascript interop, follow these steps:

  1. download AES.js
  2. add aes.js to wwwroot folder
  3. add two following method in script tag in index.html root for encrypt/decrypt string
    function encryptedText(inputSrt, keyArray) {
    var textBytes = aesjs.utils.utf8.toBytes(inputSrt);
    var aesCtr = new aesjs.ModeOfOperation.ctr(keyArray, new aesjs.Counter(5));
    var encryptedBytes = aesCtr.encrypt(textBytes);
    return aesjs.utils.hex.fromBytes(encryptedBytes);
}

    function decryptText(inputStr, keyArray) {
        var encryptedBytes = aesjs.utils.hex.toBytes(inputStr);
        var aesCtr = new aesjs.ModeOfOperation.ctr(keyArray, new aesjs.Counter(5));
        var decryptedBytes = aesCtr.decrypt(encryptedBytes);
        return aesjs.utils.utf8.fromBytes(decryptedBytes);
    }

now your are ready. add DI interface to .NetCore follow these steps:

  1. create class and interface
public interface IEncryptProvider
    {
        string TextEncrypt(string input);
        string TextDecrypt(string input);

        string Encrypt<T>(T input);
        T Decrypt<T>(string input);
    }
public class AesJsProvider : IEncryptProvider
    {
        IJSRuntime GetJSRuntime;
        public static int[] HiddenKey = new int[] { 0, 45, 6, 3, 8, 5, 8, 7, 89, 7, 10, 21, 12, 34, 12, 1 };
        public static string JsEncryptMethod { get; set; } = "encryptText";
        public static string JsDecryptMethod { get; set; } = "decryptText";

        public AesJsProvider(IJSRuntime jSRuntime)
        {
            GetJSRuntime = jSRuntime;
        }

        public async Task<string> TextDecrypt(string input)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;
            try
            {
                return await GetJSRuntime.InvokeAsync<string>(JsEncryptMethod, input, HiddenKey);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        public async Task<string> TextEncrypt(string input)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;
            try
            {
                return await GetJSRuntime.InvokeAsync<string>(JsDecryptMethod, input, HiddenKey);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        public async Task<string> Encrypt<T>(T input)
        {
            var str = JsonSerializer.Serialize(input);
            if (input == null)
                return string.Empty;
            try
            {
                return await GetJSRuntime.InvokeAsync<string>(JsEncryptMethod, input, HiddenKey);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        public async Task<T> Decrypt<T>(string input)
        {
            var str = await TextDecrypt(input);
            if (string.IsNullOrEmpty(input))
                return default(T);
            try
            {
                return await GetJSRuntime.InvokeAsync<T>(JsDecryptMethod, input, HiddenKey);
            }
            catch (Exception)
            {
                return default;

            }
        }
    }

so all of codes completed, lets config startup options

services.AddSingleton<IEncryptProvider, JSRuntimeProvider>();

you can change change HiddenKey as your need to a secret key in provider, and inject IEncryptProvider on any page to encrypt/decrypt string or objects

source code available in github: https://github.com/mahdiit/blazor-wasm-encryptstorage

Mahdi
  • 649
  • 8
  • 18