Add basic digest logging

handle differing digest name cases
This commit is contained in:
asonix 2020-03-17 14:27:38 -05:00
parent 926ed7fc56
commit aaf8e16db4
6 changed files with 120 additions and 211 deletions

View file

@ -1,7 +1,7 @@
[package] [package]
name = "http-signature-normalization-actix" name = "http-signature-normalization-actix"
description = "An HTTP Signatures library that leaves the signing to you" 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 <asonix@asonix.dog>"] authors = ["asonix <asonix@asonix.dog>"]
license-file = "LICENSE" license-file = "LICENSE"
readme = "README.md" 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 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
default = ["sha-2", "sha-3"] default = ["sha-2", "sha-3"]
digest = ["base64"] digest = ["base64", "log"]
sha-2 = ["digest", "sha2"] sha-2 = ["digest", "sha2"]
sha-3 = ["digest", "sha3"] sha-3 = ["digest", "sha3"]
@ -31,6 +31,7 @@ base64 = { version = "0.11", optional = true }
bytes = "0.5.4" bytes = "0.5.4"
futures = "0.3" futures = "0.3"
http-signature-normalization = { version = "0.3.0", path = ".." } http-signature-normalization = { version = "0.3.0", path = ".." }
log = { version = "0.4", optional = true }
sha2 = { version = "0.8", optional = true } sha2 = { version = "0.8", optional = true }
sha3 = { version = "0.8", optional = true } sha3 = { version = "0.8", optional = true }
thiserror = "1.0" thiserror = "1.0"
@ -38,3 +39,4 @@ thiserror = "1.0"
[dev-dependencies] [dev-dependencies]
actix = "0.10.0-alpha.1" actix = "0.10.0-alpha.1"
actix-rt = "1.0.0" actix-rt = "1.0.0"
pretty_env_logger = "0.4"

View file

@ -16,7 +16,7 @@ This crate provides extensions the ClientRequest type from Actix Web, and provid
actix = "0.10.0-alpha.1" actix = "0.10.0-alpha.1"
actix-web = "3.0.0-alpha.1" actix-web = "3.0.0-alpha.1"
thiserror = "0.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" sha2 = "0.8"
``` ```

View file

@ -4,6 +4,9 @@ use sha2::{Digest, Sha256};
#[actix_rt::main] #[actix_rt::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::set_var("RUST_LOG", "info");
pretty_env_logger::init();
let config = Config::default(); let config = Config::default();
let mut digest = Sha256::new(); let mut digest = Sha256::new();

View file

@ -41,6 +41,9 @@ async fn index(_: (DigestVerified, SignatureVerified)) -> &'static str {
#[actix_rt::main] #[actix_rt::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::set_var("RUST_LOG", "info");
pretty_env_logger::init();
let config = Config::default(); let config = Config::default();
HttpServer::new(move || { HttpServer::new(move || {

View file

@ -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}; 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 { impl DigestCreate for Sha224 {
const NAME: &'static str = "sha-224"; const NAME: &'static str = "SHA-224";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha224 { impl DigestVerify for Sha224 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha256 { impl DigestCreate for Sha256 {
const NAME: &'static str = "sha-256"; const NAME: &'static str = "SHA-256";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha256 { impl DigestVerify for Sha256 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha384 { impl DigestCreate for Sha384 {
const NAME: &'static str = "sha-384"; const NAME: &'static str = "SHA-384";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha384 { impl DigestVerify for Sha384 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha512 { impl DigestCreate for Sha512 {
const NAME: &'static str = "sha-512"; const NAME: &'static str = "SHA-512";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha512 { impl DigestVerify for Sha512 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha512Trunc224 { 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 { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha512Trunc224 { impl DigestVerify for Sha512Trunc224 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha512Trunc256 { 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 { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha512Trunc256 { impl DigestVerify for Sha512Trunc256 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }

View file

@ -1,107 +1,96 @@
use log::{info, warn};
use sha3::{ use sha3::{
Digest as _, Keccak224, Keccak256, Keccak256Full, Keccak384, Keccak512, Sha3_224, Sha3_256, Keccak224, Keccak256, Keccak256Full, Keccak384, Keccak512, Sha3_224, Sha3_256, Sha3_384,
Sha3_384, Sha3_512, Sha3_512,
}; };
use super::{DigestCreate, DigestPart, DigestVerify}; 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 { impl DigestCreate for Sha3_224 {
const NAME: &'static str = "sha3-224"; const NAME: &'static str = "SHA3-224";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha3_224 { impl DigestVerify for Sha3_224 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha3_256 { impl DigestCreate for Sha3_256 {
const NAME: &'static str = "sha3-256"; const NAME: &'static str = "SHA3-256";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha3_256 { impl DigestVerify for Sha3_256 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha3_384 { impl DigestCreate for Sha3_384 {
const NAME: &'static str = "sha3-384"; const NAME: &'static str = "SHA3-384";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha3_384 { impl DigestVerify for Sha3_384 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
impl DigestCreate for Sha3_512 { impl DigestCreate for Sha3_512 {
const NAME: &'static str = "sha3-512"; const NAME: &'static str = "SHA3-512";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Sha3_512 { impl DigestVerify for Sha3_512 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
@ -109,24 +98,13 @@ impl DigestCreate for Keccak224 {
const NAME: &'static str = "keccak-224"; const NAME: &'static str = "keccak-224";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Keccak224 { impl DigestVerify for Keccak224 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
@ -134,24 +112,13 @@ impl DigestCreate for Keccak256 {
const NAME: &'static str = "keccak-256"; const NAME: &'static str = "keccak-256";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Keccak256 { impl DigestVerify for Keccak256 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
@ -159,24 +126,13 @@ impl DigestCreate for Keccak256Full {
const NAME: &'static str = "keccak-256-full"; const NAME: &'static str = "keccak-256-full";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Keccak256Full { impl DigestVerify for Keccak256Full {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
@ -184,24 +140,13 @@ impl DigestCreate for Keccak384 {
const NAME: &'static str = "keccak-384"; const NAME: &'static str = "keccak-384";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Keccak384 { impl DigestVerify for Keccak384 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }
@ -209,23 +154,12 @@ impl DigestCreate for Keccak512 {
const NAME: &'static str = "keccak-512"; const NAME: &'static str = "keccak-512";
fn compute(&mut self, input: &[u8]) -> String { fn compute(&mut self, input: &[u8]) -> String {
self.input(input); create(self, input)
base64::encode(&self.result_reset())
} }
} }
impl DigestVerify for Keccak512 { impl DigestVerify for Keccak512 {
fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool { fn verify(&mut self, parts: &[DigestPart], bytes: &[u8]) -> bool {
if let Some(part) = parts verify(self, <Self as DigestCreate>::NAME, parts, bytes)
.iter()
.find(|p| p.algorithm == <Self as DigestCreate>::NAME)
{
self.input(bytes);
let digest = base64::encode(&self.result_reset());
return part.digest == digest;
}
false
} }
} }