Skip to content

Commit 1f1e8a7

Browse files
Switch to openssl for github webhook verification
This also drops the rust-crypto dependencies
1 parent d872f55 commit 1f1e8a7

File tree

3 files changed

+16
-64
lines changed

3 files changed

+16
-64
lines changed

Cargo.lock

Lines changed: 1 addition & 49 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ maplit = "1.0.1"
1616
reqwest = "0.9.12"
1717
rocket = "0.4.0"
1818
rocket_contrib = { version = "0.4.0", features = ["json", "handlebars_templates"] }
19-
rust-crypto = "0.2.36"
19+
openssl = "0.10"
2020
serde = "1.0.59"
2121
serde_derive = "1.0.59"
2222
serde_json = "1.0"

src/github/webhooks.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
use std::io::Read;
22

3-
use crypto::hmac::Hmac;
4-
use crypto::mac::Mac;
5-
use crypto::mac::MacResult;
6-
use crypto::sha1::Sha1;
73
use hex::FromHex;
4+
use openssl::{hash::MessageDigest, memcmp, pkey::PKey, sign::Signer};
85
use rocket::data::{self, Data, FromDataSimple};
96
use rocket::http::Status;
107
use rocket::outcome::Outcome::*;
@@ -27,7 +24,7 @@ impl FromDataSimple for Event {
2724
let headers = request.headers();
2825

2926
// see [this document](https://developer.github.com/webhooks/securing/) for more information
30-
let signature = match headers.get_one("X-Hub-Signature") {
27+
let signature = match headers.get_one("X-Hub-Signature-256") {
3128
Some(s) => s,
3229
None => return Failure((Status::BadRequest, "missing signature header")),
3330
};
@@ -51,7 +48,7 @@ impl FromDataSimple for Event {
5148
}
5249

5350
for secret in &CONFIG.github_webhook_secrets {
54-
if authenticate(secret, &body, signature) {
51+
if authenticate(secret, &body, signature).is_ok() {
5552
// once we know it's from github, we'll parse it
5653

5754
let payload = match parse_event(event_name, &body) {
@@ -97,16 +94,19 @@ impl FromDataSimple for Event {
9794
}
9895
}
9996

100-
fn authenticate(secret: &str, payload: &str, signature: &str) -> bool {
97+
fn authenticate(secret: &str, payload: &str, signature: &str) -> Result<(), ()> {
10198
// https://developer.github.com/webhooks/securing/#validating-payloads-from-github
102-
let sans_prefix = signature[5..].as_bytes();
103-
if let Ok(sigbytes) = Vec::from_hex(sans_prefix) {
104-
let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());
105-
mac.input(payload.as_bytes());
106-
// constant time comparison
107-
mac.result() == MacResult::new(&sigbytes)
99+
let signature = signature.get("sha256=".len()..).ok_or(())?.as_bytes();
100+
let signature = Vec::from_hex(signature).map_err(|_| ())?;
101+
let key = PKey::hmac(secret.as_bytes()).map_err(|_| ())?;
102+
let mut signer = Signer::new(MessageDigest::sha256(), &key).map_err(|_| ())?;
103+
signer.update(payload.as_bytes()).map_err(|_| ())?;
104+
let hmac = signer.sign_to_vec().map_err(|_| ())?;
105+
// constant time comparison
106+
if memcmp::eq(&hmac, &signature) {
107+
Ok(())
108108
} else {
109-
false
109+
Err(())
110110
}
111111
}
112112

0 commit comments

Comments
 (0)