1use alloc::vec::Vec;
2
3use sha2::{Digest, Sha256};
4
5use crate::cryptomat::{
6 ClientRandomValue,
7 CryptoAlg,
8 DeriveAuthKeyForAuth,
9 DeriveMasterKeyForAuth,
10 HashedAuthenticationKey,
11 Pk,
12 PwHash,
13 SignK,
14 SignKeyComposer,
15 SignKeyPair,
16 Sk,
17 SkComposer,
18 StaticKeyPair,
19 SymKeyGen,
20 VerifyK,
21};
22use crate::error::Error;
23
24pub struct RegisterOutPut<P: Pk, V: VerifyK, CRV: ClientRandomValue, HAK: HashedAuthenticationKey>
25{
26 pub master_key_alg: &'static str,
28
29 pub client_random_value: CRV,
31 pub hashed_authentication_key_bytes: HAK,
32 pub encrypted_master_key: Vec<u8>,
33 pub encrypted_master_key_alg: &'static str,
34 pub derived_alg: &'static str,
35
36 pub public_key: P,
38 pub encrypted_private_key: Vec<u8>,
39 pub keypair_encrypt_alg: &'static str,
40 pub verify_key: V,
41 pub encrypted_sign_key: Vec<u8>,
42 pub keypair_sign_alg: &'static str,
43}
44
45pub struct LoginDoneOutput<S: Sk, Si: SignK>
46{
47 pub private_key: S,
48 pub sign_key: Si,
49}
50
51pub struct ChangePasswordOutput<CRV: ClientRandomValue, HAK: HashedAuthenticationKey, DAK: DeriveAuthKeyForAuth>
52{
53 pub client_random_value: CRV,
54 pub hashed_authentication_key_bytes: HAK,
55 pub encrypted_master_key: Vec<u8>,
56 pub encrypted_master_key_alg: &'static str,
57 pub derived_alg: &'static str,
58 pub old_auth_key: DAK,
59}
60
61pub struct ResetPasswordOutput<CRV: ClientRandomValue, HAK: HashedAuthenticationKey>
62{
63 pub master_key_alg: &'static str,
64 pub client_random_value: CRV,
65 pub hashed_authentication_key_bytes: HAK,
66 pub encrypted_master_key: Vec<u8>,
67 pub encrypted_master_key_alg: &'static str,
68 pub derived_alg: &'static str,
69 pub encrypted_private_key: Vec<u8>,
70 pub encrypted_sign_key: Vec<u8>,
71}
72
73pub struct PrepareLoginOutput<DMK: DeriveMasterKeyForAuth, DAK: DeriveAuthKeyForAuth>
74{
75 pub master_key_encryption_key: DMK,
76 pub auth_key: DAK,
77}
78
79#[allow(clippy::type_complexity)]
100pub fn register<S: SymKeyGen, St: StaticKeyPair, Sign: SignKeyPair, H: PwHash>(
101 password: &str,
102) -> Result<RegisterOutPut<St::PublicKey, Sign::VerifyKey, H::CRV, H::HAK>, Error>
103{
104 let master_key = S::generate()?;
106
107 let (sk, public_key) = St::generate_static_keypair()?;
109
110 let (sign_k, verify_key) = Sign::generate_key_pair()?;
112
113 let encrypted_private_key = sk.encrypt_by_master_key(&master_key)?;
114 let encrypted_sign_key = sign_k.encrypt_by_master_key(&master_key)?;
115
116 let (client_random_value, hashed_authentication_key_bytes, encrypted_master_key, encrypted_master_key_alg) =
117 H::derived_keys_from_password(password.as_bytes(), &master_key, None)?;
118
119 Ok(RegisterOutPut {
120 master_key_alg: master_key.get_alg_str(),
121 derived_alg: client_random_value.get_alg_str(),
122 client_random_value,
123 hashed_authentication_key_bytes,
124 encrypted_master_key,
125 encrypted_master_key_alg,
126 encrypted_sign_key,
127 verify_key,
128 keypair_sign_alg: sign_k.get_alg_str(),
129 encrypted_private_key,
130 public_key,
131 keypair_encrypt_alg: sk.get_alg_str(),
132 })
133}
134
135pub fn prepare_login<H: PwHash>(password: &str, salt: &[u8], derived_encryption_key_alg: &str) -> Result<PrepareLoginOutput<H::DMK, H::DAK>, Error>
141{
142 let (master_key_encryption_key, auth_key) = H::derive_keys_for_auth(password.as_bytes(), salt, derived_encryption_key_alg)?;
143
144 Ok(PrepareLoginOutput {
145 master_key_encryption_key,
146 auth_key,
147 })
148}
149
150pub fn done_login<SkC: SkComposer, SiC: SignKeyComposer>(
156 derived_encryption_key: &impl DeriveMasterKeyForAuth, encrypted_master_key: &[u8], encrypted_private_key: &[u8],
159 keypair_encrypt_alg: &str,
160 encrypted_sign_key: &[u8],
161 keypair_sign_alg: &str,
162) -> Result<LoginDoneOutput<SkC::SecretKey, SiC::Key>, Error>
163{
164 let master_key = derived_encryption_key.get_master_key(encrypted_master_key)?;
166
167 let private_key = SkC::decrypt_by_master_key(&master_key, encrypted_private_key, keypair_encrypt_alg)?;
169 let sign_key = SiC::decrypt_by_master_key(&master_key, encrypted_sign_key, keypair_sign_alg)?;
170
171 Ok(LoginDoneOutput {
172 private_key,
173 sign_key,
174 })
175}
176
177#[allow(clippy::type_complexity)]
195pub fn change_password<H: PwHash>(
196 old_pw: &str,
197 new_pw: &str,
198 old_salt: &[u8],
199 encrypted_master_key: &[u8],
200 derived_encryption_key_alg: &str,
201) -> Result<ChangePasswordOutput<H::CRV, H::HAK, H::DAK>, Error>
202{
203 let prepare_login_output = prepare_login::<H>(old_pw, old_salt, derived_encryption_key_alg)?;
206
207 let master_key = prepare_login_output
209 .master_key_encryption_key
210 .get_master_key(encrypted_master_key)?;
211
212 let (client_random_value, hashed_authentication_key_bytes, encrypted_master_key, encrypted_master_key_alg) =
215 H::derived_keys_from_password(new_pw.as_bytes(), &master_key, Some(derived_encryption_key_alg))?;
216
217 Ok(ChangePasswordOutput {
218 derived_alg: client_random_value.get_alg_str(),
219 client_random_value,
220 hashed_authentication_key_bytes,
221 encrypted_master_key,
222 encrypted_master_key_alg,
223 old_auth_key: prepare_login_output.auth_key,
224 })
225}
226
227pub fn password_reset<S: SymKeyGen, H: PwHash>(
241 new_pw: &str,
242 decrypted_private_key: &impl Sk,
243 decrypted_sign_key: &impl SignK,
244) -> Result<ResetPasswordOutput<H::CRV, H::HAK>, Error>
245{
246 let master_key = S::generate()?;
248
249 let encrypted_private_key = decrypted_private_key.encrypt_by_master_key(&master_key)?;
251 let encrypted_sign_key = decrypted_sign_key.encrypt_by_master_key(&master_key)?;
252
253 let (client_random_value, hashed_authentication_key_bytes, encrypted_master_key, encrypted_master_key_alg) =
255 H::derived_keys_from_password(new_pw.as_bytes(), &master_key, None)?;
256
257 Ok(ResetPasswordOutput {
258 master_key_alg: master_key.get_alg_str(),
259 derived_alg: client_random_value.get_alg_str(),
260 client_random_value,
261 hashed_authentication_key_bytes,
262 encrypted_master_key,
263 encrypted_master_key_alg,
264 encrypted_private_key,
265 encrypted_sign_key,
266 })
267}
268
269pub fn safety_number<Vk: VerifyK>(
278 user_1_verify_key: &Vk,
279 user_1_user_info: &str,
280 user_2_verify_key: Option<&Vk>,
281 user_2_user_info: Option<&str>,
282) -> Vec<u8>
283{
284 let mut hasher = Sha256::new();
285
286 user_1_verify_key.create_hash(&mut hasher);
287
288 hasher.update(user_1_user_info.as_bytes());
289
290 if let (Some(u_2), Some(u_2_i)) = (user_2_verify_key, user_2_user_info) {
291 u_2.create_hash(&mut hasher);
292
293 hasher.update(u_2_i.as_bytes());
294 }
295
296 let number_bytes = hasher.finalize();
297
298 number_bytes.to_vec()
299}