//! Hash algorithms supported by picky use digest::Digest; use picky_asn1_x509::ShaVariant; use serde::{Deserialize, Serialize}; use std::error::Error; use std::fmt; /// unsupported algorithm #[derive(Debug)] pub struct UnsupportedHashAlgorithmError { pub algorithm: String, } impl fmt::Display for UnsupportedHashAlgorithmError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "unsupported algorithm: {}", self.algorithm) } } impl Error for UnsupportedHashAlgorithmError {} /// Supported hash algorithms #[derive(Deserialize, Serialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[non_exhaustive] pub enum HashAlgorithm { MD5, SHA1, SHA2_224, SHA2_256, SHA2_384, SHA2_512, SHA3_384, SHA3_512, } impl TryFrom for ShaVariant { type Error = UnsupportedHashAlgorithmError; fn try_from(v: HashAlgorithm) -> Result { match v { HashAlgorithm::MD5 => Ok(ShaVariant::MD5), HashAlgorithm::SHA1 => Ok(ShaVariant::SHA1), HashAlgorithm::SHA2_256 => Ok(ShaVariant::SHA2_256), HashAlgorithm::SHA2_384 => Ok(ShaVariant::SHA2_384), HashAlgorithm::SHA2_512 => Ok(ShaVariant::SHA2_512), HashAlgorithm::SHA3_384 => Ok(ShaVariant::SHA3_384), HashAlgorithm::SHA3_512 => Ok(ShaVariant::SHA3_512), _ => Err(UnsupportedHashAlgorithmError { algorithm: format!("{v:?}"), }), } } } impl TryFrom for HashAlgorithm { type Error = UnsupportedHashAlgorithmError; fn try_from(v: ShaVariant) -> Result { match v { ShaVariant::MD5 => Ok(HashAlgorithm::MD5), ShaVariant::SHA1 => Ok(HashAlgorithm::SHA1), ShaVariant::SHA2_256 => Ok(HashAlgorithm::SHA2_256), ShaVariant::SHA2_384 => Ok(HashAlgorithm::SHA2_384), ShaVariant::SHA2_512 => Ok(HashAlgorithm::SHA2_512), ShaVariant::SHA3_384 => Ok(HashAlgorithm::SHA3_384), ShaVariant::SHA3_512 => Ok(HashAlgorithm::SHA3_512), _ => Err(UnsupportedHashAlgorithmError { algorithm: format!("{v:?}"), }), } } } impl HashAlgorithm { pub fn digest(self, msg: &[u8]) -> Vec { match self { Self::MD5 => md5::Md5::digest(msg).as_slice().to_vec(), Self::SHA1 => sha1::Sha1::digest(msg).as_slice().to_vec(), Self::SHA2_224 => sha2::Sha224::digest(msg).as_slice().to_vec(), Self::SHA2_256 => sha2::Sha256::digest(msg).as_slice().to_vec(), Self::SHA2_384 => sha2::Sha384::digest(msg).as_slice().to_vec(), Self::SHA2_512 => sha2::Sha512::digest(msg).as_slice().to_vec(), Self::SHA3_384 => sha3::Sha3_384::digest(msg).as_slice().to_vec(), Self::SHA3_512 => sha3::Sha3_512::digest(msg).as_slice().to_vec(), } } pub fn output_size(self) -> usize { match self { Self::MD5 => md5::Md5::output_size(), Self::SHA1 => sha1::Sha1::output_size(), Self::SHA2_224 => sha2::Sha224::output_size(), Self::SHA2_256 => sha2::Sha256::output_size(), Self::SHA2_384 => sha2::Sha384::output_size(), Self::SHA2_512 => sha2::Sha512::output_size(), Self::SHA3_384 => sha3::Sha3_384::output_size(), Self::SHA3_512 => sha3::Sha3_512::output_size(), } } }