1

I want to regenerate a token to verify the request using hmacHash The resource documentation is in javascript and I have to implement it in C#. here what I found in their documentation on generating the token.

routes.post("/webhook", (request) => {
  const body          = request.rawBody;
  const signatureTime = "2022-05-17T09:47:51.935Z";
  const signingKey = "localyStoredKey";

  const hmac = createHmac("sha256", signingKey);
  hmac.update(`${signatureTime}${body}`);

  const token = hmac.digest("hex");
}

here is what I have done in C#

public async Task<string> GetWebhookAuthenticationTokenAsync(Stream requestBody) // requestBody is from HttpContext.Request.Body
{
    var signingKey = "localyStoredKey"; // should be from db
    var signatureTime = "2022-05-17T09:47:51.935Z"; // a timestamp

    var reader = new StreamReader(requestBody, Encoding.UTF8);
    var body = await reader.ReadToEndAsync();
    var byteArray1 = Encoding.UTF8.GetBytes($"{signatureTime}");
    var byteArray2 = Encoding.UTF8.GetBytes(body);

    var concatenatedByteArray = byteArray1.Concat(byteArray2).ToArray();
    var stringInMemoryStream = new MemoryStream(concatenatedByteArray);
    
    using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(signingKey));
    var hashBytes = hmac.ComputeHash(stringInMemoryStream);

    var token = BitConverter.ToString(hashBytes).Replace("-", String.Empty).ToLower();
    return token;
}

This works fine when I send the request body(json) without newline characters(\n). when I send the formatted json body with the request, the token is different from javascript generated token. What am I missing? simply if json is {"pro": "duct"} the tokens are matched but when json {\n "pro": "duct"\n} its different.

PS: I found the issue is due to Carriage Return \r in json body. Any help to handle this independently from the platform?

Dimuth Ruwantha
  • 671
  • 2
  • 12
  • 26
  • 1
    Do you really need to convert a request body to a string before hash computation? Can you pass a raw bytes into the `ComputeHash`? I suspect the problem is due to sting manipulation like difference in newline sequence (`\r\n` or `\n` on different platforms) or something similar. – Serg May 18 '22 at 06:07
  • @serg not really, so I removed the code of converting to body and used `MemomoryStream` `await requestBody.CopyToAsync(ms);` and converted it to array. no luck – Dimuth Ruwantha May 18 '22 at 06:27
  • Yes, @serg I tried removing '\r' from the body and now it's matched. might need to handle Carriage Return properly – Dimuth Ruwantha May 18 '22 at 06:57
  • maybe try to minify the JSON object beforehand. – noone May 19 '22 at 16:28

0 Answers0