Skip to content

Commit

Permalink
fix: introduce subtle and use it for constant time comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
arlyon committed Oct 8, 2021
1 parent ccc9329 commit dc11407
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 12 deletions.
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ sigma = []
webhook-endpoints = []

# deserialize events from webhooks
webhook-events = ["events", "hmac", "sha2", "chrono"]
webhook-events = ["events", "hmac", "sha2", "chrono", "subtle"]
events = []

# runtimes
Expand All @@ -78,6 +78,7 @@ runtime-async-std-surf = ["async-std", "surf", "async"]
[dependencies]
async-std = { version = "1.9", optional = true }
chrono = { version = "0.4", features = ["serde"], optional = true }
thiserror = "1.0.24"
hyper = { version = "0.14", default-features = false, features = ["http1", "http2", "client", "tcp"], optional = true }
hyper-tls = { version = "0.5", optional = true }
hyper-rustls = { version = "0.22", optional = true }
Expand All @@ -90,9 +91,9 @@ surf = { version = "2.1", optional = true }
tokio = { version = "1.2", optional = true }

# webhook support
hmac = { version = "0.10", optional = true }
hmac = { version = "0.11", optional = true }
sha2 = { version = "0.9", optional = true }
thiserror = "1.0.24"
subtle = { version = "2.4", optional = true }


[dev-dependencies]
Expand Down
23 changes: 14 additions & 9 deletions src/resources/webhook_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use hmac::{Hmac, Mac, NewMac};
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "webhook-events")]
use sha2::Sha256;
#[cfg(feature = "webhook-events")]
use subtle::ConstantTimeEq;

use crate::error::WebhookError;
use crate::ids::EventId;
Expand Down Expand Up @@ -259,17 +261,20 @@ impl Webhook {
secret: &str,
) -> Result<WebhookEvent, WebhookError> {
// Get Stripe signature from header
let signature = Signature::parse(&sig)?;
let signed_payload = format!("{}{}{}", signature.t, ".", payload);
let signature = Signature::parse(sig)?;
let signed_payload = format!("{}.{}", signature.t, payload);

// Compute HMAC with the SHA256 hash function, using endpoing secret as key
// and signed_payload string as the message.
let mut mac =
Hmac::<Sha256>::new_varkey(secret.as_bytes()).map_err(|_| WebhookError::BadKey)?;
mac.update(signed_payload.as_bytes());
let mac_result = mac.finalize();
let hex = to_hex(&mac_result.into_bytes());
if hex != signature.v1 {
let hex = {
let mut mac = Hmac::<Sha256>::new_from_slice(secret.as_bytes())
.map_err(|_| WebhookError::BadKey)?;
mac.update(signed_payload.as_bytes());
to_hex(&mac.finalize().into_bytes())
};

// if the hex signature doesn't equal the stripe signature
if hex.as_bytes().ct_eq(signature.v1.as_bytes()).unwrap_u8() == 0 {
return Err(WebhookError::BadSignature);
}

Expand All @@ -278,7 +283,7 @@ impl Webhook {
return Err(WebhookError::BadTimestamp(signature.t));
}

serde_json::from_str(&payload).map_err(WebhookError::BadParse)
Ok(serde_json::from_str(&payload)?)
}
}

Expand Down

0 comments on commit dc11407

Please sign in to comment.