http-signature-normalization-actix 0.12.0

An HTTP Signatures library that leaves the signing to you
Documentation
use crate::digest::DigestName;
use sha2::{Sha224, Sha256, Sha384, Sha512};

impl DigestName for Sha224 {
    const NAME: &'static str = "SHA-244";
}

impl DigestName for Sha256 {
    const NAME: &'static str = "SHA-256";
}

impl DigestName for Sha384 {
    const NAME: &'static str = "SHA-384";
}

impl DigestName for Sha512 {
    const NAME: &'static str = "SHA-512";
}

#[cfg(feature = "client")]
mod client {
    use super::*;
    use crate::digest::DigestCreate;
    use base64::prelude::*;

    fn create<D: sha2::Digest + sha2::digest::FixedOutputReset>(
        digest: &mut D,
        input: &[u8],
    ) -> String {
        sha2::Digest::update(digest, input);
        BASE64_STANDARD.encode(digest.finalize_reset())
    }

    impl DigestCreate for Sha224 {
        fn compute(&mut self, input: &[u8]) -> String {
            create(self, input)
        }
    }

    impl DigestCreate for Sha256 {
        fn compute(&mut self, input: &[u8]) -> String {
            create(self, input)
        }
    }

    impl DigestCreate for Sha384 {
        fn compute(&mut self, input: &[u8]) -> String {
            create(self, input)
        }
    }

    impl DigestCreate for Sha512 {
        fn compute(&mut self, input: &[u8]) -> String {
            create(self, input)
        }
    }
}

#[cfg(feature = "server")]
mod server {
    use super::*;
    use crate::digest::{DigestPart, DigestVerify};
    use base64::prelude::*;
    use tracing::{debug, warn};

    fn verify<D: sha2::Digest + sha2::digest::FixedOutputReset>(
        digest: &mut D,
        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);
            let encoded = BASE64_STANDARD.encode(digest.finalize_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.push_str(", ");
                }
                acc.push_str(&item.algorithm);
                acc
            })
        );

        false
    }

    impl DigestVerify for Sha224 {
        fn update(&mut self, part: &[u8]) {
            sha2::Digest::update(self, part);
        }

        fn verify(&mut self, parts: &[DigestPart]) -> bool {
            verify(self, Self::NAME, parts)
        }
    }

    impl DigestVerify for Sha256 {
        fn update(&mut self, part: &[u8]) {
            sha2::Digest::update(self, part);
        }

        fn verify(&mut self, parts: &[DigestPart]) -> bool {
            verify(self, Self::NAME, parts)
        }
    }

    impl DigestVerify for Sha384 {
        fn update(&mut self, part: &[u8]) {
            sha2::Digest::update(self, part);
        }

        fn verify(&mut self, parts: &[DigestPart]) -> bool {
            verify(self, Self::NAME, parts)
        }
    }

    impl DigestVerify for Sha512 {
        fn update(&mut self, part: &[u8]) {
            sha2::Digest::update(self, part);
        }

        fn verify(&mut self, parts: &[DigestPart]) -> bool {
            verify(self, Self::NAME, parts)
        }
    }
}