mirror of
https://git.asonix.dog/asonix/http-signature-normalization.git
synced 2024-11-21 17:00:59 +00:00
Move to partial updates for verification, put it on the threadpool
This commit is contained in:
parent
2366c9a917
commit
cd1a824ebb
5 changed files with 115 additions and 51 deletions
|
@ -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 <asonix@asonix.dog>"]
|
||||
license-file = "LICENSE"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -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<T, S, B> Transform<S> for VerifyDigest<T>
|
||||
where
|
||||
T: DigestVerify + Clone + 'static,
|
||||
T: DigestVerify + Clone + Send + 'static,
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error>
|
||||
+ 'static,
|
||||
S::Error: 'static,
|
||||
|
@ -108,7 +108,7 @@ type FutResult<T, E> = dyn Future<Output = Result<T, E>>;
|
|||
|
||||
impl<T, S, B> Service for VerifyMiddleware<T, S>
|
||||
where
|
||||
T: DigestVerify + Clone + 'static,
|
||||
T: DigestVerify + Clone + Send + 'static,
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error>
|
||||
+ 'static,
|
||||
S::Error: 'static,
|
||||
|
@ -163,24 +163,29 @@ async fn verify_payload<T>(
|
|||
mut tx: mpsc::Sender<Bytes>,
|
||||
) -> 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<T, VerifyError>
|
||||
})
|
||||
.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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha2::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha2::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha2::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha2::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha2::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha2::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::NAME, parts)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::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, <Self as DigestCreate>::NAME, parts, bytes)
|
||||
fn update(&mut self, part: &[u8]) {
|
||||
sha3::Digest::update(self, part);
|
||||
}
|
||||
|
||||
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||||
verify(self, <Self as DigestCreate>::NAME, parts)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue