Skip to content

Instantly share code, notes, and snippets.

@xiaomi7732
Last active January 29, 2023 00:39
Show Gist options
  • Save xiaomi7732/b1a20083fc1f7eb980e1eddeca492785 to your computer and use it in GitHub Desktop.
Save xiaomi7732/b1a20083fc1f7eb980e1eddeca492785 to your computer and use it in GitHub Desktop.
Verify SHA256 signature by GitHub WebHooks in ASP.NET Core WebAPI

Verify SHA256 signature by GitHub WebHooks in ASP.NET Core WebAPI

Description

Sharing a secrect with GitHub, it is important to verify the signaure hashed by it. You don't want your API being called by malicious 3rd parties.

Here's how you do it in ASP.NET Core WebAPI.

Code

using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Primitives;

const string secret = "this is the secret shared with github webhooks for signing"; // Only your service and github knows about it.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// Assuming GitHub will POST on /payloads.
app.MapPost("/payloads", async (HttpContext httpContext, CancellationToken cancellationToken) =>
{
    string? payload = null;
    using (var reader = new StreamReader(httpContext.Request.Body, leaveOpen: true))
    {
        payload = await reader.ReadToEndAsync();
    }

    Console.WriteLine("I got some json: " + payload);
    
    httpContext.Request.Headers.TryGetValue("x-hub-signature-256", out StringValues signatureSHA256);
    Console.WriteLine("And the signature: " + signatureSHA256);
    // Verify header here if you want.

    // Re-compute the hash value using the secret as the key.
    byte[] key = Encoding.UTF8.GetBytes(secret);
    using (HMACSHA256 hmac = new HMACSHA256(key))
    {
        {
            // Use secret to re-compute the hash of the payload.
            byte[] computedSig = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
            // Notice the hash needs to be in HEX before comparison
            Console.WriteLine("Computed signature: {0}", ToHexString(computedSig));
        }
    }
});

static string ToHexString(byte[] bytes)
{
    var builder = new StringBuilder(bytes.Length * 2);
    foreach (byte b in bytes)
    {
        builder.AppendFormat("{0:x2}", b);
    }

    return builder.ToString();
}

app.Run();

Result:

I got some json: {"zen":"Avoid administrative distraction.","hook_id":395209045,"hook":{json_content}
And the signature: sha256=71d8e307d216a45425b57220f4ed89c1111b1f410213fec83659e8d4c1253813              # comes from the header
Computed signature: 71d8e307d216a45425b57220f4ed89c1111b1f410213fec83659e8d4c1253813                    # computed with the secret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment