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
120
121
122
123
124
125
126
use crate::*;
pub const BYTES_MIN: usize =
libsodium_sys::crypto_pwhash_argon2id_BYTES_MIN as usize;
pub const SALTBYTES: usize =
libsodium_sys::crypto_pwhash_argon2id_SALTBYTES as usize;
pub const PASSWD_MIN: usize =
libsodium_sys::crypto_pwhash_argon2id_PASSWD_MIN as usize;
pub const PASSWD_MAX: usize =
libsodium_sys::crypto_pwhash_argon2id_PASSWD_MAX as usize;
pub const OPSLIMIT_MIN: u32 =
libsodium_sys::crypto_pwhash_argon2id_OPSLIMIT_MIN as u32;
pub const OPSLIMIT_INTERACTIVE: u32 =
libsodium_sys::crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE as u32;
pub const OPSLIMIT_MODERATE: u32 =
libsodium_sys::crypto_pwhash_argon2id_OPSLIMIT_MODERATE as u32;
pub const OPSLIMIT_SENSITIVE: u32 =
libsodium_sys::crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE as u32;
pub const OPSLIMIT_MAX: u32 =
libsodium_sys::crypto_pwhash_argon2id_OPSLIMIT_MAX as u32;
pub const MEMLIMIT_MIN: u32 =
libsodium_sys::crypto_pwhash_argon2id_MEMLIMIT_MIN as u32;
pub const MEMLIMIT_INTERACTIVE: u32 =
libsodium_sys::crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE as u32;
pub const MEMLIMIT_MODERATE: u32 =
libsodium_sys::crypto_pwhash_argon2id_MEMLIMIT_MODERATE as u32;
pub const MEMLIMIT_SENSITIVE: u32 =
libsodium_sys::crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE as u32;
pub async fn hash<H, P, S>(
hash: H,
passphrase: P,
salt: S,
ops_limit: u32,
mem_limit: u32,
) -> SodokenResult<()>
where
H: Into<BufWrite> + 'static + Send,
P: Into<BufRead> + 'static + Send,
S: Into<BufReadSized<SALTBYTES>> + 'static + Send,
{
let hash = hash.into();
let passphrase = passphrase.into();
let salt = salt.into();
tokio_exec_blocking(move || {
let tmp_hash = BufWrite::new_mem_locked(hash.len())?;
let tmp_passphrase = BufWrite::deep_clone_mem_locked(passphrase)?;
let tmp_salt = BufWriteSized::deep_clone_no_lock(salt);
let mut tmp_hash_lock = tmp_hash.write_lock();
let tmp_passphrase_lock = tmp_passphrase.read_lock();
let tmp_salt_lock = tmp_salt.read_lock_sized();
safe::sodium::crypto_pwhash_argon2id(
&mut tmp_hash_lock,
&tmp_passphrase_lock,
&tmp_salt_lock,
ops_limit,
mem_limit,
)?;
hash.write_lock().copy_from_slice(&tmp_hash_lock);
Ok(())
})
.await
}
#[cfg(test)]
mod tests {
use crate::*;
#[tokio::test(flavor = "multi_thread")]
async fn argon2id() -> SodokenResult<()> {
let pass = BufRead::new_no_lock(b"my passphrase");
let salt: BufReadSized<{ hash::argon2id::SALTBYTES }> =
BufReadSized::new_no_lock([0xdb; hash::argon2id::SALTBYTES]);
let hash = BufWrite::new_no_lock(hash::argon2id::BYTES_MIN);
hash::argon2id::hash(
hash.clone(),
pass,
salt,
hash::argon2id::OPSLIMIT_INTERACTIVE,
hash::argon2id::MEMLIMIT_INTERACTIVE,
)
.await?;
assert_eq!(
"[236, 88, 226, 164, 99, 188, 201, 149, 83, 218, 26, 28, 193, 215, 226, 72]",
format!("{:?}", &*hash.read_lock()),
);
Ok(())
}
}