0

I want to have a custom middleware in my asp.net core application where I decrypt the request that is coming and after processing or doing some work encrypt the response.

For example: if a client sends a msg "Hello server" and it is encrypted from the client side itself and when receiving on the server, the custom middleware decrypts it and further pass on to the controller for processing the data. The server replies with "hello client" and the custom middleware encrypts the data.

What I know is how the middleware works but I couldn't find any reference how to use it on my application. I have RSA encryption working with public and private key but I don't know how to implement this in the middleware. In the middleware there is httpcontext passed in Invoke function while implementing IMiddleware interface.

All I'm finding is on the internet is Response.WriteAsync() examples. This much I have understood that there is something to do with the HttpContext class.

For simplicity take Encrypt() and Decrypt() which can take needed argument(s) to use in the middleware. General middleware invoke function is as below. Any help would be appreciated.

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
   //do decryption
   await next(context);
   //do encryption
}
6
  • Why not allow the web server to do this with TLS? Commented Aug 3, 2021 at 21:55
  • No the requirement is to have own custom encryption/ decryption. And I also dont know what and how to implement TLS. See Im new to this middleware concept and implementation. Commented Aug 4, 2021 at 6:12
  • How about using actionfilter? Commented Aug 4, 2021 at 8:22
  • @TinyWang appreciated your input. i have a question though, if there is some model in the request, will it work? Suppose im sending User object from client which is a json object which is encrypted and on my server im decrypting that to get back the user object. And after processing sending the response in encrypted. The same middleware will be in the client side also. I have found link and Im thinking to encrypt and decrypt the request/response body. If you can help me with this. Commented Aug 4, 2021 at 15:12
  • Thanks for your reply but I'm not sure if I misunderstood in some place. I've updated my post, see details below. Commented Aug 5, 2021 at 7:48

1 Answer 1

0

I write a demo to achieve the "filter"

using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace CustomActionFilter.Filter
{
    public class MySampleActionFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            var secret = context.HttpContext.Request.Form["secret"].ToString();
            
            string privateKey = "MIICxxxxxxxxxxxxxxxxZg==";
            var privateKeyBits = Convert.FromBase64String(privateKey);
            RSA rsa = RSA.Create();
            var rsaParameters = new RSAParameters();
            BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits));
            byte bt = 0;
            ushort twobytes = 0;
            twobytes = binr.ReadUInt16();
            if (twobytes == 0x8130)
                binr.ReadByte();
            else if (twobytes == 0x8230)
                binr.ReadInt16();
            else
                throw new Exception("Unexpected value read binr.ReadUInt16()");

            twobytes = binr.ReadUInt16();
            if (twobytes != 0x0102)
                throw new Exception("Unexpected version");

            bt = binr.ReadByte();
            if (bt != 0x00)
                throw new Exception("Unexpected value read binr.ReadByte()");
            rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr));
            rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr));
            rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr));
            rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr));
            rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr));
            rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr));
            rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr));
            rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr));

            rsa.ImportParameters(rsaParameters);
            var temp = Encoding.UTF8.GetString(rsa.Decrypt(Convert.FromBase64String(secret), RSAEncryptionPadding.Pkcs1));
            //JObject json = JObject.Parse(temp);
            context.ActionArguments["secret"] = temp;
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            var res = context.Result;
            //encrypt code 
        }


        private int GetIntegerSize(BinaryReader binr)
        {
            byte bt = 0;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02)
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
                count = binr.ReadByte();
            else
            if (bt == 0x82)
            {
                var highbyte = binr.ReadByte();
                var lowbyte = binr.ReadByte();
                byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                count = BitConverter.ToInt32(modint, 0);
            }
            else
            {
                count = bt;
            }

            while (binr.ReadByte() == 0x00)
            {
                count -= 1;
            }
            binr.BaseStream.Seek(-1, SeekOrigin.Current);
            return count;
        }

    }
}

and set DI in startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            //services.AddScoped<MySampleActionFilter>();
            services.AddControllersWithViews();
            services.AddControllers(config =>
            {
                config.Filters.Add<MySampleActionFilter>();
            });
        }

my view :

@{
    ViewData["Title"] = "Home Page";
}

<button id="test">send</button>
<script src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.2.1/jsencrypt.min.js"></script>
<script>

    var user = {
        "age": 18,
        "name": "tiny"
    };

    var public_key = "MIGfMA0GCxxxxxxxxxDAQAB";
    var private_key = "MIICWwIxxxxxxxxxlRbEbsDVZg==";

    var encrypt = new JSEncrypt();
    encrypt.setPublicKey(public_key);
    var encrypted = encrypt.encrypt(JSON.stringify(user));
    console.log(encrypted);

    var decrypt = new JSEncrypt();
    decrypt.setPrivateKey(private_key);
    var uncrypted = decrypt.decrypt(encrypted);
    console.log(uncrypted);

    $('#test').click(function () {
        var user = {
            "age": 18,
            "name": "tiny"
        };
        $.ajax({
            url: "https://localhost:44369/hello",
            type: "post",
            data: {
                secret: encrypted
            },
            success: function (data) {
                alert(data);
            }
        })
    });
</script>

My controller action:

[HttpPost]
[ServiceFilter(typeof(MySampleActionFilter))]
public JsonResult Index(string secret)
{
    User json12 = JsonConvert.DeserializeObject<User>(secret);
    User res = new User
    {
        age = 0,
        name = "zero"
    };
    return Json(res);
}

Test result:

enter image description here enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.