From cd1a824ebb675947fa370a5f136a08dea654f5d5 Mon Sep 17 00:00:00 2001 From: asonix Date: Wed, 1 Jul 2020 17:27:34 -0500 Subject: [PATCH] Move to partial updates for verification, put it on the threadpool --- http-signature-normalization-actix/Cargo.toml | 2 +- .../src/digest/middleware.rs | 29 ++++--- .../src/digest/mod.rs | 9 ++- .../src/digest/sha2.rs | 51 +++++++++---- .../src/digest/sha3.rs | 75 ++++++++++++++----- 5 files changed, 115 insertions(+), 51 deletions(-) diff --git a/http-signature-normalization-actix/Cargo.toml b/http-signature-normalization-actix/Cargo.toml index 4c31f44..fa1fe57 100644 --- a/http-signature-normalization-actix/Cargo.toml +++ b/http-signature-normalization-actix/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "http-signature-normalization-actix" description = "An HTTP Signatures library that leaves the signing to you" -version = "0.4.0-alpha.0" +version = "0.4.0-alpha.1" authors = ["asonix "] license-file = "LICENSE" readme = "README.md" diff --git a/http-signature-normalization-actix/src/digest/middleware.rs b/http-signature-normalization-actix/src/digest/middleware.rs index 10f511d..ebb2a3f 100644 --- a/http-signature-normalization-actix/src/digest/middleware.rs +++ b/http-signature-normalization-actix/src/digest/middleware.rs @@ -5,9 +5,9 @@ use actix_web::{ dev::{MessageBody, Payload, Service, ServiceRequest, ServiceResponse, Transform}, error::PayloadError, http::{header::HeaderValue, StatusCode}, - FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError, + web, FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError, }; -use bytes::{Bytes, BytesMut}; +use bytes::Bytes; use futures::{ channel::mpsc, future::{err, ok, ready, Ready}, @@ -86,7 +86,7 @@ impl FromRequest for DigestVerified { impl Transform for VerifyDigest where - T: DigestVerify + Clone + 'static, + T: DigestVerify + Clone + Send + 'static, S: Service, Error = actix_web::Error> + 'static, S::Error: 'static, @@ -108,7 +108,7 @@ type FutResult = dyn Future>; impl Service for VerifyMiddleware where - T: DigestVerify + Clone + 'static, + T: DigestVerify + Clone + Send + 'static, S: Service, Error = actix_web::Error> + 'static, S::Error: 'static, @@ -163,24 +163,29 @@ async fn verify_payload( mut tx: mpsc::Sender, ) -> Result<(), actix_web::Error> where - T: DigestVerify + Clone + 'static, + T: DigestVerify + Clone + Send + 'static, { - let mut output_bytes = BytesMut::new(); - while let Some(res) = payload.next().await { let bytes = res?; - output_bytes.extend(bytes); + let bytes2 = bytes.clone(); + verify_digest = web::block(move || { + verify_digest.update(&bytes2.as_ref()); + Ok(verify_digest) as Result + }) + .await?; if tx.is_closed() { warn!("Payload dropped. If this was unexpected, it could be that the payload isn't required in the route this middleware is guarding"); - return Err(VerifyError.into()); } + + tx.try_send(bytes).map_err(|_| VerifyError)?; } - let bytes = output_bytes.freeze(); + let verified = + web::block(move || Ok(verify_digest.verify(&vec)) as Result<_, VerifyError>).await?; - if verify_digest.verify(&vec, &bytes.as_ref()) { - tx.try_send(bytes).map_err(|_| VerifyError.into()) + if verified { + Ok(()) } else { warn!("Digest could not be verified"); Err(VerifyError.into()) diff --git a/http-signature-normalization-actix/src/digest/mod.rs b/http-signature-normalization-actix/src/digest/mod.rs index 9812cac..8206a3b 100644 --- a/http-signature-normalization-actix/src/digest/mod.rs +++ b/http-signature-normalization-actix/src/digest/mod.rs @@ -33,10 +33,11 @@ pub trait DigestCreate { /// A trait for verifying digests pub trait DigestVerify { - /// Verify the payload of the request against a slice of digests - /// - /// The slice of digests should never be empty - fn verify(&mut self, digests: &[DigestPart], payload: &[u8]) -> bool; + /// Update the verifier with bytes from the request body + fn update(&mut self, part: &[u8]); + + /// Verify the request body against the digests from the request headers + fn verify(&mut self, digests: &[DigestPart]) -> bool; } /// Extend the Sign trait with support for adding Digest Headers to the request diff --git a/http-signature-normalization-actix/src/digest/sha2.rs b/http-signature-normalization-actix/src/digest/sha2.rs index 6a436d0..d26960f 100644 --- a/http-signature-normalization-actix/src/digest/sha2.rs +++ b/http-signature-normalization-actix/src/digest/sha2.rs @@ -8,13 +8,12 @@ fn create(digest: &mut impl sha2::Digest, input: &[u8]) -> String { base64::encode(&digest.finalize_reset()) } -fn verify(digest: &mut impl sha2::Digest, name: &str, parts: &[DigestPart], bytes: &[u8]) -> bool { +fn verify(digest: &mut impl sha2::Digest, name: &str, parts: &[DigestPart]) -> bool { if let Some(part) = parts .iter() .find(|p| p.algorithm.to_lowercase() == name.to_lowercase()) { debug!("Verifying digest type, {}", name); - digest.update(bytes); let encoded = base64::encode(&digest.finalize_reset()); return part.digest == encoded; @@ -44,8 +43,12 @@ impl DigestCreate for Sha224 { } impl DigestVerify for Sha224 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha2::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -58,8 +61,12 @@ impl DigestCreate for Sha256 { } impl DigestVerify for Sha256 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha2::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -72,8 +79,12 @@ impl DigestCreate for Sha384 { } impl DigestVerify for Sha384 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha2::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -86,8 +97,12 @@ impl DigestCreate for Sha512 { } impl DigestVerify for Sha512 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha2::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -100,8 +115,12 @@ impl DigestCreate for Sha512Trunc224 { } impl DigestVerify for Sha512Trunc224 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha2::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -114,7 +133,11 @@ impl DigestCreate for Sha512Trunc256 { } impl DigestVerify for Sha512Trunc256 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha2::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } diff --git a/http-signature-normalization-actix/src/digest/sha3.rs b/http-signature-normalization-actix/src/digest/sha3.rs index 1367370..3938f84 100644 --- a/http-signature-normalization-actix/src/digest/sha3.rs +++ b/http-signature-normalization-actix/src/digest/sha3.rs @@ -11,13 +11,12 @@ fn create(digest: &mut impl sha2::Digest, input: &[u8]) -> String { base64::encode(&digest.finalize_reset()) } -fn verify(digest: &mut impl sha2::Digest, name: &str, parts: &[DigestPart], bytes: &[u8]) -> bool { +fn verify(digest: &mut impl sha2::Digest, name: &str, parts: &[DigestPart]) -> bool { if let Some(part) = parts .iter() .find(|p| p.algorithm.to_lowercase() == name.to_lowercase()) { debug!("Verifying digest type, {}", name); - digest.update(bytes); let encoded = base64::encode(&digest.finalize_reset()); return part.digest == encoded; @@ -47,8 +46,12 @@ impl DigestCreate for Sha3_224 { } impl DigestVerify for Sha3_224 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -61,8 +64,12 @@ impl DigestCreate for Sha3_256 { } impl DigestVerify for Sha3_256 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -75,8 +82,12 @@ impl DigestCreate for Sha3_384 { } impl DigestVerify for Sha3_384 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -89,8 +100,12 @@ impl DigestCreate for Sha3_512 { } impl DigestVerify for Sha3_512 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -103,8 +118,12 @@ impl DigestCreate for Keccak224 { } impl DigestVerify for Keccak224 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -117,8 +136,12 @@ impl DigestCreate for Keccak256 { } impl DigestVerify for Keccak256 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -131,8 +154,12 @@ impl DigestCreate for Keccak256Full { } impl DigestVerify for Keccak256Full { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -145,8 +172,12 @@ impl DigestCreate for Keccak384 { } impl DigestVerify for Keccak384 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } } @@ -159,7 +190,11 @@ impl DigestCreate for Keccak512 { } impl DigestVerify for Keccak512 { - fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - verify(self, ::NAME, parts, bytes) + fn update(&mut self, part: &[u8]) { + sha3::Digest::update(self, part); + } + + fn verify(&mut self, parts: &[DigestPart]) -> bool { + verify(self, ::NAME, parts) } }