Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update "Securing Your Webhooks" to prefer X-Hub-Signature-Sha-256 header #82

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions content/developers/webhooks-and-events/securing-your-webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ $ export SECRET_TOKEN=<em>your_token</em>

When your secret token is set, GitHub uses it to create a hash signature with each payload.

This hash signature is passed along with each request in the headers as `X-Hub-Signature`. Suppose you have a basic server listening to webhooks that looks like this:
This hash signature is passed along with each request in the headers as `X-Hub-Signature-256`. Suppose you have a basic server listening to webhooks that looks like this:

``` ruby
require 'sinatra'
Expand All @@ -60,15 +60,17 @@ post '/payload' do
end

def verify_signature(payload_body)
signature = 'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), ENV['SECRET_TOKEN'], payload_body)
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE'])
signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], payload_body)
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_2'])
end
```

Obviously, your language and server implementations may differ than this code. There are a couple of very important things to point out, however:

* No matter which implementation you use, the hash signature starts with `sha1=`, using the key of your secret token and your payload body.
* No matter which implementation you use, the hash signature starts with `sha256=`, using the key of your secret token and your payload body.

* Using a plain `==` operator is **not advised**. A method like [`secure_compare`][secure_compare] performs a "constant time" string comparison, which renders it safe from certain timing attacks against regular equality operators.

We also include a signature based on SHA-1 for backward-compatibility in a header called `X-Hub-Signature`. If possible, prefer `X-Hub-Signature-256` for improved security. We do not currently plan to deprecate the old header, so it should be safe to rely on it if updating to SHA-256 isn't feasible.

[secure_compare]: http://rubydoc.info/github/rack/rack/master/Rack/Utils.secure_compare