# Are there any cryptographic flaws in my webhook signing process?

Out of band my services have exchanged secret keys. These secret keys are then used to prevent two things of the webhooks (HTTP calls triggered by Service A to Service B when an event occurs in Service A).

1. Webhook Spoofing
2. Webhook Replaying

The basic problems with webhooks involve the fact that, short of Client SSL Certificates, there's no way to know that the sender of the HTTP call is who we think they are. Because of these, a mechanism is needed to ensure that the webhook is not being spoofed and that it isn't being replayed. For this, I'm using a Nonce and HMAC-SHA256. The definition of the Signing process (and a Python example) follows:

Creating the Signature

1. Generate a Random UUID.
3. A new, empty string is created, henceforth known as the signing string.
4. In alphabetical order of the Header names, append the HTTP Request headers (names and values, in that order, in lower case) onto the signing string.
5. Base64 encode the request body. Append the resulting Base64 encoded string to the signing string.
6. Using HMAC SHA256, create the signature. The previously exchanged key is to be used as the key and the signing string as the value to be signed.
7. Take the resulting HMAC value and Base64 encode it. Create the HTTP Header “x-webhook-signature” with the resulting Base64 encoded HMAC string as the value.

Verifying the signature:

This process is almost the exact same as generating the signature with a few minor changes. 1. Verifiers should not generate their own nonce, but use the one provided in the “x-webhook-nonce” header. 2. Verifiers should first check and ensure that the nonce has not been used before. If it has, it should ignore the webhook. 3. When arranging the headers for the signing string, do not add the “x-webhook-signature” header. 4. Once you have generated a signing string, compare it to the included “x-webhook-signature” to ensure that the generated signature and the header value are the same. If they are, the request is valid. If not, ignore the webhook.

Generating Signature Example in Python:

signing_key = "SIGNING_KEY_FROM_SUBSCRIPTION"
nonce = uuid.uuid4()

body = "{\"url\": \"https://example.com/\"}"
'Content-Length': 25,
'Host': 'example.com',
'x-webhook-nonce': nonce
}

to_sign = ""

if key != "x-webhook-signature":

to_sign += base64.b64encode(body)
signature = base64.b64encode(hmac.new(signing_key, to_sign, digestmod=hashlib.sha256).digest())


So, after that large wall of text, does this solution correctly prevent against spoofing and replaying of webhooks?

• A server certificate plus a password is a way "short of Client SSL Certificates" "to know $\hspace{1.12 in}$ that the sender of the HTTP call is who we think they are". $\;$ – user991 Aug 11 '14 at 21:47
• Why sign webhooks at all? I prefer a pattern where the recipient doesn't assume that the webhook is authentic and simply uses it as a trigger to fetch the relevant information. That fetch is authenticated and protected against replay attacks since it uses HTTPS with your server as target. – CodesInChaos Aug 12 '14 at 8:02
• @CodesInChaos mostly because there's no good reason not to. If one has a reliable way to ensure authenticity, this reduces latency in the system and helps to reduce superfluous HTTP calls. It'd also be somewhat trivial to perform a DoS attach against someone that accepts all webhooks as a trigger to update from the HTTPS target. I send very small payloads to you and you fetch much larger payloads from an external system. I can send 1000's of requests quite easily which then causes your system to use significantly more bandwidth than I am using. – Jessie A. Morris Aug 12 '14 at 13:15
• @RickyDemer Certainly, but the receivers of the webhooks would be the "server" in this case. The receivers would likely receive the webhooks for multiple different systems and many different users on each system. They are also likely going to be third party systems. I don't want to require them to set up a password. It puts significantly higher burden on the receiver of the webhooks. – Jessie A. Morris Aug 12 '14 at 13:18
• Is there a reason you aren't just using client certificates? They were designed for solving this problem. The TLS folks thought a lot about the security challenges, so you wouldn't have to. – D.W. Aug 15 '14 at 3:06