I am trying to validate an API request from Slack as per the instructions here.
In summary the steps are:
I have applied the suggestion in this post which is:
string hexaHash = "";
foreach (byte b in my_signature)
{
hexaHash += String.Format("{0:x2}", b);
}
I'm expecting a value like this:
'a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503'
When I don't apply the code above I'm getting a value like this:
'KvFZL2TojhYJj6ahS0Z7etDwSn4='
Which changes to this when applying that code:
'76303d6f4f31494741457277466e4b32344c6f655172713281ef935fe1fa3d'
My full Azure API Management policy code is as below:
<inbound>
<!-- Setting variables from the headers passed by Slack -->
<set-variable name="timestamp" value="@(context.Request.Headers.GetValueOrDefault("X-Slack-Request-Timestamp"))" />
<set-variable name="slack_signature" value="@(context.Request.Headers.GetValueOrDefault("X-Slack-Signature"))" />
<!-- Set body received from slack as variable -->
<set-variable name="slack_body" value="@(context.Request.Body.As
<String>(preserveContent: true))" />
<set-variable name="slack_signing_secret" value="{{Slack-Signing-Secret}}" />
<!-- Create concatenation string as per slack documentation -->
<set-variable name="sig_basestring" value="@{
string body = (string)context.Variables.GetValueOrDefault("slack_body");
string timestamp = (string)context.Variables.GetValueOrDefault("timestamp");
string sig_basestring = "v0:" + timestamp + ":" + body;
return sig_basestring;
}" />
<!-- Apply HMACSHA256 to concatenated string using slack signing secret as key -->
<set-variable name="my_signature" value="@{
<!-- Hash-based Message Authentication Code (HMAC) using SHA256 hash -->
System.Security.Cryptography.HMACSHA256 hasher = new System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes("{{Slack-Signing-Secret}}"));
return Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes((string)context.Variables["sig_basestring"])));
}" />
<!-- I'm using this method to send the data back to slack to validate both signatures -->
<return-response response-variable-name="existing response variable">
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@{
string my_signature = (string)context.Variables["my_signature"];
string slack_signature = (string)context.Variables["slack_signature"];
string hexaHash = "";
<!-- This code is applying the "hex digest" method I found -->
foreach (byte b in my_signature)
{
hexaHash += String.Format("{0:x2}", b);
}
my_signature = "v0=" + hexaHash;
return my_signature + " " + slack_signature;
}</set-body>
</return-response>
</inbound>
Is there anything that I could apply to the current hashed value to get a similar result to the hexdigest()
method suggested in the Slack documentation?
Using the Slack example values I managed to accomplish the correct digest.
I'm sure there is somewhat more elegant way to achieve the removal of the '-' chars that BitConverter.ToString()
produces.
<inbound>
<!-- Setting variables from the headers passed by Slack -->
<set-variable name="timestamp" value="@(context.Request.Headers.GetValueOrDefault("X-Slack-Request-Timestamp"))" />
<set-variable name="slack_signature" value="@(context.Request.Headers.GetValueOrDefault("X-Slack-Signature"))" />
<!-- Set body received from slack as variable -->
<set-variable name="slack_body" value="@(context.Request.Body.As
<String>(preserveContent: true))" />
<!-- Create concatenation string as per slack documentation -->
<set-variable name="sig_basestring" value="@{
string body = (string)context.Variables.GetValueOrDefault("slack_body");
string timestamp = (string)context.Variables.GetValueOrDefault("timestamp");
string sig_basestring = "v0:" + timestamp + ":" + body;
return sig_basestring;
}" />
<!-- Apply HMACSHA256 to concatenated string using slack signing secret as key -->
<set-variable name="my_signature" value="@{
System.Security.Cryptography.HMACSHA256 hasher = new System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes("8f742231b10e8888abcd99yyyzzz85a5"));
return System.BitConverter.ToString(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes((string)context.Variables["sig_basestring"]))).ToLower().Replace("-", "");
}" />
</inbound>