1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::*;
pub const BYTES_MIN: usize =
libsodium_sys::crypto_generichash_BYTES_MIN as usize;
pub const BYTES_MAX: usize =
libsodium_sys::crypto_generichash_BYTES_MAX as usize;
pub const KEYBYTES_MIN: usize =
libsodium_sys::crypto_generichash_BYTES_MIN as usize;
pub const KEYBYTES_MAX: usize =
libsodium_sys::crypto_generichash_BYTES_MAX as usize;
async fn hash_inner<H, M, K>(
hash: H,
message: M,
key: Option<K>,
) -> SodokenResult<()>
where
H: Into<BufWrite> + 'static + Send,
M: Into<BufRead> + 'static + Send,
K: Into<BufRead> + 'static + Send,
{
let hash = hash.into();
let message = message.into();
const BLOCKING_THRESHOLD: usize = 1024 * 50;
let len = message.len();
let exec_hash = move || {
let mut hash = hash.write_lock();
let message = message.read_lock();
match key {
Some(key) => {
let key = key.into();
let key = key.read_lock();
safe::sodium::crypto_generichash(
&mut hash,
&message,
Some(&key),
)
}
None => safe::sodium::crypto_generichash(&mut hash, &message, None),
}
};
if len <= BLOCKING_THRESHOLD {
return exec_hash();
}
tokio_exec_blocking(exec_hash).await
}
pub async fn hash_with_key<H, M, K>(
hash: H,
message: M,
key: K,
) -> SodokenResult<()>
where
H: Into<BufWrite> + 'static + Send,
M: Into<BufRead> + 'static + Send,
K: Into<BufRead> + 'static + Send,
{
hash_inner(hash, message, Some(key)).await
}
pub async fn hash<H, M>(hash: H, message: M) -> SodokenResult<()>
where
H: Into<BufWrite> + 'static + Send,
M: Into<BufRead> + 'static + Send,
{
hash_inner::<H, M, BufRead>(hash, message, None).await
}
#[cfg(test)]
mod tests {
use crate::*;
#[tokio::test(flavor = "multi_thread")]
async fn blake2b() -> SodokenResult<()> {
let msg = BufRead::new_no_lock(b"test message");
let hash = BufWrite::new_no_lock(hash::blake2b::BYTES_MIN);
hash::blake2b::hash(hash.clone(), msg.clone()).await?;
assert_eq!(
"[153, 12, 203, 148, 189, 196, 68, 143, 36, 38, 97, 11, 155, 176, 16, 230]",
format!("{:?}", &*hash.read_lock()),
);
Ok(())
}
}