1#![no_std]
16
17use core::{
18 hash::{Hash, Hasher},
19 convert::TryFrom,
20};
21
22#[cfg(feature = "hash-md5")]
29pub fn md5_hash<H: Hash>(data: &H) -> [u8; 16] {
30 let mut hasher = md5_hasher::Md5Hasher::new();
31 data.hash(&mut hasher);
32 hasher.digest()
33}
34
35#[cfg(feature = "hash-md5")]
36#[doc(opaque)]
37pub use md5_hasher::Md5Hasher;
38
39#[cfg(feature = "hash-sha256")]
41pub fn sha256_hash<H: Hash>(data: &H) -> [u8; 32] {
42 let mut hasher = sha256_hasher::Sha256Hasher::new();
43 data.hash(&mut hasher);
44 hasher.finalize()
45}
46
47#[cfg(feature = "hash-sha256")]
48#[doc(opaque)]
49pub use sha256_hasher::Sha256Hasher;
50
51#[cfg(feature = "hash-sha512")]
53pub fn sha512_hash<H: Hash>(data: &H) -> [u8; 64] {
54 let mut hasher = sha512_hasher::Sha512Hasher::new();
55 data.hash(&mut hasher);
56 hasher.finalize()
57}
58
59#[cfg(feature = "hash-sha512")]
60#[doc(opaque)]
61pub use sha512_hasher::Sha512Hasher;
62
63fn bytes_xor_u64(slice: &[u8]) -> u64 {
65 assert_eq!(slice.len() % 8, 0);
66
67 let mut accum: u64 = 0;
68 for i in 0..slice.len() / 8 {
69 let subslice = &slice[i * 8..(i + 1) * 8];
70 let subslice = <[u8; 8]>::try_from(subslice).unwrap();
71 accum ^= u64::from_ne_bytes(subslice);
72 }
73
74 accum
75}
76
77#[cfg(feature = "hash-md5")]
78mod md5_hasher {
79 extern crate md5;
80 use super::*;
81
82 #[derive(Clone)]
84 pub struct Md5Hasher(md5::Context);
85
86 impl Md5Hasher {
87 pub fn new() -> Self {
88 Md5Hasher(md5::Context::new())
89 }
90
91 pub fn digest(&self) -> [u8; 16] {
93 self.0.clone().compute().into()
94 }
95 }
96
97 impl Hasher for Md5Hasher {
98 fn finish(&self) -> u64 {
99 bytes_xor_u64(&self.digest())
100 }
101
102 fn write(&mut self, bytes: &[u8]) {
103 self.0.consume(bytes);
104 }
105 }
106}
107
108#[cfg(feature = "hash-sha256")]
109mod sha256_hasher {
110 extern crate hmac_sha256;
111
112 use super::*;
113 use hmac_sha256 as sha256;
114
115 #[derive(Copy, Clone)]
117 pub struct Sha256Hasher(sha256::Hash);
118
119 impl Sha256Hasher {
120 pub fn new() -> Self {
121 Sha256Hasher(sha256::Hash::new())
122 }
123
124 pub fn finalize(&self) -> [u8; 32] {
126 self.0.finalize()
127 }
128 }
129
130 impl Hasher for Sha256Hasher {
131 fn finish(&self) -> u64 {
132 bytes_xor_u64(&self.finalize())
133 }
134
135 fn write(&mut self, bytes: &[u8]) {
136 self.0.update(bytes);
137 }
138 }
139}
140
141#[cfg(feature = "hash-sha512")]
142mod sha512_hasher {
143 extern crate hmac_sha512;
144
145 use super::*;
146 use hmac_sha512 as sha512;
147
148 #[derive(Copy, Clone)]
150 pub struct Sha512Hasher(sha512::Hash);
151
152 impl Sha512Hasher {
153 pub fn new() -> Self {
154 Sha512Hasher(sha512::Hash::new())
155 }
156
157 pub fn finalize(&self) -> [u8; 64] {
159 self.0.finalize()
160 }
161 }
162
163 impl Hasher for Sha512Hasher {
164 fn finish(&self) -> u64 {
165 bytes_xor_u64(&self.finalize())
166 }
167
168 fn write(&mut self, bytes: &[u8]) {
169 self.0.update(bytes);
170 }
171 }
172}
173