diff --git a/crates/dkim/src/hash.rs b/crates/dkim/src/hash.rs index 2152b45c..5af0d9cf 100644 --- a/crates/dkim/src/hash.rs +++ b/crates/dkim/src/hash.rs @@ -99,19 +99,12 @@ impl HashImpl { /// https://datatracker.ietf.org/doc/html/rfc6376#section-3.7 pub(crate) fn compute_body_hash<'a>( canonicalization_type: canonicalization::Type, - length: Option<&str>, + length: Option, hash_algo: HashAlgo, email: &'a ParsedEmail<'a>, ) -> Result { let body = email.get_body_bytes(); - - let limit = if let Some(length) = length { - length - .parse::() - .map_err(|err| DKIMError::SignatureSyntaxError(format!("invalid length: {}", err)))? - } else { - usize::MAX - }; + let limit = length.unwrap_or(usize::MAX); let mut hasher = LimitHasher { hasher: HashImpl::from_algo(hash_algo), @@ -260,7 +253,7 @@ Hello Alice let email = ParsedEmail::parse_bytes(email.as_bytes()).unwrap(); let canonicalization_type = canonicalization::Type::Relaxed; - let length = Some("3"); + let length = Some(3); let hash_algo = HashAlgo::RsaSha1; assert_eq!( compute_body_hash(canonicalization_type, length, hash_algo, &email).unwrap(), diff --git a/crates/dkim/src/header.rs b/crates/dkim/src/header.rs index c504194c..614603a9 100644 --- a/crates/dkim/src/header.rs +++ b/crates/dkim/src/header.rs @@ -1,6 +1,7 @@ use crate::{parser, DKIMError}; use indexmap::map::IndexMap; use std::io::Write; +use std::str::FromStr; pub(crate) const HEADER: &str = "DKIM-Signature"; const REQUIRED_TAGS: &[&str] = &["v", "a", "b", "bh", "d", "h", "s"]; @@ -84,6 +85,26 @@ impl DKIMHeader { self.tags.get(name).map(|v| v.value.as_str()) } + /// Get the named tag. + /// Attempt to parse it into an `R` + pub fn parse_tag(&self, name: &str) -> Result, DKIMError> + where + R: FromStr, + ::Err: std::fmt::Display, + { + match self.get_tag(name) { + None => Ok(None), + Some(value) => { + let value: R = value.parse().map_err(|err| { + DKIMError::SignatureSyntaxError(format!( + "invalid \"{name}\" tag value: {err:#}" + )) + })?; + Ok(Some(value)) + } + } + } + pub fn get_raw_tag(&self, name: &str) -> Option<&str> { self.tags.get(name).map(|v| v.raw_value.as_str()) } diff --git a/crates/dkim/src/lib.rs b/crates/dkim/src/lib.rs index 60356ff2..fe138230 100644 --- a/crates/dkim/src/lib.rs +++ b/crates/dkim/src/lib.rs @@ -93,7 +93,7 @@ async fn verify_email_header<'a>( let hash_algo = parser::parse_hash_algo(&dkim_header.get_required_tag("a"))?; let computed_body_hash = hash::compute_body_hash( body_canonicalization_type, - dkim_header.get_tag("l"), + dkim_header.parse_tag("l")?, hash_algo, email, )?;