HMAC Signature

Jason He Updated by Jason He

DeskDirector offers various methods for sending webhooks. To ensure the security of the receiving endpoint, our system includes a signature as a custom header. This signature acts as a fingerprint for the current delivered webhook payload. The receiving endpoint utilizes a secret to verify incoming HTTP requests.

Verification Process

The verification process involves several steps:

  1. Read Request Body: The incoming HTTP request body is read as a raw payload.
  2. Extract Custom Header: The custom header containing the signature is extracted from the HTTP request. Custom header name is x-dd-signature.
  3. Hash Calculation: The request body is hashed using the HMAC hash algorithm.
  4. Comparison: The hashed request body is compared with the extracted signature in the header. They must match for verification to succeed.

C# Code Example:

using System;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Http;

public class VerifierSample
{
public async Task HandleWebhookAsync(HttpRequest request)
{
StringValues value = request.Headers["x-dd-signature"];
if (value.Count != 1)
{
throw new Exception("Signature not exist");
}

string signatureHeader = value.ToString();
string requestBody = await ReadPayloadAsync(request);
if (String.IsNullOrEmpty(requestBody))
{
throw new Exception("Request does not have payload.");
}

const string secret = "kfA18wgZKW30F7dL1JtlHq2judcJ0uoB";

if (!VerifyWebhook(secret, requestBody, signatureHeader))
{
throw new Exception("Invalid signature");
}

// Handle webhook payload.
}

private bool VerifyWebhook(string secret, string requestBody, string signatureHeader)
{
if (!signatureHeader.StartsWith("sha256=", StringComparison.OrdinalIgnoreCase))
{
// handle unknown algorithm
return false;
}

string expectValue = CalculateSha256Signature(secret, requestBody);
return String.Equals(expectValue, signatureHeader, StringComparison.Ordinal);
}

private async Task<string> ReadPayloadAsync(HttpRequest request)
{
request.Body.Position = 0;

using StreamReader reader = new(request.Body);

return await reader.ReadToEndAsync();
}

private string CalculateSha256Signature(string secret, string body)
{
byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
using HMACSHA256 hasher = new(secretBytes);

byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
byte[] sha256Bytes = hasher.ComputeHash(bodyBytes);

return $"sha256={Convert.ToBase64String(sha256Bytes)}";
}
}

Explanation:

  • secret: The secret key shared between the sender and receiver.
  • requestBody: The raw payload of the incoming HTTP request.
  • signatureHeader: The custom header containing the signature.

The VerifyWebhook method takes these inputs, calculates the HMAC-SHA256 hash of the request body using the shared secret, and compares the computed signature with the signature provided in the header. If they match, the method returns true, indicating successful verification.

Conclusion:

Implementing signature verification ensures the integrity and authenticity of incoming webhooks in the DeskDirector system. By employing this security measure, organizations can trust the data received through webhooks and mitigate potential risks associated with unauthorized access or tampering.

How did we do?

Contact