| 
1 | 1 | #[cfg(feature = "alloc")]  | 
2 | 2 | use alloc::boxed::Box;  | 
 | 3 | +use const_default::ConstDefault;  | 
3 | 4 | 
 
  | 
 | 5 | +use core::marker::PhantomData;  | 
4 | 6 | use digest::{Digest, OutputSizeUser};  | 
5 |  | -use preinterpret::preinterpret;  | 
6 | 7 | use rustls::crypto::{self, hash};  | 
7 | 8 | 
 
  | 
8 |  | -macro_rules! impl_hash {  | 
9 |  | -    ($name:ident, $ty:ty, $algo:ty) => {  | 
10 |  | -        preinterpret! {  | 
11 |  | -            [!set! #hash_name = [!ident! Hash_ $name]]  | 
12 |  | -            [!set! #hash_content_name = [!ident! HashContent_ $name]]  | 
 | 9 | +/// Trait to provide hash algorithm for different hash types  | 
 | 10 | +pub trait HashAlgorithm {  | 
 | 11 | +    const ALGORITHM: hash::HashAlgorithm;  | 
 | 12 | +}  | 
 | 13 | + | 
 | 14 | +// Generic hash implementation  | 
 | 15 | +#[derive(ConstDefault)]  | 
 | 16 | +pub struct GenericHash<H> {  | 
 | 17 | +    _phantom: PhantomData<H>,  | 
 | 18 | +}  | 
 | 19 | + | 
 | 20 | +impl<H> hash::Hash for GenericHash<H>  | 
 | 21 | +where  | 
 | 22 | +    H: Digest + OutputSizeUser + Clone + Send + Sync + 'static + HashAlgorithm,  | 
 | 23 | +{  | 
 | 24 | +    fn start(&self) -> Box<dyn hash::Context> {  | 
 | 25 | +        Box::new(GenericHashContext(H::new()))  | 
 | 26 | +    }  | 
 | 27 | + | 
 | 28 | +    fn hash(&self, data: &[u8]) -> hash::Output {  | 
 | 29 | +        hash::Output::new(&H::digest(data)[..])  | 
 | 30 | +    }  | 
13 | 31 | 
 
  | 
14 |  | -            #[allow(non_camel_case_types)]  | 
15 |  | -            pub struct #hash_name;  | 
 | 32 | +    fn output_len(&self) -> usize {  | 
 | 33 | +        <H as OutputSizeUser>::output_size()  | 
 | 34 | +    }  | 
16 | 35 | 
 
  | 
17 |  | -            impl hash::Hash for #hash_name {  | 
18 |  | -                fn start(&self) -> Box<dyn hash::Context> {  | 
19 |  | -                    Box::new(#hash_content_name($ty::new()))  | 
20 |  | -                }  | 
 | 36 | +    fn algorithm(&self) -> hash::HashAlgorithm {  | 
 | 37 | +        H::ALGORITHM  | 
 | 38 | +    }  | 
 | 39 | +}  | 
21 | 40 | 
 
  | 
22 |  | -                fn hash(&self, data: &[u8]) -> hash::Output {  | 
23 |  | -                    hash::Output::new(&$ty::digest(data)[..])  | 
24 |  | -                }  | 
 | 41 | +// Implement HashAlgorithm trait for each hash type  | 
 | 42 | +#[cfg(feature = "hash-sha224")]  | 
 | 43 | +impl HashAlgorithm for ::sha2::Sha224 {  | 
 | 44 | +    const ALGORITHM: hash::HashAlgorithm = hash::HashAlgorithm::SHA224;  | 
 | 45 | +}  | 
 | 46 | + | 
 | 47 | +#[cfg(feature = "hash-sha256")]  | 
 | 48 | +impl HashAlgorithm for ::sha2::Sha256 {  | 
 | 49 | +    const ALGORITHM: hash::HashAlgorithm = hash::HashAlgorithm::SHA256;  | 
 | 50 | +}  | 
25 | 51 | 
 
  | 
26 |  | -                fn output_len(&self) -> usize {  | 
27 |  | -                    <$ty as OutputSizeUser>::output_size()  | 
28 |  | -                }  | 
 | 52 | +#[cfg(feature = "hash-sha384")]  | 
 | 53 | +impl HashAlgorithm for ::sha2::Sha384 {  | 
 | 54 | +    const ALGORITHM: hash::HashAlgorithm = hash::HashAlgorithm::SHA384;  | 
 | 55 | +}  | 
29 | 56 | 
 
  | 
30 |  | -                fn algorithm(&self) -> hash::HashAlgorithm {  | 
31 |  | -                    $algo  | 
32 |  | -                }  | 
33 |  | -            }  | 
 | 57 | +#[cfg(feature = "hash-sha512")]  | 
 | 58 | +impl HashAlgorithm for ::sha2::Sha512 {  | 
 | 59 | +    const ALGORITHM: hash::HashAlgorithm = hash::HashAlgorithm::SHA512;  | 
 | 60 | +}  | 
34 | 61 | 
 
  | 
35 |  | -            #[allow(non_camel_case_types)]  | 
36 |  | -            pub struct #hash_content_name($ty);  | 
 | 62 | +pub struct GenericHashContext<H>(H);  | 
37 | 63 | 
 
  | 
38 |  | -            impl hash::Context for #hash_content_name {  | 
39 |  | -                fn fork_finish(&self) -> hash::Output {  | 
40 |  | -                    hash::Output::new(&self.0.clone().finalize()[..])  | 
41 |  | -                }  | 
 | 64 | +impl<H> hash::Context for GenericHashContext<H>  | 
 | 65 | +where  | 
 | 66 | +    H: Digest + Clone + Send + Sync + 'static,  | 
 | 67 | +{  | 
 | 68 | +    fn fork_finish(&self) -> hash::Output {  | 
 | 69 | +        hash::Output::new(&self.0.clone().finalize()[..])  | 
 | 70 | +    }  | 
42 | 71 | 
 
  | 
43 |  | -                fn fork(&self) -> Box<dyn hash::Context> {  | 
44 |  | -                    Box::new(#hash_content_name(self.0.clone()))  | 
45 |  | -                }  | 
 | 72 | +    fn fork(&self) -> Box<dyn hash::Context> {  | 
 | 73 | +        Box::new(GenericHashContext(self.0.clone()))  | 
 | 74 | +    }  | 
46 | 75 | 
 
  | 
47 |  | -                fn finish(self: Box<Self>) -> hash::Output {  | 
48 |  | -                    hash::Output::new(&self.0.finalize()[..])  | 
49 |  | -                }  | 
 | 76 | +    fn finish(self: Box<Self>) -> hash::Output {  | 
 | 77 | +        hash::Output::new(&self.0.finalize()[..])  | 
 | 78 | +    }  | 
50 | 79 | 
 
  | 
51 |  | -                fn update(&mut self, data: &[u8]) {  | 
52 |  | -                    self.0.update(data);  | 
53 |  | -                }  | 
54 |  | -            }  | 
 | 80 | +    fn update(&mut self, data: &[u8]) {  | 
 | 81 | +        self.0.update(data);  | 
 | 82 | +    }  | 
 | 83 | +}  | 
55 | 84 | 
 
  | 
56 |  | -            pub const $name: &dyn crypto::hash::Hash = &#hash_name;  | 
57 |  | -        }  | 
 | 85 | +/// Macro to generate hash constants  | 
 | 86 | +macro_rules! hash_const {  | 
 | 87 | +    ($name:ident, $hash:ty, $feature:literal) => {  | 
 | 88 | +        #[cfg(feature = $feature)]  | 
 | 89 | +        pub const $name: &dyn crypto::hash::Hash = &GenericHash::<$hash>::DEFAULT;  | 
58 | 90 |     };  | 
59 | 91 | }  | 
60 | 92 | 
 
  | 
61 |  | -#[cfg(feature = "hash-sha224")]  | 
62 |  | -impl_hash! {SHA224, ::sha2::Sha224, hash::HashAlgorithm::SHA224}  | 
63 |  | -#[cfg(feature = "hash-sha256")]  | 
64 |  | -impl_hash! {SHA256, ::sha2::Sha256, hash::HashAlgorithm::SHA256}  | 
65 |  | -#[cfg(feature = "hash-sha384")]  | 
66 |  | -impl_hash! {SHA384, ::sha2::Sha384, hash::HashAlgorithm::SHA384}  | 
67 |  | -#[cfg(feature = "hash-sha512")]  | 
68 |  | -impl_hash! {SHA512, ::sha2::Sha512, hash::HashAlgorithm::SHA512}  | 
 | 93 | +// Generate hash constants using macro  | 
 | 94 | +hash_const!(SHA224, ::sha2::Sha224, "hash-sha224");  | 
 | 95 | +hash_const!(SHA256, ::sha2::Sha256, "hash-sha256");  | 
 | 96 | +hash_const!(SHA384, ::sha2::Sha384, "hash-sha384");  | 
 | 97 | +hash_const!(SHA512, ::sha2::Sha512, "hash-sha512");  | 
0 commit comments