diff --git a/Cargo.lock b/Cargo.lock index d76f4ac6..22ad9635 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1040,7 +1040,7 @@ dependencies = [ "dotenv", "env_logger", "flate2", - "hmac 0.12.1", + "hmac 0.13.0", "indexmap", "jiff", "lazy_static", @@ -1065,7 +1065,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_regex", - "sha-1", + "sha2 0.11.0", "smol_str", "tar", "tempfile", @@ -3725,17 +3725,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - [[package]] name = "sha1" version = "0.10.6" diff --git a/Cargo.toml b/Cargo.toml index 8ab5454d..1bf6c494 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ docsrs-metadata = { git = "https://github.com/rust-lang/docs.rs/" } dotenv = "0.15" env_logger = "0.11.8" flate2 = "1" -hmac = "0.12" +hmac = "0.13" indexmap = { version = "2.0.2", features = ["serde"] } lazy_static = "1.0" log = "0.4.6" @@ -56,7 +56,6 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" serde_regex = "1.1.0" -sha-1 = "0.10" tar = "0.4.36" tempfile = "3.0.0" tera = "1.19.1" @@ -68,6 +67,7 @@ walkdir = "2" warp = { version = "0.4", features = ["server"] } zstd = "0.13.0" rawzip = "0.4.0" +sha2 = "0.11.0" [dev-dependencies] assert_cmd = "2.0.4" diff --git a/src/server/routes/webhooks/mod.rs b/src/server/routes/webhooks/mod.rs index db425f25..9703be33 100644 --- a/src/server/routes/webhooks/mod.rs +++ b/src/server/routes/webhooks/mod.rs @@ -7,13 +7,15 @@ use crate::server::messages::Message; use crate::server::routes::webhooks::args::Command; use crate::server::{Data, GithubData}; use bytes::Bytes; -use hmac::{Hmac, Mac}; use std::str::FromStr; use std::sync::Arc; use warp::http::{HeaderMap, StatusCode}; use warp::reply::Response; use warp::{Filter, Rejection}; +use hmac::{Hmac, KeyInit, Mac}; +use sha2::Sha256; + fn process_webhook( payload: &[u8], host: &str, @@ -151,39 +153,24 @@ fn process_command( Ok(()) } -fn verify_signature(secret: &str, payload: &[u8], raw_signature: &str) -> bool { - type HmacSha1 = Hmac; +type HmacSha256 = Hmac; - // The signature must have a = - if !raw_signature.contains('=') { +fn verify_signature(secret: &str, payload: &[u8], raw_signature: &str) -> bool { + // Strip sha256= prefix validating expected algorithm + let Some(hex_signature) = raw_signature.strip_prefix("sha256=") else { return false; - } - - // Split the raw signature to get the algorithm and the signature - let splitted: Vec<&str> = raw_signature.split('=').collect(); - let algorithm = &splitted[0]; - let hex_signature = splitted - .iter() - .skip(1) - .cloned() - .collect::>() - .join("="); + }; // Convert the signature from hex - let signature = if let Ok(converted) = crate::utils::hex::from_hex(&hex_signature) { + let signature = if let Ok(converted) = crate::utils::hex::from_hex(hex_signature) { converted } else { // This is not hex return false; }; - // Only SHA-1 is supported - if *algorithm != "sha1" { - return false; - } - - // Verify the HMAC signature - let mut mac = HmacSha1::new_from_slice(secret.as_bytes()).unwrap(); + let mut mac = + HmacSha256::new_from_slice(secret.as_bytes()).expect("HMAC can take key of any size"); mac.update(payload); mac.verify_slice(&signature).is_ok() } @@ -195,7 +182,7 @@ fn receive_endpoint( body: Bytes, ) -> Fallible<()> { let signature = headers - .get("X-Hub-Signature") + .get("X-Hub-Signature-256") .and_then(|h| h.to_str().ok()) .ok_or_else(|| anyhow!("missing header X-Hub-Signature\n"))?; let event = headers @@ -249,3 +236,19 @@ pub fn routes( }, ) } + +#[test] +fn check_sig() { + let secret = "It's a Secret to Everybody"; + let payload: &[u8] = "Hello, World!".as_bytes(); + assert!(verify_signature( + secret, + payload, + "sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17" + )); + assert!(!verify_signature( + secret, + payload, + "sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e18" + )); +}