HMAC signatures for webhook subscriptions | XM Community
Question

HMAC signatures for webhook subscriptions

  • 22 October 2020
  • 1 reply
  • 41 views

Hi,

Can someone explain to me the exact method that is used to generate the HMAC signatures for the webhook events. Without this information I am unable to verify the signature of messages sent by qualtrics. The API documentation seems incomplete in this area.
The first question is how does the shared key which is specified as a string correspond to a 16 byte or 32 byte key for signing and encryption?
Then when we get the HMAC signature in webhook messages, this is a 128 character hex number. What algorithm is used to generate this signature?
Finally, how is the webhook payload converted to a byte array for signing by the shared key?

For example, this is one of my attempts to verify these signatures:
//specify the shared key in some format
    var key = "0000000000000000000000000000000000000000000000000000000000000000";
      var createSubscriptionPayload = new CreateSubscriptionPayload()
      {
        topics = $"surveyengine.completedResponse.{Configuration["surveyId"]}",
        encrypt = false,
        publicationUrl = Configuration["webHookUrl"],
        sharedKey = key,
      };
//create a subscription using this key
      var result = await createSubscription(createSubscriptionPayload);

An example payload we receive for the above subscription is:
Topic=peopleplus.surveyengine.completedResponse.SV_cVn9uBwheR9hz01&HMAC=c8621d76544a65d3ee49171a9d86377f1eed3af389d191fc0d8b1ccdf4acaf2420c84f07c944bd9de423c25c1ad514bc07f09fae7f937a590f8aa7c2a368d2b6&MSG=%7B%22Status%22%3A%22Complete%22%2C%22SurveyID%22%3A%22SV_cVn9uBwheR9hz01%22%2C%22RecipientID%22%3A%22CGC_GiMUyLkGpEZsVF3%22%2C%22ResponseEventContext%22%3A%22%22%2C%22DistributionID%22%3A%22EMD_96woxYS85Cg5Lqx%22%2C%22ResponseID%22%3A%22R_suq806jn8LGzhx7%22%2C%22CompletedDate%22%3A%222020-10-22+12%3A31%3A40%22%2C%22CreatorID%22%3A%22UR_2686s36oneK8iW1%22%2C%22DistributionChannel%22%3A%22gl%22%2C%22Duration%22%3A%222%22%2C%22Language%22%3A%22EN%22%2C%22SurveyVersionID%22%3A%229223370436078023907%22%2C%22IsPreview%22%3A%22false%22%2C%22IsTest%22%3A%22false%22%2C%22HasTextEntryAnswer%22%3A%22false%22%2C%22LinkType%22%3A%22Individual%22%2C%22BrandID%22%3A%22peopleplus%22%7D

And I try and verify the signature by signing the MSG payload and using a 32 byte array of 0s as the key for a HMACSHA512 alforithm:
      string payload = [as above, either raw or as JSON]
      var key = Enumerable.Repeat((byte)0, 32).ToArray();
      using (HMACSHA512 hmac = new HMACSHA512(key))
      {
        using (MemoryStream inStream = new MemoryStream(Encoding.UTF8.GetBytes(payload)))
        {
          byte[] computedHash = hmac.ComputeHash(inStream);

        }
     }

However I cannot get the computerHash in the code above to correspond to the HMAC value in the webhook payload.

Thanks in advance for any help.


1 reply

We have determined that it is the SHA512 alogorithm used for these signatures and have been able to verify signatures using this.
Seems the issue with the above code is in the generation of a byte array from the string key.
Regards,

Leave a Reply