//! Types for creating digests with the `ring` cryptography library use crate::digest::DigestName; /// A Sha256 digest backed by ring #[derive(Clone)] pub struct Sha256 { ctx: ring::digest::Context, } /// A Sha384 digest backed by ring #[derive(Clone)] pub struct Sha384 { ctx: ring::digest::Context, } /// A Sha512 digest backed by ring #[derive(Clone)] pub struct Sha512 { ctx: ring::digest::Context, } impl Sha256 { /// Create a new empty digest pub fn new() -> Self { Self::default() } /// Extract the context pub fn into_inner(self) -> ring::digest::Context { self.ctx } } impl Default for Sha256 { fn default() -> Self { Sha256 { ctx: ring::digest::Context::new(&ring::digest::SHA256), } } } impl Sha384 { /// Create a new empty digest pub fn new() -> Self { Self::default() } /// Extract the context pub fn into_inner(self) -> ring::digest::Context { self.ctx } } impl Default for Sha384 { fn default() -> Self { Sha384 { ctx: ring::digest::Context::new(&ring::digest::SHA384), } } } impl Sha512 { /// Create a new empty digest pub fn new() -> Self { Self::default() } /// Extract the context pub fn into_inner(self) -> ring::digest::Context { self.ctx } } impl Default for Sha512 { fn default() -> Self { Sha512 { ctx: ring::digest::Context::new(&ring::digest::SHA512), } } } 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(mut context: ring::digest::Context, input: &[u8]) -> String { context.update(input); let digest = context.finish(); BASE64_STANDARD.encode(digest.as_ref()) } impl DigestCreate for Sha256 { fn compute(&mut self, input: &[u8]) -> String { create(self.ctx.clone(), input) } } impl DigestCreate for Sha384 { fn compute(&mut self, input: &[u8]) -> String { create(self.ctx.clone(), input) } } impl DigestCreate for Sha512 { fn compute(&mut self, input: &[u8]) -> String { create(self.ctx.clone(), input) } } } #[cfg(feature = "server")] mod server { use super::*; use crate::digest::{DigestPart, DigestVerify}; use base64::prelude::*; use tracing::{debug, warn}; fn verify(context: ring::digest::Context, 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 digest = context.finish(); let encoded = BASE64_STANDARD.encode(digest.as_ref()); 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 Sha256 { fn update(&mut self, part: &[u8]) { self.ctx.update(part); } fn verify(&mut self, parts: &[DigestPart]) -> bool { let alg = self.ctx.algorithm(); let ctx = std::mem::replace(&mut self.ctx, ring::digest::Context::new(alg)); verify(ctx, Self::NAME, parts) } } impl DigestVerify for Sha384 { fn update(&mut self, part: &[u8]) { self.ctx.update(part); } fn verify(&mut self, parts: &[DigestPart]) -> bool { let alg = self.ctx.algorithm(); let ctx = std::mem::replace(&mut self.ctx, ring::digest::Context::new(alg)); verify(ctx, Self::NAME, parts) } } impl DigestVerify for Sha512 { fn update(&mut self, part: &[u8]) { self.ctx.update(part); } fn verify(&mut self, parts: &[DigestPart]) -> bool { let alg = self.ctx.algorithm(); let ctx = std::mem::replace(&mut self.ctx, ring::digest::Context::new(alg)); verify(ctx, Self::NAME, parts) } } }