|
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