Encrypt - Encrypt Payload/Parameter Using Angular 11 And ASP.NET Core | Rajesh Gami

 

Introduction

Nowadays clients want to secure the website, they want no one can see the whole payload or id parameter value that we pass during the API call so using this you can get the exact solution.

In this article, I have explained everything that is more useful for security.

So, here I am going to explain Encrypt and Decrypt whole payload or any id using Angular 11(front end) and ASP.NET CORE (API).

I have used AES256 algorithm in both Angular and ASP.NET CORE. In angular side using interceptor passing the payload or id with encryption and using same algorithm getting payload or ids in ASP.NET CORE using middleware that I will explain step by step.

Make sure that if we use any algorithm for encryption from angular or any front-end framework we must have to use same algorithm for decryption.

So let me explain step by step, let’s start with Angular code.

First, you have to create project. If not create and do all processes like CRUD or any functionality that use GET and POST else you can add to your current project also.

Angular Code

Step 1

Install the crypto js using npm terminal. Use below command to install the crypto js

npm i crypto-js
ASP.NET (C#)

I have used 4.1.1 version, you can use according to your angular version.

Once install Crypto Js next we have to create one service to encrypt the payload or parameter.

Step 2

Create the service for Encrypt-Decrypt payload with AES256 algorithm.

For Encrypt KEY and Encrypt IV we have to get a unique 16 number code that we will use in encrypt and also use same key and IV in asp.net code side for decrypt.

So here I am using same id for both, you can set different but make sure to use the same key and IV to decrypt the code.

environment.EncryptKey = 1203199320052021

environment.EncryptIV = 1203199320052021

Here I have created service and given name encrypt-decrypt.service.ts.

import { Injectable } from '@angular/core';
import * as CryptoJS from 'crypto-js';
import { environment } from 'src/environments/environment';

@Injectable({
    providedIn: 'root'
})
export class EncryptDecryptService {
    private key = CryptoJS.enc.Utf8.parse(environment.EncryptKey);
    private iv = CryptoJS.enc.Utf8.parse(environment.EncryptIV);
    constructor() {}
    // Methods for the encrypt and decrypt Using AES
    encryptUsingAES256(text): any {
        var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(text), this.key, {
            keySize: 128 / 8,
            iv: this.iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return encrypted.toString();
    }
    decryptUsingAES256(decString) {
        var decrypted = CryptoJS.AES.decrypt(decString, this.key, {
            keySize: 128 / 8,
            iv: this.iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return decrypted.toString(CryptoJS.enc.Utf8);
    }
}
JavaScript

So above code is for encrypting and decrypting the payload and parameter so these functions we will use from interceptor method.

HTTP Interceptors is a special type of angular service that we can implement. It's used to apply custom logic to the central point between the client-side and server-side outgoing/incoming HTTP request and response. Keep in mind that the interceptor wants only HTTP requests.

Let’s create interceptor.

Step 3

Create the interceptor file to generate encrypted payload before passing it into API service call.

I created interceptor with encrypt-decrypt-interceptor.ts name.

See the below code of interceptor method.

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { EncryptDecryptService } from './services/encrypt-decrypt.service';
import { Observable } from 'rxjs/Observable';
import { environment } from 'src/environments/environment';

@Injectable()
export class EncryptDecryptAuthInterceptor implements HttpInterceptor {
    constructor(private encryptDecryptService: EncryptDecryptService, ) {}
    // If you want to some exclude api call from Encryption then add here like that.
    // environment.basUrl is your API URL
    ExcludeURLList = [
        environment.baseUrl + "/api/Common/commonFileuploaddata",
        environment.baseUrl + "/api/Users/UploadProfilePicture",
        environment.baseUrl + "/api/Common/downloadattachedfile"
    ];
    intercept(req: HttpRequest < any > , next: HttpHandler): Observable < HttpEvent < any >> {
        let exludeFound = this.ExcludeURLList.filter(element => {
            return req.url.includes(element)
        });
        // We have Encrypt the GET and POST call before pass payload to API
        if (!(exludeFound && exludeFound.length > 0)) {
            if (req.method == "GET") {
                if (req.url.indexOf("?") > 0) {
                    let encriptURL = req.url.substr(0, req.url.indexOf("?") + 1) + this.encryptDecryptService.encryptUsingAES256(req.url.substr(req.url.indexOf("?") + 1, req.url.length));
                    const cloneReq = req.clone({
                        url: encriptURL
                    });
                    return next.handle(cloneReq);
                }
                return next.handle(req);
            } else if (req.method == "POST") {
                if (req.body || req.body.length > 0) {
                    const cloneReq = req.clone({
                        body: this.encryptDecryptService.encryptUsingAES256(req.body)
                    });
                    return next.handle(cloneReq);
                }
                let data = req.body as FormData;
                return next.handle(req);
            }
        }
        return next.handle(req);
    }
}
JavaScript

I want to mention specially that if you want to exclude API call from encryption then you have to just add API URL into ExcludeURLList as shown in Interceptor. In our project has many methods or API call that are not necessary to encrypt then we can manage in our way. Suppose here I mention some API call into exclude list that upload image related so for upload image encryption not needed so I added under exclude list.

Now need to configure into module file so whenever we call the API then call interceptor before API and encrypt the payload and then pass into API (GET or POST).

Step 4: Configure interceptor in app.module.ts file

First import the inceptor that we created (encrypt-decrypt-interceptor.ts) and configure Interceptor into provider

See the below sample app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { EncryptDecryptAuthInterceptor } from './encrypt-decrypt-interceptor';
@NgModule({
    imports: [],
    declarations: [
        AppComponent,
    ],
    providers: [{
            provide: 'BASE_URL',
            useFactory: getBaseUrl
        }, {
            provide: ErrorHandler,
            useClass: AppErrorHandler
        }, {
            provide: HTTP_INTERCEPTORS,
            useClass: EncryptDecryptAuthInterceptor,
            multi: true
        },
        CommonService,
    ],
    bootstrap: [AppComponent],
    entryComponents: [],
    exports: [],
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}
export function getBaseUrl() {
    return document.getElementsByTagName('base')[0].href;
}
JavaScript

Add Interceptor into providers as shown in above code,

Now front-end Angular side code is done. Using above all steps to encrypt the payload and parameter so no one can see original payload or parameter.

See above image to understand encryption, It’s fully encrypted payload/parameter so no one can see original payload/parameter value.

ASP.NET Core Code

In Asp.Net core we must have to use same algorithm to decrypt the payload before passing to Action method,

So for that I have created one middleware helper to decrypt the payload before calling the Controller Action method. Main benefit is we have not done much code for everything just use middleware and call middleware from Startup.cs file so call middleware on every request of ASP.NET CORE.

We can set exclude list same as in Angular in ASP.Net Core..

Middleware is software components that are assembled into an application pipeline to handle requests and responses. Each component chooses whether to pass the request on to the next component in the pipeline, and can perform certain actions before and after the next component is invoked in the pipeline.

First need to create middleware helper for encrypt-decrypt the payload and parameter which is passing from angular.

Create middleware helper name EncryptionMiddleware.cs and copy and paste below code.

using FC_API.Data.Access;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Rajesh_API.Helpers {
    public class EncryptionMiddleware {
        private readonly RequestDelegate _next;
        private readonly AppSettings _appSettings;
        public EncryptionMiddleware(RequestDelegate next, IOptions < AppSettings > appSettings) {
            _next = next;
            _appSettings = appSettings.Value;
        }
        // Whenever we call any action method then call this before call the action method
        public async Task Invoke(HttpContext httpContext) {
            List < string > excludeURL = GetExcludeURLList();
            if (!excludeURL.Contains(httpContext.Request.Path.Value)) {
                httpContext.Request.Body = DecryptStream(httpContext.Request.Body);
                if (httpContext.Request.QueryString.HasValue) {
                    string decryptedString = DecryptString(httpContext.Request.QueryString.Value.Substring(1));
                    httpContext.Request.QueryString = new QueryString($ "?{decryptedString}");
                }
            }
            await _next(httpContext);
        }
        // This function is not needed but if we want anything to encrypt then we can use
        private CryptoStream EncryptStream(Stream responseStream) {
            Aes aes = GetEncryptionAlgorithm();
            ToBase64Transform base64Transform = new ToBase64Transform();
            CryptoStream base64EncodedStream = new CryptoStream(responseStream, base64Transform, CryptoStreamMode.Write);
            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
            CryptoStream cryptoStream = new CryptoStream(base64EncodedStream, encryptor, CryptoStreamMode.Write);
            return cryptoStream;
        }
        static byte[] Encrypt(string plainText) {
            byte[] encrypted;
            using(AesManaged aes = new AesManaged()) {
                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
                using(MemoryStream ms = new MemoryStream()) {
                    using(CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) {
                        using(StreamWriter sw = new StreamWriter(cs))
                        sw.Write(plainText);
                        encrypted = ms.ToArray();
                    }
                }
            }
            return encrypted;
        }
        // This are main functions that we decrypt the payload and  parameter which we pass from the angular service.
        private Stream DecryptStream(Stream cipherStream) {
            Aes aes = GetEncryptionAlgorithm();
            FromBase64Transform base64Transform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
            CryptoStream base64DecodedStream = new CryptoStream(cipherStream, base64Transform, CryptoStreamMode.Read);
            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
            CryptoStream decryptedStream = new CryptoStream(base64DecodedStream, decryptor, CryptoStreamMode.Read);
            return decryptedStream;
        }
        private string DecryptString(string cipherText) {
            Aes aes = GetEncryptionAlgorithm();
            byte[] buffer = Convert.FromBase64String(cipherText);
            MemoryStream memoryStream = new MemoryStream(buffer);
            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
            CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
            StreamReader streamReader = new StreamReader(cryptoStream);
            return streamReader.ReadToEnd();
        }
        // We have to use same KEY and IV as we use for encryption in angular side.
        // _appSettings.EncryptKey= 1203199320052021
        // _appSettings.EncryptIV = 1203199320052021
        private Aes GetEncryptionAlgorithm() {
            Aes aes = Aes.Create();
            var secret_key = Encoding.UTF8.GetBytes(_appSettings.EncryptKey);
            var initialization_vector = Encoding.UTF8.GetBytes(_appSettings.EncryptIV);
            aes.Key = secret_key;
            aes.IV = initialization_vector;
            return aes;
        }
        // This are excluded URL from encrypt- decrypt that already we added in angular side and as well as in ASP.NET CORE side.
        private List < string > GetExcludeURLList() {
            List < string > excludeURL = new List < string > ();
            excludeURL.Add("/api/Common/commonFileuploaddata");
            excludeURL.Add("/api/Users/UploadProfilePicture");
            excludeURL.Add("/api/Common/downloadattachedfile");
            return excludeURL;
        }
    }
}
JavaScript

Now need this middleware call from Startup.cs file, See below screenshot

 

So, here all the code is complete. Now you can run the project and see the result. But make sure that use the same 16-digit code for both encryption and decryption. If you want to add long digit unique code then you can but make sure its basis of the AES256 algorithm rule means 128 bit(16 digits), 192 bit (24 digits), or 256 bit(32 digits) encryption, Here I have used 128-bit encryption.

If you have any doubt or anything else please let me know in a comment.

RAJESH GAMI - Blog

Digital Signature Pad in Angular | RAJESH GAMI

  What is Signature Pad? Signature Pad could be a JavaScript library for drawing fancy signatures. It supports HTML5 canvas and uses variabl...