use digest::{ core_api::BlockSizeUser, Digest, DynDigest, ExtendableOutput, ExtendableOutputReset, Reset, Update,};use typenum::{U32, U48};
#[derive(Clone)]pub enum Context { Blake2b(Box<blake2::Blake2b512>), Blake2b256(Box<blake2::Blake2b<U32>>), Blake2b384(Box<blake2::Blake2b<U48>>), Blake2s(Box<blake2::Blake2s256>), Blake3(Box<blake3::Hasher>), Keccak224(Box<sha3::Keccak224>), Keccak256(Box<sha3::Keccak256>), Keccak384(Box<sha3::Keccak384>), Keccak512(Box<sha3::Keccak512>), Md4(Box<md4::Md4>), Md5(Box<md5::Md5>), Ripemd160(Box<ripemd::Ripemd160>), Sha1(Box<sha1::Sha1>), Sha3_224(Box<sha3::Sha3_224>), Sha3_256(Box<sha3::Sha3_256>), Sha3_384(Box<sha3::Sha3_384>), Sha3_512(Box<sha3::Sha3_512>), Sha224(Box<sha2::Sha224>), Sha256(Box<sha2::Sha256>), Sha384(Box<sha2::Sha384>), Sha512(Box<sha2::Sha512>), Shake128(Box<sha3::Shake128>), Shake256(Box<sha3::Shake256>), Tiger(Box<tiger::Tiger>),}
use Context::*;
impl Context { pub fn new(algorithm_name: &str) -> Result<Context, &'static str> { Ok(match algorithm_name { "BLAKE2B" => Blake2b(Default::default()), "BLAKE2B-256" => Blake2b256(Default::default()), "BLAKE2B-384" => Blake2b384(Default::default()), "BLAKE2S" => Blake2s(Default::default()), "BLAKE3" => Blake3(Default::default()), "KECCAK-224" => Keccak224(Default::default()), "KECCAK-256" => Keccak256(Default::default()), "KECCAK-384" => Keccak384(Default::default()), "KECCAK-512" => Keccak512(Default::default()), "MD4" => Md4(Default::default()), "MD5" => Md5(Default::default()), "RIPEMD-160" => Ripemd160(Default::default()), "SHA-1" => Sha1(Default::default()), "SHA3-224" => Sha3_224(Default::default()), "SHA3-256" => Sha3_256(Default::default()), "SHA3-384" => Sha3_384(Default::default()), "SHA3-512" => Sha3_512(Default::default()), "SHA-224" => Sha224(Default::default()), "SHA-256" => Sha256(Default::default()), "SHA-384" => Sha384(Default::default()), "SHA-512" => Sha512(Default::default()), "SHAKE128" => Shake128(Default::default()), "SHAKE256" => Shake256(Default::default()), "TIGER" => Tiger(Default::default()), _ => return Err("unsupported algorithm"), }) }
pub fn input_block_length(&self) -> usize { fn static_block_length<T: BlockSizeUser>(_: &T) -> usize { <T::BlockSize as typenum::Unsigned>::to_usize() }
match self { Blake2b(context) => static_block_length(&**context), Blake2b256(context) => static_block_length(&**context), Blake2b384(context) => static_block_length(&**context), Blake2s(context) => static_block_length(&**context), Blake3(_) => 64, Keccak224(context) => static_block_length(&**context), Keccak256(context) => static_block_length(&**context), Keccak384(context) => static_block_length(&**context), Keccak512(context) => static_block_length(&**context), Md4(context) => static_block_length(&**context), Md5(context) => static_block_length(&**context), Ripemd160(context) => static_block_length(&**context), Sha1(context) => static_block_length(&**context), Sha3_224(context) => static_block_length(&**context), Sha3_256(context) => static_block_length(&**context), Sha3_384(context) => static_block_length(&**context), Sha3_512(context) => static_block_length(&**context), Sha224(context) => static_block_length(&**context), Sha256(context) => static_block_length(&**context), Sha384(context) => static_block_length(&**context), Sha512(context) => static_block_length(&**context), Tiger(context) => static_block_length(&**context),
Shake128(_) => 168, Shake256(_) => 136, } }
pub fn output_length(&self) -> usize { match self { Blake2b(context) => context.output_size(), Blake2b256(context) => context.output_size(), Blake2b384(context) => context.output_size(), Blake2s(context) => context.output_size(), Blake3(context) => context.output_size(), Keccak224(context) => context.output_size(), Keccak256(context) => context.output_size(), Keccak384(context) => context.output_size(), Keccak512(context) => context.output_size(), Md4(context) => context.output_size(), Md5(context) => context.output_size(), Ripemd160(context) => context.output_size(), Sha1(context) => context.output_size(), Sha3_224(context) => context.output_size(), Sha3_256(context) => context.output_size(), Sha3_384(context) => context.output_size(), Sha3_512(context) => context.output_size(), Sha224(context) => context.output_size(), Sha256(context) => context.output_size(), Sha384(context) => context.output_size(), Sha512(context) => context.output_size(), Tiger(context) => context.output_size(),
Shake128(_) => 32, Shake256(_) => 64, } }
pub const fn extendable(&self) -> bool { matches!(self, Blake3(_) | Shake128(_) | Shake256(_)) }
pub const fn algorithm_name(&self) -> &'static str { match self { Blake2b(_) => "BLAKE2B", Blake2b256(_) => "BLAKE2B-256", Blake2b384(_) => "BLAKE2B-384", Blake2s(_) => "BLAKE2S", Blake3(_) => "BLAKE3", Keccak224(_) => "KECCAK-224", Keccak256(_) => "KECCAK-256", Keccak384(_) => "KECCAK-384", Keccak512(_) => "KECCAK-512", Md4(_) => "MD5", Md5(_) => "MD5", Ripemd160(_) => "RIPEMD-160", Sha1(_) => "SHA-1", Sha3_224(_) => "SHA3-224", Sha3_256(_) => "SHA3-256", Sha3_384(_) => "SHA3-384", Sha3_512(_) => "SHA3-512", Sha224(_) => "SHA-224", Sha256(_) => "SHA-256", Sha384(_) => "SHA-384", Sha512(_) => "SHA-512", Shake128(_) => "SHAKE128", Shake256(_) => "SHAKE256", Tiger(_) => "TIGER", } }
pub fn reset(&mut self) { match self { Blake2b(context) => Reset::reset(&mut **context), Blake2b256(context) => Reset::reset(&mut **context), Blake2b384(context) => Reset::reset(&mut **context), Blake2s(context) => Reset::reset(&mut **context), Blake3(context) => Reset::reset(&mut **context), Keccak224(context) => Reset::reset(&mut **context), Keccak256(context) => Reset::reset(&mut **context), Keccak384(context) => Reset::reset(&mut **context), Keccak512(context) => Reset::reset(&mut **context), Md4(context) => Reset::reset(&mut **context), Md5(context) => Reset::reset(&mut **context), Ripemd160(context) => Reset::reset(&mut **context), Sha1(context) => Reset::reset(&mut **context), Sha3_224(context) => Reset::reset(&mut **context), Sha3_256(context) => Reset::reset(&mut **context), Sha3_384(context) => Reset::reset(&mut **context), Sha3_512(context) => Reset::reset(&mut **context), Sha224(context) => Reset::reset(&mut **context), Sha256(context) => Reset::reset(&mut **context), Sha384(context) => Reset::reset(&mut **context), Sha512(context) => Reset::reset(&mut **context), Shake128(context) => Reset::reset(&mut **context), Shake256(context) => Reset::reset(&mut **context), Tiger(context) => Reset::reset(&mut **context), }; }
pub fn update(&mut self, data: &[u8]) { match self { Blake2b(context) => Digest::update(&mut **context, data), Blake2b256(context) => Digest::update(&mut **context, data), Blake2b384(context) => Digest::update(&mut **context, data), Blake2s(context) => Digest::update(&mut **context, data), Blake3(context) => Digest::update(&mut **context, data), Keccak224(context) => Digest::update(&mut **context, data), Keccak256(context) => Digest::update(&mut **context, data), Keccak384(context) => Digest::update(&mut **context, data), Keccak512(context) => Digest::update(&mut **context, data), Md4(context) => Digest::update(&mut **context, data), Md5(context) => Digest::update(&mut **context, data), Ripemd160(context) => Digest::update(&mut **context, data), Sha1(context) => Digest::update(&mut **context, data), Sha3_224(context) => Digest::update(&mut **context, data), Sha3_256(context) => Digest::update(&mut **context, data), Sha3_384(context) => Digest::update(&mut **context, data), Sha3_512(context) => Digest::update(&mut **context, data), Sha224(context) => Digest::update(&mut **context, data), Sha256(context) => Digest::update(&mut **context, data), Sha384(context) => Digest::update(&mut **context, data), Sha512(context) => Digest::update(&mut **context, data), Tiger(context) => Digest::update(&mut **context, data), Shake128(context) => (&mut **context).update(data), Shake256(context) => (&mut **context).update(data), }; }
pub fn digest_and_drop( self, length: Option<usize>, ) -> Result<Box<[u8]>, &'static str> { if let Some(length) = length { if !self.extendable() && length != self.output_length() { return Err( "non-default length specified for non-extendable algorithm", ); } }
let length = length.unwrap_or_else(|| self.output_length());
Ok(match self { Blake2b(context) => context.finalize(), Blake2b256(context) => context.finalize(), Blake2b384(context) => context.finalize(), Blake2s(context) => context.finalize(), Blake3(context) => context.finalize_boxed(length), Keccak224(context) => context.finalize(), Keccak256(context) => context.finalize(), Keccak384(context) => context.finalize(), Keccak512(context) => context.finalize(), Md4(context) => context.finalize(), Md5(context) => context.finalize(), Ripemd160(context) => context.finalize(), Sha1(context) => context.finalize(), Sha3_224(context) => context.finalize(), Sha3_256(context) => context.finalize(), Sha3_384(context) => context.finalize(), Sha3_512(context) => context.finalize(), Sha224(context) => context.finalize(), Sha256(context) => context.finalize(), Sha384(context) => context.finalize(), Sha512(context) => context.finalize(), Tiger(context) => context.finalize(), Shake128(context) => context.finalize_boxed(length), Shake256(context) => context.finalize_boxed(length), }) }
pub fn digest_and_reset( &mut self, length: Option<usize>, ) -> Result<Box<[u8]>, &'static str> { if let Some(length) = length { if !self.extendable() && length != self.output_length() { return Err( "non-default length specified for non-extendable algorithm", ); } }
let length = length.unwrap_or_else(|| self.output_length()); Ok(match self { Blake2b(context) => DynDigest::finalize_reset(context.as_mut()), Blake2b256(context) => DynDigest::finalize_reset(context.as_mut()), Blake2b384(context) => DynDigest::finalize_reset(context.as_mut()), Blake2s(context) => DynDigest::finalize_reset(context.as_mut()), Blake3(context) => { ExtendableOutputReset::finalize_boxed_reset(context.as_mut(), length) } Keccak224(context) => DynDigest::finalize_reset(context.as_mut()), Keccak256(context) => DynDigest::finalize_reset(context.as_mut()), Keccak384(context) => DynDigest::finalize_reset(context.as_mut()), Keccak512(context) => DynDigest::finalize_reset(context.as_mut()), Md4(context) => DynDigest::finalize_reset(context.as_mut()), Md5(context) => DynDigest::finalize_reset(context.as_mut()), Ripemd160(context) => DynDigest::finalize_reset(context.as_mut()), Sha1(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_224(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_256(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_384(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_512(context) => DynDigest::finalize_reset(context.as_mut()), Sha224(context) => DynDigest::finalize_reset(context.as_mut()), Sha256(context) => DynDigest::finalize_reset(context.as_mut()), Sha384(context) => DynDigest::finalize_reset(context.as_mut()), Sha512(context) => DynDigest::finalize_reset(context.as_mut()), Tiger(context) => DynDigest::finalize_reset(context.as_mut()), Shake128(context) => { ExtendableOutputReset::finalize_boxed_reset(context.as_mut(), length) } Shake256(context) => { ExtendableOutputReset::finalize_boxed_reset(context.as_mut(), length) } }) }
pub fn digest( &self, length: Option<usize>, ) -> Result<Box<[u8]>, &'static str> { self.clone().digest_and_drop(length) }}