prople_crypto/keysecure/
mod.rs1use rst_common::standard::serde::{self, Deserialize, Serialize};
6use rst_common::standard::serde_json;
7use rst_common::standard::uuid::Uuid;
8use rst_common::with_cryptography::hex;
9
10pub mod builder;
11pub mod objects;
12pub mod types;
13
14use crate::aead::{Key, KeyEncryption, KeyNonce, MessageCipher, MessagePlain, AEAD};
15use crate::passphrase::kdf_params::KdfParams as PassphraseKDFParams;
16use crate::passphrase::types::SaltBytes;
17use crate::passphrase::Passphrase;
18
19use objects::*;
20use types::{errors::*, ContextOptions};
21
22#[derive(Debug, Serialize, Deserialize, Clone)]
25#[serde(crate = "self::serde")]
26pub struct KeySecure {
27 pub id: Uuid,
28 pub context: ContextOptions,
29 pub crypto: KeySecureCrypto,
30}
31
32impl KeySecure {
33 pub fn new(context: ContextOptions, crypto: KeySecureCrypto) -> Self {
34 let id = Uuid::new_v4();
35 Self {
36 id,
37 context,
38 crypto,
39 }
40 }
41
42 pub fn to_json(&self) -> Result<String, CommonError> {
43 serde_json::to_string(self).map_err(|err| CommonError::BuildJSONError(err.to_string()))
44 }
45
46 pub fn decrypt(&self, password: String) -> Result<MessagePlain, KeySecureError> {
47 let encrypted_data = self.crypto.cipher_text.to_owned();
48 let encrypted_data_decoded = hex::decode(encrypted_data)
49 .map_err(|err| KeySecureError::DecryptError(err.to_string()))?;
50
51 let kdf_params = self.crypto.kdf_params.to_owned();
52 let passphrase_kdf_params = PassphraseKDFParams {
53 m_cost: kdf_params.params.m_cost,
54 p_cost: kdf_params.params.p_cost,
55 t_cost: kdf_params.params.t_cost,
56 output_len: kdf_params.params.output_len,
57 };
58
59 let kdf = Passphrase::new(passphrase_kdf_params);
60 let salt_vec = kdf_params.salt.as_bytes().to_vec();
61 let salt_bytes = SaltBytes::from(salt_vec);
62 let password_hash = kdf
63 .hash(password, salt_bytes)
64 .map_err(|err| KeySecureError::DecryptError(err.to_string()))?;
65
66 let nonce_str = self.crypto.cipher_params.nonce.to_owned();
67 let nonce_str_decoded =
68 hex::decode(nonce_str).map_err(|err| KeySecureError::DecryptError(err.to_string()))?;
69
70 let nonce_value: [u8; 24] = nonce_str_decoded
71 .clone()
72 .try_into()
73 .map_err(|_| KeySecureError::DecryptError("unable to decode nonce".to_string()))?;
74
75 let key = Key::new(
76 KeyEncryption::from(password_hash),
77 KeyNonce::from(nonce_value),
78 );
79 let decrypted = AEAD::decrypt(&key, &MessageCipher::from(encrypted_data_decoded))
80 .map_err(|err| KeySecureError::DecryptError(err.to_string()))?;
81
82 Ok(decrypted)
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 use crate::aead::{Key, KeyEncryption, KeyNonce, AEAD};
91 use crate::ecdh::keypair::KeyPair;
92 use crate::passphrase::kdf_params::KdfParams as PassphraseKDFParams;
93 use crate::passphrase::salt::Salt;
94 use crate::passphrase::Passphrase;
95 use crate::types::{BytesValue, VectorValue};
96 use types::ContextOptions;
97
98 use rst_common::with_cryptography::hex;
99
100 fn generate_alice_key() -> [u8; 32] {
101 let keypair_alice = KeyPair::generate();
102 let keypair_bob = KeyPair::generate();
103
104 let pubkey_bob = keypair_bob.pub_key();
105 let public_bob_hex = pubkey_bob.to_hex();
106
107 let secret_alice = keypair_alice.secret(public_bob_hex);
108 let shared_secret_alice_blake3 = secret_alice.to_blake3();
109 let shared_secret_alice_value: &Result<[u8; 32], _> =
110 &shared_secret_alice_blake3.unwrap().bytes()[..32].try_into();
111
112 shared_secret_alice_value.unwrap()
113 }
114
115 fn generate_ecdh_keysecure() -> (KeySecure, [u8; 32]) {
116 let alice_key = generate_alice_key();
117
118 let nonce = AEAD::nonce();
119 let nonce_value: Result<[u8; 24], _> = nonce.vec().clone().try_into();
120
121 let salt = Salt::generate();
122 let salt_string = Salt::from_vec(salt.clone());
123
124 let kdf_params = PassphraseKDFParams::default();
125 let kdf = Passphrase::new(kdf_params.clone());
126
127 let try_hash = kdf.hash(String::from("password"), salt.clone());
128 let key = Key::new(
129 KeyEncryption::from(try_hash.unwrap()),
130 KeyNonce::from(nonce_value.unwrap()),
131 );
132 let encrypted = AEAD::encrypt(&key, &MessagePlain::from(alice_key.to_vec()));
133
134 let encrypted_hex = hex::encode(encrypted.unwrap().vec());
135 let crypto_nonce_hex = hex::encode(nonce.vec().clone());
136 let keysecure_kdf_params = KdfParams::new(kdf_params, salt_string.unwrap());
137 let crypto = KeySecureCrypto::new(crypto_nonce_hex, encrypted_hex, keysecure_kdf_params);
138
139 (KeySecure::new(ContextOptions::X25519, crypto), alice_key)
140 }
141
142 #[test]
143 fn test_generate_json() {
144 let keysecure = generate_ecdh_keysecure();
145 let keysecure_json = keysecure.0.to_json();
146 assert!(!keysecure_json.is_err());
147 }
148
149 #[test]
150 fn test_decrypt_keysecure() {
151 let keysecure = generate_ecdh_keysecure();
152 let alice_key = keysecure.1;
153 let decrypted = keysecure.0.decrypt(String::from("password"));
154 assert!(!decrypted.is_err());
155 assert_eq!(alice_key.to_vec(), decrypted.unwrap().vec())
156 }
157
158 #[test]
159 fn test_decrypt_keysecure_check_bytes() {
160 let keysecure1 = generate_ecdh_keysecure();
161 let keysecure2 = generate_ecdh_keysecure();
162
163 let alice_key1 = keysecure1.1;
164 let alice_key2 = keysecure2.1;
165 assert_ne!(alice_key1.to_vec(), alice_key2.to_vec());
166
167 let decrypted1 = keysecure1.0.decrypt(String::from("password"));
168 assert!(!decrypted1.is_err());
169
170 let decrypted_value1 = decrypted1.unwrap();
171 assert_eq!(alice_key1.to_vec(), decrypted_value1.vec().clone());
172 assert_ne!(alice_key2.to_vec(), decrypted_value1.vec().clone());
173
174 let decrypted2 = keysecure2.0.decrypt(String::from("password"));
175 assert!(!decrypted2.is_err());
176
177 let decrypted_value2 = decrypted2.unwrap();
178 assert_eq!(alice_key2.to_vec(), decrypted_value2.vec().clone());
179 assert_ne!(alice_key1.to_vec(), decrypted_value2.vec().clone());
180 }
181
182 #[test]
183 fn test_decrypt_keysecure_invalid_password() {
184 let keysecure = generate_ecdh_keysecure();
185 let decrypted = keysecure.0.decrypt(String::from("invalid"));
186 assert!(decrypted.is_err());
187 }
188}