0

I'm trying to verify a webhook from bamboohr. the documentation is here https://documentation.bamboohr.com/docs/webhooks

and after unpacking the headers I see this:

  • X-BambooHR-Signature: 362cb0eff0193af8d3f939349f84014e5c70bba4cfc105682b45ecd305db01ff
  • X-BambooHR-Timestamp: 1652747163

Here is my code, from an azure function triggered by the webhook. The testOutput is not whats in the ‘X-BambooHR-Signature’ header:

            string data;
            using (var reader = new StreamReader(req.Body))
            {
                 data = await reader.ReadToEndAsync();
            }

            string privateKey = "<gotten from bamboohr webhookconfig>";
            if (req.Headers.Keys.Contains("X-BambooHR-Signature") && req.Headers.Keys.Contains("X-BambooHR-Timestamp"))
            {

                string timestamp = req.Headers["X-BambooHR-Timestamp"];
                string signature = req.Headers["X-BambooHR-Signature"];
                byte[] privateKeyBytes = Encoding.UTF8.GetBytes(privateKey);
                byte[] combinedBytes = Encoding.UTF8.GetBytes(data + timestamp);
                HMACSHA256 hmac = new HMACSHA256(privateKeyBytes);
                byte[] testOutputBytes = hmac.ComputeHash(combinedBytes);
                string testOutput = Convert.ToBase64String(testOutputBytes);
                log.LogInformation("testOutput is: " + testOutput);  //----NOT EQUAL TO signature.

            }

Any idea what I might be doing wrong? the testUutput is something like 'llBdZd2IfVdrJBlkGFFNG2dszDxpgJlJ4vQqTATJsYU=' which as you can see isnt even close.

Jeyenne
  • 121
  • 2
  • 15

1 Answers1

2

Instead of using ToBase64String, try converting it to hexadecimal format. (There are different ways to convert it.) I had similar issue verifying bambooHR signature key in python, and fixed it by converting expected signature to hexadecimal format (not bytes or bytes string).

c#

using System;
using System.Text;
using System.Security.Cryptography;


namespace Test
{
    public class VerifySignature
    {
        public static void Main(string[] args)
        {
            string data = "request data";
            string privateKey = "your private key";
            string timestamp = "1652747163";
            string signature = "362cb0eff0193af8d3f939349f84014e5c70bba4cfc105682b45ecd305db01ff";
            byte[] privateKeyBytes = Encoding.UTF8.GetBytes(privateKey);
            byte[] combinedBytes = Encoding.UTF8.GetBytes(data + timestamp);
            HMACSHA256 hmac = new HMACSHA256(privateKeyBytes);
            byte[] testOutputBytes = hmac.ComputeHash(combinedBytes);
            // edited from here
            // string testOutput = Convert.ToBase64String(testOutputBytes);
            // log.LogInformation("testOutput is: " + testOutput);
            string hexOutput = BitConverter.ToString(testOutputBytes).Replace("-",""); // convert to hexadecimal format
            Console.WriteLine(hexOutput);

        }
    }
}

python

import hmac
from hashlib import sha256

def verify_signature(request):
    received_signature = 'get sig from request headers'
    timestamp = 'get timestamp from request headers'
    private_key = 'your private key'
    body = request.body
    calculated_signature = hmac.new(
        private_key, body + timestamp, sha256
    ).hexdigest()

    return received_signature == calculated_signature
    

I hope this helps although it's a bit late!

NamsanCode
  • 226
  • 1
  • 4
  • This is my first time posting anything to stackoverflow.. i really hope this helps someone. – NamsanCode Jun 28 '22 at 04:48
  • i did try BitConverter.ToString(testOutputBytes).Replace("-", "") https://stackoverflow.com/users/13799488/seoul-kim (thanks for that suggestion) but i believe its the same as Convert.ToHexString(testOutputBytes) and neither of those gives me what i am reading in the signature. Perhaps Im not using the hmac function correctly? – Jeyenne Jul 21 '22 at 01:42