Request signature in ASP.NET

This article presents a sample implementation of a request signature in ASP.NET.

# Dependencies

This example uses System dependencies from ASP.NET.

# Example

The following simple example implements the algorithm described in the Request signature guide. The most important thing is to use the HMACSHA256 from System.Security.Cryptography and pass the parameters in the correct order: method, url, timestamp, body.

The method parameter should be uppercase and path should contain only the relative path and query parameters from the URL, not the full URL address. The full URL address should be converted to e.g. /webhook?a=1.

If the algorithm works correctly, it should generate the same signature as the one given below: 56ac656c7f932c5b775be28949e90af9a2356eae2826539f10ab6526a0eec762 for the following parameters:

  • apiSecret=SECRET

  • method=POST

  • uri=http://demo.example.com/webhook?a=1

  • timestamp=1563276169752

  • body={a:1}

using System;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Security.Cryptography;

public class Program
{
    public static void Main()
    {
        string signature = GenerateSignature(
            "SECRET",
            "POST",
            "http://demo.example.com/webhook?a=1",
            1563276169752,
            new { a = 1 }
        );

        Console.WriteLine(
            signature == "56ac656c7f932c5b775be28949e90af9a2356eae2826539f10ab6526a0eec762"
        );
    }

    public static string GenerateSignature(
        string apiSecret,
        string method,
        string uri,
        long timestampMilliseconds,
        object body = null
    )
    {
        string upperMethod = method.ToUpper();
        Uri url = new Uri(uri);
        string path = url.AbsolutePath + url.Query;
        string message = upperMethod + path + timestampMilliseconds;

        if (body != null && (upperMethod == "POST" || upperMethod == "PUT"))
        {
            string bodyString = JsonSerializer.Serialize(body);
            message += bodyString;
        }

        return HmacSha256Digest(message, apiSecret);
    }

    public static string HmacSha256Digest(string message, string secret)
    {
        UTF8Encoding utf8Encoder = new UTF8Encoding();
        byte[] encodedSecret = utf8Encoder.GetBytes(secret);
        byte[] encodedMessage = utf8Encoder.GetBytes(message);

        HMACSHA256 hmac256 = new HMACSHA256(encodedSecret);
        byte[] messageHash = hmac256.ComputeHash(encodedMessage);

        return BitConverter.ToString(messageHash).Replace("-", "").ToLower();
    }
}