From aaf8e16db4b0c2f09a039c4ba332d659e59e5173 Mon Sep 17 00:00:00 2001 From: asonix Date: Tue, 17 Mar 2020 14:27:38 -0500 Subject: [PATCH] Add basic digest logging handle differing digest name cases --- http-signature-normalization-actix/Cargo.toml | 6 +- http-signature-normalization-actix/README.md | 2 +- .../examples/client.rs | 3 + .../examples/server.rs | 3 + .../src/digest/sha2.rs | 137 +++++-------- .../src/digest/sha3.rs | 180 ++++++------------ 6 files changed, 120 insertions(+), 211 deletions(-) diff --git a/http-signature-normalization-actix/Cargo.toml b/http-signature-normalization-actix/Cargo.toml index 7d7848f..2f1b253 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.3.0-alpha.1" +version = "0.3.0-alpha.2" authors = ["asonix "] license-file = "LICENSE" readme = "README.md" @@ -12,7 +12,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] default = ["sha-2", "sha-3"] -digest = ["base64"] +digest = ["base64", "log"] sha-2 = ["digest", "sha2"] sha-3 = ["digest", "sha3"] @@ -31,6 +31,7 @@ base64 = { version = "0.11", optional = true } bytes = "0.5.4" futures = "0.3" http-signature-normalization = { version = "0.3.0", path = ".." } +log = { version = "0.4", optional = true } sha2 = { version = "0.8", optional = true } sha3 = { version = "0.8", optional = true } thiserror = "1.0" @@ -38,3 +39,4 @@ thiserror = "1.0" [dev-dependencies] actix = "0.10.0-alpha.1" actix-rt = "1.0.0" +pretty_env_logger = "0.4" diff --git a/http-signature-normalization-actix/README.md b/http-signature-normalization-actix/README.md index 5732ad6..52ff497 100644 --- a/http-signature-normalization-actix/README.md +++ b/http-signature-normalization-actix/README.md @@ -16,7 +16,7 @@ This crate provides extensions the ClientRequest type from Actix Web, and provid actix = "0.10.0-alpha.1" actix-web = "3.0.0-alpha.1" thiserror = "0.1" -http-signature-normalization-actix = { version = "0.3.0-alpha.0", default-features = false, features = ["sha-2"] } +http-signature-normalization-actix = { version = "0.3.0-alpha.2", default-features = false, features = ["sha-2"] } sha2 = "0.8" ``` diff --git a/http-signature-normalization-actix/examples/client.rs b/http-signature-normalization-actix/examples/client.rs index 5edc73f..f30dc8b 100644 --- a/http-signature-normalization-actix/examples/client.rs +++ b/http-signature-normalization-actix/examples/client.rs @@ -4,6 +4,9 @@ use sha2::{Digest, Sha256}; #[actix_rt::main] async fn main() -> Result<(), Box> { + std::env::set_var("RUST_LOG", "info"); + pretty_env_logger::init(); + let config = Config::default(); let mut digest = Sha256::new(); diff --git a/http-signature-normalization-actix/examples/server.rs b/http-signature-normalization-actix/examples/server.rs index eca757c..5ffa804 100644 --- a/http-signature-normalization-actix/examples/server.rs +++ b/http-signature-normalization-actix/examples/server.rs @@ -41,6 +41,9 @@ async fn index(_: (DigestVerified, SignatureVerified)) -> &'static str { #[actix_rt::main] async fn main() -> Result<(), Box> { + std::env::set_var("RUST_LOG", "info"); + pretty_env_logger::init(); + let config = Config::default(); HttpServer::new(move || { diff --git a/http-signature-normalization-actix/src/digest/sha2.rs b/http-signature-normalization-actix/src/digest/sha2.rs index aa8c58d..6dbd113 100644 --- a/http-signature-normalization-actix/src/digest/sha2.rs +++ b/http-signature-normalization-actix/src/digest/sha2.rs @@ -1,153 +1,120 @@ -use sha2::{Digest as _, Sha224, Sha256, Sha384, Sha512, Sha512Trunc224, Sha512Trunc256}; +use log::{info, warn}; +use sha2::{Sha224, Sha256, Sha384, Sha512, Sha512Trunc224, Sha512Trunc256}; use super::{DigestCreate, DigestPart, DigestVerify}; +fn create(digest: &mut impl sha2::Digest, input: &[u8]) -> String { + digest.input(input); + base64::encode(&digest.result_reset()) +} + +fn verify(digest: &mut impl sha2::Digest, name: &str, parts: &[DigestPart], bytes: &[u8]) -> bool { + if let Some(part) = parts + .iter() + .find(|p| p.algorithm.to_lowercase() == name.to_lowercase()) + { + info!("Verifying digest type, {}", name); + digest.input(bytes); + let encoded = base64::encode(&digest.result_reset()); + + return part.digest == encoded; + } + warn!("No matching digest algorithm found for {}", name); + warn!( + "Provided: [{}]", + parts.iter().fold(String::new(), |mut acc, item| { + if acc.is_empty() { + } else { + acc.extend(", ".chars()); + } + acc.extend(item.algorithm.chars()); + acc + }) + ); + + false +} + impl DigestCreate for Sha224 { - const NAME: &'static str = "sha-224"; + const NAME: &'static str = "SHA-224"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha224 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha256 { - const NAME: &'static str = "sha-256"; + const NAME: &'static str = "SHA-256"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha256 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha384 { - const NAME: &'static str = "sha-384"; + const NAME: &'static str = "SHA-384"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha384 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha512 { - const NAME: &'static str = "sha-512"; + const NAME: &'static str = "SHA-512"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha512 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha512Trunc224 { - const NAME: &'static str = "sha-512-224"; + const NAME: &'static str = "SHA-512-224"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha512Trunc224 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha512Trunc256 { - const NAME: &'static str = "sha-512-256"; + const NAME: &'static str = "SHA-512-256"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha512Trunc256 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } diff --git a/http-signature-normalization-actix/src/digest/sha3.rs b/http-signature-normalization-actix/src/digest/sha3.rs index e671032..f160f0f 100644 --- a/http-signature-normalization-actix/src/digest/sha3.rs +++ b/http-signature-normalization-actix/src/digest/sha3.rs @@ -1,107 +1,96 @@ +use log::{info, warn}; use sha3::{ - Digest as _, Keccak224, Keccak256, Keccak256Full, Keccak384, Keccak512, Sha3_224, Sha3_256, - Sha3_384, Sha3_512, + Keccak224, Keccak256, Keccak256Full, Keccak384, Keccak512, Sha3_224, Sha3_256, Sha3_384, + Sha3_512, }; use super::{DigestCreate, DigestPart, DigestVerify}; +fn create(digest: &mut impl sha2::Digest, input: &[u8]) -> String { + digest.input(input); + base64::encode(&digest.result_reset()) +} + +fn verify(digest: &mut impl sha2::Digest, name: &str, parts: &[DigestPart], bytes: &[u8]) -> bool { + if let Some(part) = parts + .iter() + .find(|p| p.algorithm.to_lowercase() == name.to_lowercase()) + { + info!("Verifying digest type, {}", name); + digest.input(bytes); + let encoded = base64::encode(&digest.result_reset()); + + return part.digest == encoded; + } + warn!("No matching digest algorithm found for {}", name); + warn!( + "Provided: [{}]", + parts.iter().fold(String::new(), |mut acc, item| { + if acc.is_empty() { + } else { + acc.extend(", ".chars()); + } + acc.extend(item.algorithm.chars()); + acc + }) + ); + + false +} + impl DigestCreate for Sha3_224 { - const NAME: &'static str = "sha3-224"; + const NAME: &'static str = "SHA3-224"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha3_224 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha3_256 { - const NAME: &'static str = "sha3-256"; + const NAME: &'static str = "SHA3-256"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha3_256 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha3_384 { - const NAME: &'static str = "sha3-384"; + const NAME: &'static str = "SHA3-384"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha3_384 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } impl DigestCreate for Sha3_512 { - const NAME: &'static str = "sha3-512"; + const NAME: &'static str = "SHA3-512"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Sha3_512 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } @@ -109,24 +98,13 @@ impl DigestCreate for Keccak224 { const NAME: &'static str = "keccak-224"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Keccak224 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } @@ -134,24 +112,13 @@ impl DigestCreate for Keccak256 { const NAME: &'static str = "keccak-256"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Keccak256 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } @@ -159,24 +126,13 @@ impl DigestCreate for Keccak256Full { const NAME: &'static str = "keccak-256-full"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Keccak256Full { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } @@ -184,24 +140,13 @@ impl DigestCreate for Keccak384 { const NAME: &'static str = "keccak-384"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Keccak384 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } } @@ -209,23 +154,12 @@ impl DigestCreate for Keccak512 { const NAME: &'static str = "keccak-512"; fn compute(&mut self, input: &[u8]) -> String { - self.input(input); - base64::encode(&self.result_reset()) + create(self, input) } } impl DigestVerify for Keccak512 { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { - if let Some(part) = parts - .iter() - .find(|p| p.algorithm == ::NAME) - { - self.input(bytes); - let digest = base64::encode(&self.result_reset()); - - return part.digest == digest; - } - - false + verify(self, ::NAME, parts, bytes) } }