Search code examples
blazor-client-sideblazor-webassembly

How to protect/encrypt data stored in session/local storage in Blazor WebAssembly


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


Solution

  • 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