1use std::str::FromStr;
2
3use bitwarden_core::key_management::{KeyIds, SymmetricKeyId};
4#[allow(deprecated)]
5use bitwarden_crypto::dangerous_derive_kdf_material;
6use bitwarden_crypto::{
7 AsymmetricCryptoKey, AsymmetricPublicCryptoKey, BitwardenLegacyKeyBytes, CoseKeyBytes,
8 CoseSerializable, CoseSign1Bytes, CryptoError, Decryptable, EncString, Kdf, KeyDecryptable,
9 KeyEncryptable, KeyStore, MasterKey, OctetStreamBytes, Pkcs8PrivateKeyBytes,
10 PrimitiveEncryptable, SignatureAlgorithm, SignedPublicKey, SigningKey, SpkiPublicKeyBytes,
11 SymmetricCryptoKey, UnsignedSharedKey, VerifyingKey,
12};
13use wasm_bindgen::prelude::*;
14
15#[wasm_bindgen]
20pub struct PureCrypto {}
21
22#[wasm_bindgen]
24impl PureCrypto {
25 pub fn symmetric_decrypt(enc_string: String, key: Vec<u8>) -> Result<String, CryptoError> {
28 Self::symmetric_decrypt_string(enc_string, key)
29 }
30
31 pub fn symmetric_decrypt_string(
32 enc_string: String,
33 key: Vec<u8>,
34 ) -> Result<String, CryptoError> {
35 let key = &BitwardenLegacyKeyBytes::from(key);
36 EncString::from_str(&enc_string)?.decrypt_with_key(&SymmetricCryptoKey::try_from(key)?)
37 }
38
39 pub fn symmetric_decrypt_bytes(
40 enc_string: String,
41 key: Vec<u8>,
42 ) -> Result<Vec<u8>, CryptoError> {
43 let key = &BitwardenLegacyKeyBytes::from(key);
44 EncString::from_str(&enc_string)?.decrypt_with_key(&SymmetricCryptoKey::try_from(key)?)
45 }
46
47 pub fn symmetric_decrypt_array_buffer(
50 enc_bytes: Vec<u8>,
51 key: Vec<u8>,
52 ) -> Result<Vec<u8>, CryptoError> {
53 Self::symmetric_decrypt_filedata(enc_bytes, key)
54 }
55
56 pub fn symmetric_decrypt_filedata(
57 enc_bytes: Vec<u8>,
58 key: Vec<u8>,
59 ) -> Result<Vec<u8>, CryptoError> {
60 let key = &BitwardenLegacyKeyBytes::from(key);
61 EncString::from_buffer(&enc_bytes)?.decrypt_with_key(&SymmetricCryptoKey::try_from(key)?)
62 }
63
64 pub fn symmetric_encrypt_string(plain: String, key: Vec<u8>) -> Result<String, CryptoError> {
65 let key = &BitwardenLegacyKeyBytes::from(key);
66 plain
67 .encrypt_with_key(&SymmetricCryptoKey::try_from(key)?)
68 .map(|enc| enc.to_string())
69 }
70
71 pub fn symmetric_encrypt_bytes(plain: Vec<u8>, key: Vec<u8>) -> Result<String, CryptoError> {
73 let key = &BitwardenLegacyKeyBytes::from(key);
74 OctetStreamBytes::from(plain)
75 .encrypt_with_key(&SymmetricCryptoKey::try_from(key)?)
76 .map(|enc| enc.to_string())
77 }
78
79 pub fn symmetric_encrypt_filedata(
80 plain: Vec<u8>,
81 key: Vec<u8>,
82 ) -> Result<Vec<u8>, CryptoError> {
83 let key = &BitwardenLegacyKeyBytes::from(key);
84 OctetStreamBytes::from(plain)
85 .encrypt_with_key(&SymmetricCryptoKey::try_from(key)?)?
86 .to_buffer()
87 }
88
89 pub fn decrypt_user_key_with_master_password(
90 encrypted_user_key: String,
91 master_password: String,
92 email: String,
93 kdf: Kdf,
94 ) -> Result<Vec<u8>, CryptoError> {
95 let master_key = MasterKey::derive(master_password.as_str(), email.as_str(), &kdf)?;
96 let encrypted_user_key = EncString::from_str(&encrypted_user_key)?;
97 let result = master_key
98 .decrypt_user_key(encrypted_user_key)
99 .map_err(|_| CryptoError::InvalidKey)?;
100 Ok(result.to_encoded().to_vec())
101 }
102
103 pub fn encrypt_user_key_with_master_password(
104 user_key: Vec<u8>,
105 master_password: String,
106 email: String,
107 kdf: Kdf,
108 ) -> Result<String, CryptoError> {
109 let master_key = MasterKey::derive(master_password.as_str(), email.as_str(), &kdf)?;
110 let user_key = &BitwardenLegacyKeyBytes::from(user_key);
111 let user_key = SymmetricCryptoKey::try_from(user_key)?;
112 let result = master_key.encrypt_user_key(&user_key)?;
113 Ok(result.to_string())
114 }
115
116 pub fn make_user_key_aes256_cbc_hmac() -> Vec<u8> {
117 SymmetricCryptoKey::make_aes256_cbc_hmac_key()
118 .to_encoded()
119 .to_vec()
120 }
121
122 pub fn make_user_key_xchacha20_poly1305() -> Vec<u8> {
123 SymmetricCryptoKey::make_xchacha20_poly1305_key()
124 .to_encoded()
125 .to_vec()
126 }
127
128 pub fn wrap_symmetric_key(
131 key_to_be_wrapped: Vec<u8>,
132 wrapping_key: Vec<u8>,
133 ) -> Result<String, CryptoError> {
134 let tmp_store: KeyStore<KeyIds> = KeyStore::default();
135 let mut context = tmp_store.context();
136 let wrapping_key =
137 SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(wrapping_key))?;
138 #[allow(deprecated)]
139 context.set_symmetric_key(SymmetricKeyId::Local("wrapping_key"), wrapping_key)?;
140 let key_to_be_wrapped =
141 SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(key_to_be_wrapped))?;
142 #[allow(deprecated)]
143 context.set_symmetric_key(SymmetricKeyId::Local("key_to_wrap"), key_to_be_wrapped)?;
144 Ok(context
146 .wrap_symmetric_key(
147 SymmetricKeyId::Local("wrapping_key"),
148 SymmetricKeyId::Local("key_to_wrap"),
149 )?
150 .to_string())
151 }
152
153 pub fn unwrap_symmetric_key(
156 wrapped_key: String,
157 wrapping_key: Vec<u8>,
158 ) -> Result<Vec<u8>, CryptoError> {
159 let tmp_store: KeyStore<KeyIds> = KeyStore::default();
160 let mut context = tmp_store.context();
161 let wrapping_key =
162 SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(wrapping_key))?;
163 #[allow(deprecated)]
164 context.set_symmetric_key(SymmetricKeyId::Local("wrapping_key"), wrapping_key)?;
165 context.unwrap_symmetric_key(
167 SymmetricKeyId::Local("wrapping_key"),
168 SymmetricKeyId::Local("wrapped_key"),
169 &EncString::from_str(wrapped_key.as_str())?,
170 )?;
171 #[allow(deprecated)]
172 let key = context.dangerous_get_symmetric_key(SymmetricKeyId::Local("wrapped_key"))?;
173 Ok(key.to_encoded().to_vec())
174 }
175
176 pub fn wrap_encapsulation_key(
182 encapsulation_key: Vec<u8>,
183 wrapping_key: Vec<u8>,
184 ) -> Result<String, CryptoError> {
185 let tmp_store: KeyStore<KeyIds> = KeyStore::default();
186 let mut context = tmp_store.context();
187 #[allow(deprecated)]
188 context.set_symmetric_key(
189 SymmetricKeyId::Local("wrapping_key"),
190 SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(wrapping_key))?,
191 )?;
192 Ok(SpkiPublicKeyBytes::from(encapsulation_key)
193 .encrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))?
194 .to_string())
195 }
196
197 pub fn unwrap_encapsulation_key(
200 wrapped_key: String,
201 wrapping_key: Vec<u8>,
202 ) -> Result<Vec<u8>, CryptoError> {
203 let tmp_store: KeyStore<KeyIds> = KeyStore::default();
204 let mut context = tmp_store.context();
205 #[allow(deprecated)]
206 context.set_symmetric_key(
207 SymmetricKeyId::Local("wrapping_key"),
208 SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(wrapping_key))?,
209 )?;
210 EncString::from_str(wrapped_key.as_str())?
211 .decrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))
212 }
213
214 pub fn wrap_decapsulation_key(
217 decapsulation_key: Vec<u8>,
218 wrapping_key: Vec<u8>,
219 ) -> Result<String, CryptoError> {
220 let tmp_store: KeyStore<KeyIds> = KeyStore::default();
221 let mut context = tmp_store.context();
222 #[allow(deprecated)]
223 context.set_symmetric_key(
224 SymmetricKeyId::Local("wrapping_key"),
225 SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(wrapping_key))?,
226 )?;
227 Ok(Pkcs8PrivateKeyBytes::from(decapsulation_key)
228 .encrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))?
229 .to_string())
230 }
231
232 pub fn unwrap_decapsulation_key(
235 wrapped_key: String,
236 wrapping_key: Vec<u8>,
237 ) -> Result<Vec<u8>, CryptoError> {
238 let tmp_store: KeyStore<KeyIds> = KeyStore::default();
239 let mut context = tmp_store.context();
240 #[allow(deprecated)]
241 context.set_symmetric_key(
242 SymmetricKeyId::Local("wrapping_key"),
243 SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(wrapping_key))?,
244 )?;
245 EncString::from_str(wrapped_key.as_str())?
246 .decrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))
247 }
248
249 pub fn encapsulate_key_unsigned(
253 shared_key: Vec<u8>,
254 encapsulation_key: Vec<u8>,
255 ) -> Result<String, CryptoError> {
256 let encapsulation_key =
257 AsymmetricPublicCryptoKey::from_der(&SpkiPublicKeyBytes::from(encapsulation_key))?;
258 Ok(UnsignedSharedKey::encapsulate_key_unsigned(
259 &SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(shared_key))?,
260 &encapsulation_key,
261 )?
262 .to_string())
263 }
264
265 pub fn decapsulate_key_unsigned(
269 encapsulated_key: String,
270 decapsulation_key: Vec<u8>,
271 ) -> Result<Vec<u8>, CryptoError> {
272 Ok(UnsignedSharedKey::from_str(encapsulated_key.as_str())?
273 .decapsulate_key_unsigned(&AsymmetricCryptoKey::from_der(
274 &Pkcs8PrivateKeyBytes::from(decapsulation_key),
275 )?)?
276 .to_encoded()
277 .to_vec())
278 }
279
280 pub fn verifying_key_for_signing_key(
283 signing_key: String,
284 wrapping_key: Vec<u8>,
285 ) -> Result<Vec<u8>, CryptoError> {
286 let bytes = Self::symmetric_decrypt_bytes(signing_key, wrapping_key)?;
287 let signing_key = SigningKey::from_cose(&CoseKeyBytes::from(bytes))?;
288 let verifying_key = signing_key.to_verifying_key();
289 Ok(verifying_key.to_cose().to_vec())
290 }
291
292 pub fn key_algorithm_for_verifying_key(
294 verifying_key: Vec<u8>,
295 ) -> Result<SignatureAlgorithm, CryptoError> {
296 let verifying_key = VerifyingKey::from_cose(&CoseKeyBytes::from(verifying_key))?;
297 let algorithm = verifying_key.algorithm();
298 Ok(algorithm)
299 }
300
301 pub fn verify_and_unwrap_signed_public_key(
306 signed_public_key: Vec<u8>,
307 verifying_key: Vec<u8>,
308 ) -> Result<Vec<u8>, CryptoError> {
309 let signed_public_key = SignedPublicKey::try_from(CoseSign1Bytes::from(signed_public_key))?;
310 let verifying_key = VerifyingKey::from_cose(&CoseKeyBytes::from(verifying_key))?;
311 signed_public_key
312 .verify_and_unwrap(&verifying_key)
313 .map(|public_key| public_key.to_der())?
314 .map(|pk| pk.to_vec())
315 }
316
317 pub fn derive_kdf_material(
319 password: &[u8],
320 salt: &[u8],
321 kdf: Kdf,
322 ) -> Result<Vec<u8>, CryptoError> {
323 #[allow(deprecated)]
324 dangerous_derive_kdf_material(password, salt, &kdf)
325 }
326
327 pub fn decrypt_user_key_with_master_key(
328 encrypted_user_key: String,
329 master_key: Vec<u8>,
330 ) -> Result<Vec<u8>, CryptoError> {
331 let master_key = &BitwardenLegacyKeyBytes::from(master_key);
332 let master_key = &SymmetricCryptoKey::try_from(master_key)?;
333 let master_key = MasterKey::try_from(master_key)?;
334 let encrypted_user_key = EncString::from_str(&encrypted_user_key)?;
335 let result = master_key
336 .decrypt_user_key(encrypted_user_key)
337 .map_err(|_| CryptoError::InvalidKey)?;
338 Ok(result.to_encoded().to_vec())
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use std::{num::NonZero, str::FromStr};
345
346 use bitwarden_crypto::EncString;
347
348 use super::*;
349
350 const KEY: &[u8] = &[
351 81, 142, 1, 228, 222, 3, 3, 133, 34, 176, 35, 66, 150, 6, 109, 70, 190, 149, 47, 47, 89,
352 23, 144, 87, 92, 46, 220, 13, 148, 106, 162, 234, 202, 139, 136, 33, 16, 200, 8, 73, 176,
353 172, 185, 187, 224, 10, 65, 223, 228, 54, 92, 181, 8, 213, 162, 221, 117, 254, 245, 111,
354 55, 211, 77, 29,
355 ];
356
357 const ENCRYPTED: &str = "2.Dh7AFLXR+LXcxUaO5cRjpg==|uXyhubjAoNH8lTdy/zgJDQ==|cHEMboj0MYsU5yDRQ1rLCgxcjNbKRc1PWKuv8bpU5pM=";
358 const DECRYPTED: &str = "test";
359 const DECRYPTED_BYTES: &[u8] = b"test";
360 const ENCRYPTED_BYTES: &[u8] = &[
361 2, 209, 195, 115, 49, 205, 253, 128, 162, 169, 246, 175, 217, 144, 73, 108, 191, 27, 113,
362 69, 55, 94, 142, 62, 129, 204, 173, 130, 37, 42, 97, 209, 25, 192, 64, 126, 112, 139, 248,
363 2, 89, 112, 178, 83, 25, 77, 130, 187, 127, 85, 179, 211, 159, 186, 111, 44, 109, 211, 18,
364 120, 104, 144, 4, 76, 3,
365 ];
366
367 const PEM_KEY: &str = "-----BEGIN PRIVATE KEY-----
368MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDiTQVuzhdygFz5
369qv14i+XFDGTnDravzUQT1hPKPGUZOUSZ1gwdNgkWqOIaOnR65BHEnL0sp4bnuiYc
370afeK2JAW5Sc8Z7IxBNSuAwhQmuKx3RochMIiuCkI2/p+JvUQoJu6FBNm8OoJ4Cwm
371qqHGZESMfnpQDCuDrB3JdJEdXhtmnl0C48sGjOk3WaBMcgGqn8LbJDUlyu1zdqyv
372b0waJf0iV4PJm2fkUl7+57D/2TkpbCqURVnZK1FFIEg8mr6FzSN1F2pOfktkNYZw
373P7MSNR7o81CkRSCMr7EkIVa+MZYMBx106BMK7FXgWB7nbSpsWKxBk7ZDHkID2fam
374rEcVtrzDAgMBAAECggEBAKwq9OssGGKgjhvUnyrLJHAZ0dqIMyzk+dotkLjX4gKi
375szJmyqiep6N5sStLNbsZMPtoU/RZMCW0VbJgXFhiEp2YkZU/Py5UAoqw++53J+kx
3760d/IkPphKbb3xUec0+1mg5O6GljDCQuiZXS1dIa/WfeZcezclW6Dz9WovY6ePjJ+
3778vEBR1icbNKzyeINd6MtPtpcgQPHtDwHvhPyUDbKDYGbLvjh9nui8h4+ZUlXKuVR
378jB0ChxiKV1xJRjkrEVoulOOicd5r597WfB2ghax3pvRZ4MdXemCXm3gQYqPVKach
379vGU+1cPQR/MBJZpxT+EZA97xwtFS3gqwbxJaNFcoE8ECgYEA9OaeYZhQPDo485tI
3801u/Z7L/3PNape9hBQIXoW7+MgcQ5NiWqYh8Jnj43EIYa0wM/ECQINr1Za8Q5e6KR
381J30FcU+kfyjuQ0jeXdNELGU/fx5XXNg/vV8GevHwxRlwzqZTCg6UExUZzbYEQqd7
382l+wPyETGeua5xCEywA1nX/D101kCgYEA7I6aMFjhEjO71RmzNhqjKJt6DOghoOfQ
383TjhaaanNEhLYSbenFz1mlb21mW67ulmz162saKdIYLxQNJIP8ZPmxh4ummOJI8w9
384ClHfo8WuCI2hCjJ19xbQJocSbTA5aJg6lA1IDVZMDbQwsnAByPRGpaLHBT/Q9Bye
385KvCMB+9amXsCgYEAx65yXSkP4sumPBrVHUub6MntERIGRxBgw/drKcPZEMWp0FiN
386wEuGUBxyUWrG3F69QK/gcqGZE6F/LSu0JvptQaKqgXQiMYJsrRvhbkFvsHpQyUcZ
387UZL1ebFjm5HOxPAgrQaN/bEqxOwwNRjSUWEMzUImg3c06JIZCzbinvudtKECgYEA
388kY3JF/iIPI/yglP27lKDlCfeeHSYxI3+oTKRhzSAxx8rUGidenJAXeDGDauR/T7W
389pt3pGNfddBBK9Z3uC4Iq3DqUCFE4f/taj7ADAJ1Q0Vh7/28/IJM77ojr8J1cpZwN
390Zy2o6PPxhfkagaDjqEeN9Lrs5LD4nEvDkr5CG1vOjmMCgYEAvIBFKRm31NyF8jLi
391CVuPwC5PzrW5iThDmsWTaXFpB3esUsbICO2pEz872oeQS+Em4GO5vXUlpbbFPzup
392PFhA8iMJ8TAvemhvc7oM0OZqpU6p3K4seHf6BkwLxumoA3vDJfovu9RuXVcJVOnf
393DnqOsltgPomWZ7xVfMkm9niL2OA=
394-----END PRIVATE KEY-----";
395
396 const SIGNING_KEY_WRAPPING_KEY: &[u8] = &[
397 40, 215, 110, 199, 183, 4, 182, 78, 213, 123, 251, 113, 72, 223, 57, 2, 3, 81, 136, 19, 88,
398 78, 206, 176, 158, 251, 211, 84, 1, 199, 203, 142, 176, 227, 187, 136, 209, 79, 23, 13, 44,
399 224, 90, 10, 191, 72, 22, 227, 171, 105, 107, 139, 24, 49, 9, 150, 103, 139, 151, 204, 165,
400 121, 165, 71,
401 ];
402 const SIGNING_KEY: &[u8] = &[
403 166, 1, 1, 2, 80, 123, 226, 102, 228, 194, 232, 71, 30, 183, 42, 219, 193, 50, 30, 21, 43,
404 3, 39, 4, 130, 1, 2, 35, 88, 32, 148, 2, 66, 69, 169, 57, 129, 240, 37, 18, 225, 211, 207,
405 133, 66, 143, 204, 238, 113, 152, 43, 112, 133, 173, 179, 17, 202, 135, 175, 237, 1, 59,
406 32, 6,
407 ];
408 const VERIFYING_KEY: &[u8] = &[
409 166, 1, 1, 2, 80, 123, 226, 102, 228, 194, 232, 71, 30, 183, 42, 219, 193, 50, 30, 21, 43,
410 3, 39, 4, 129, 2, 32, 6, 33, 88, 32, 63, 70, 49, 37, 246, 232, 146, 144, 83, 224, 0, 17,
411 111, 248, 16, 242, 69, 195, 84, 46, 39, 218, 55, 63, 90, 112, 148, 91, 224, 186, 122, 4,
412 ];
413 const PUBLIC_KEY: &[u8] = &[
414 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0,
415 48, 130, 1, 10, 2, 130, 1, 1, 0, 173, 4, 54, 63, 125, 12, 254, 38, 115, 34, 95, 164, 148,
416 115, 86, 140, 129, 74, 19, 70, 212, 212, 130, 163, 105, 249, 101, 120, 154, 46, 194, 250,
417 229, 242, 156, 67, 109, 179, 187, 134, 59, 235, 60, 107, 144, 163, 35, 22, 109, 230, 134,
418 243, 44, 243, 79, 84, 76, 11, 64, 56, 236, 167, 98, 26, 30, 213, 143, 105, 52, 92, 129, 92,
419 88, 22, 115, 135, 63, 215, 79, 8, 11, 183, 124, 10, 73, 231, 170, 110, 210, 178, 22, 100,
420 76, 75, 118, 202, 252, 204, 67, 204, 152, 6, 244, 208, 161, 146, 103, 225, 233, 239, 88,
421 195, 88, 150, 230, 111, 62, 142, 12, 157, 184, 155, 34, 84, 237, 111, 11, 97, 56, 152, 130,
422 14, 72, 123, 140, 47, 137, 5, 97, 166, 4, 147, 111, 23, 65, 78, 63, 208, 198, 50, 161, 39,
423 80, 143, 100, 194, 37, 252, 194, 53, 207, 166, 168, 250, 165, 121, 9, 207, 90, 36, 213,
424 211, 84, 255, 14, 205, 114, 135, 217, 137, 105, 232, 58, 169, 222, 10, 13, 138, 203, 16,
425 12, 122, 72, 227, 95, 160, 111, 54, 200, 198, 143, 156, 15, 143, 196, 50, 150, 204, 144,
426 255, 162, 248, 50, 28, 47, 66, 9, 83, 158, 67, 9, 50, 147, 174, 147, 200, 199, 238, 190,
427 248, 60, 114, 218, 32, 209, 120, 218, 17, 234, 14, 128, 192, 166, 33, 60, 73, 227, 108,
428 201, 41, 160, 81, 133, 171, 205, 221, 2, 3, 1, 0, 1,
429 ];
430
431 const SIGNED_PUBLIC_KEY: &[u8] = &[
432 132, 88, 30, 164, 1, 39, 3, 24, 60, 4, 80, 123, 226, 102, 228, 194, 232, 71, 30, 183, 42,
433 219, 193, 50, 30, 21, 43, 58, 0, 1, 56, 127, 1, 160, 89, 1, 78, 163, 105, 97, 108, 103,
434 111, 114, 105, 116, 104, 109, 0, 109, 99, 111, 110, 116, 101, 110, 116, 70, 111, 114, 109,
435 97, 116, 0, 105, 112, 117, 98, 108, 105, 99, 75, 101, 121, 89, 1, 38, 48, 130, 1, 34, 48,
436 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2,
437 130, 1, 1, 0, 173, 4, 54, 63, 125, 12, 254, 38, 115, 34, 95, 164, 148, 115, 86, 140, 129,
438 74, 19, 70, 212, 212, 130, 163, 105, 249, 101, 120, 154, 46, 194, 250, 229, 242, 156, 67,
439 109, 179, 187, 134, 59, 235, 60, 107, 144, 163, 35, 22, 109, 230, 134, 243, 44, 243, 79,
440 84, 76, 11, 64, 56, 236, 167, 98, 26, 30, 213, 143, 105, 52, 92, 129, 92, 88, 22, 115, 135,
441 63, 215, 79, 8, 11, 183, 124, 10, 73, 231, 170, 110, 210, 178, 22, 100, 76, 75, 118, 202,
442 252, 204, 67, 204, 152, 6, 244, 208, 161, 146, 103, 225, 233, 239, 88, 195, 88, 150, 230,
443 111, 62, 142, 12, 157, 184, 155, 34, 84, 237, 111, 11, 97, 56, 152, 130, 14, 72, 123, 140,
444 47, 137, 5, 97, 166, 4, 147, 111, 23, 65, 78, 63, 208, 198, 50, 161, 39, 80, 143, 100, 194,
445 37, 252, 194, 53, 207, 166, 168, 250, 165, 121, 9, 207, 90, 36, 213, 211, 84, 255, 14, 205,
446 114, 135, 217, 137, 105, 232, 58, 169, 222, 10, 13, 138, 203, 16, 12, 122, 72, 227, 95,
447 160, 111, 54, 200, 198, 143, 156, 15, 143, 196, 50, 150, 204, 144, 255, 162, 248, 50, 28,
448 47, 66, 9, 83, 158, 67, 9, 50, 147, 174, 147, 200, 199, 238, 190, 248, 60, 114, 218, 32,
449 209, 120, 218, 17, 234, 14, 128, 192, 166, 33, 60, 73, 227, 108, 201, 41, 160, 81, 133,
450 171, 205, 221, 2, 3, 1, 0, 1, 88, 64, 207, 18, 4, 242, 149, 31, 37, 255, 243, 62, 78, 46,
451 12, 150, 134, 159, 69, 89, 62, 222, 132, 12, 177, 74, 155, 80, 154, 37, 77, 176, 19, 142,
452 73, 4, 134, 242, 24, 56, 54, 38, 178, 59, 11, 118, 230, 159, 87, 91, 20, 237, 188, 186,
453 216, 86, 189, 50, 46, 173, 117, 36, 54, 105, 216, 9,
454 ];
455
456 const DERIVED_KDF_MATERIAL_PBKDF2: &[u8] = &[
457 129, 57, 137, 140, 156, 220, 110, 212, 201, 255, 52, 182, 22, 206, 221, 66, 136, 199, 181,
458 89, 252, 175, 82, 168, 79, 204, 88, 174, 166, 60, 52, 79,
459 ];
460 const DERIVED_KDF_MATERIAL_ARGON2ID: &[u8] = &[
461 221, 57, 158, 206, 27, 154, 188, 170, 33, 198, 250, 144, 191, 231, 29, 74, 201, 102, 253,
462 77, 8, 128, 173, 111, 217, 41, 125, 9, 156, 52, 112, 140,
463 ];
464
465 #[test]
466 fn test_symmetric_decrypt() {
467 let enc_string = EncString::from_str(ENCRYPTED).unwrap();
468
469 let result = PureCrypto::symmetric_decrypt_string(enc_string.to_string(), KEY.to_vec());
470 assert!(result.is_ok());
471 assert_eq!(result.unwrap(), DECRYPTED);
472 }
473
474 #[test]
475 fn test_symmetric_encrypt() {
476 let result = PureCrypto::symmetric_encrypt_string(DECRYPTED.to_string(), KEY.to_vec());
477 assert!(result.is_ok());
478 }
480
481 #[test]
482 fn test_symmetric_string_round_trip() {
483 let encrypted =
484 PureCrypto::symmetric_encrypt_string(DECRYPTED.to_string(), KEY.to_vec()).unwrap();
485 let decrypted =
486 PureCrypto::symmetric_decrypt_string(encrypted.clone(), KEY.to_vec()).unwrap();
487 assert_eq!(decrypted, DECRYPTED);
488 }
489
490 #[test]
491 fn test_symmetric_bytes_round_trip() {
492 let encrypted =
493 PureCrypto::symmetric_encrypt_bytes(DECRYPTED.as_bytes().to_vec(), KEY.to_vec())
494 .unwrap();
495 let decrypted =
496 PureCrypto::symmetric_decrypt_bytes(encrypted.clone(), KEY.to_vec()).unwrap();
497 assert_eq!(decrypted, DECRYPTED.as_bytes().to_vec());
498 }
499
500 #[test]
501 fn test_symmetric_decrypt_array_buffer() {
502 let result = PureCrypto::symmetric_decrypt_filedata(ENCRYPTED_BYTES.to_vec(), KEY.to_vec());
503 assert!(result.is_ok());
504 assert_eq!(result.unwrap(), DECRYPTED_BYTES);
505 }
506
507 #[test]
508 fn test_symmetric_encrypt_to_array_buffer() {
509 let result = PureCrypto::symmetric_encrypt_filedata(DECRYPTED_BYTES.to_vec(), KEY.to_vec());
510 assert!(result.is_ok());
511 }
513
514 #[test]
515 fn test_symmetric_filedata_round_trip() {
516 let encrypted =
517 PureCrypto::symmetric_encrypt_filedata(DECRYPTED_BYTES.to_vec(), KEY.to_vec()).unwrap();
518 let decrypted =
519 PureCrypto::symmetric_decrypt_filedata(encrypted.clone(), KEY.to_vec()).unwrap();
520 assert_eq!(decrypted, DECRYPTED_BYTES);
521 }
522
523 #[test]
524 fn test_make_aes256_cbc_hmac_key() {
525 let key = PureCrypto::make_user_key_aes256_cbc_hmac();
526 assert_eq!(key.len(), 64);
527 }
528
529 #[test]
530 fn test_make_xchacha20_poly1305_key() {
531 let key = PureCrypto::make_user_key_xchacha20_poly1305();
532 assert!(key.len() > 64);
533 }
534
535 #[test]
536 fn roundtrip_encrypt_user_key_with_master_password() {
537 let master_password = "test";
538 let email = "[email protected]";
539 let kdf = Kdf::PBKDF2 {
540 iterations: NonZero::try_from(600000).unwrap(),
541 };
542 let user_key = PureCrypto::make_user_key_aes256_cbc_hmac();
543 let encrypted_user_key = PureCrypto::encrypt_user_key_with_master_password(
544 user_key.clone(),
545 master_password.to_string(),
546 email.to_string(),
547 kdf.clone(),
548 )
549 .unwrap();
550 let decrypted_user_key = PureCrypto::decrypt_user_key_with_master_password(
551 encrypted_user_key,
552 master_password.to_string(),
553 email.to_string(),
554 kdf,
555 )
556 .unwrap();
557 assert_eq!(user_key, decrypted_user_key);
558 }
559
560 #[test]
561 fn test_wrap_unwrap_symmetric_key() {
562 let key_to_be_wrapped = PureCrypto::make_user_key_aes256_cbc_hmac();
563 let wrapping_key = PureCrypto::make_user_key_aes256_cbc_hmac();
564 let wrapped_key =
565 PureCrypto::wrap_symmetric_key(key_to_be_wrapped.clone(), wrapping_key.clone())
566 .unwrap();
567 let unwrapped_key = PureCrypto::unwrap_symmetric_key(wrapped_key, wrapping_key).unwrap();
568 assert_eq!(key_to_be_wrapped, unwrapped_key);
569 }
570
571 #[test]
572 fn test_wrap_encapsulation_key() {
573 let decapsulation_key = AsymmetricCryptoKey::from_pem(PEM_KEY).unwrap();
574 let encapsulation_key = decapsulation_key
575 .to_public_key()
576 .to_der()
577 .unwrap()
578 .as_ref()
579 .to_vec();
580 let wrapping_key = PureCrypto::make_user_key_aes256_cbc_hmac();
581 let wrapped_key =
582 PureCrypto::wrap_encapsulation_key(encapsulation_key.clone(), wrapping_key.clone())
583 .unwrap();
584 let unwrapped_key =
585 PureCrypto::unwrap_encapsulation_key(wrapped_key, wrapping_key).unwrap();
586 assert_eq!(encapsulation_key, unwrapped_key);
587 }
588
589 #[test]
590 fn test_wrap_decapsulation_key() {
591 let decapsulation_key = AsymmetricCryptoKey::from_pem(PEM_KEY).unwrap();
592 let wrapping_key = PureCrypto::make_user_key_aes256_cbc_hmac();
593 let wrapped_key = PureCrypto::wrap_decapsulation_key(
594 decapsulation_key.to_der().unwrap().to_vec(),
595 wrapping_key.clone(),
596 )
597 .unwrap();
598 let unwrapped_key =
599 PureCrypto::unwrap_decapsulation_key(wrapped_key, wrapping_key).unwrap();
600 assert_eq!(decapsulation_key.to_der().unwrap().to_vec(), unwrapped_key);
601 }
602
603 #[test]
604 fn test_encapsulate_key_unsigned() {
605 let shared_key = PureCrypto::make_user_key_aes256_cbc_hmac();
606 let decapsulation_key = AsymmetricCryptoKey::from_pem(PEM_KEY).unwrap();
607 let encapsulation_key = decapsulation_key.to_public_key().to_der().unwrap();
608 let encapsulated_key = PureCrypto::encapsulate_key_unsigned(
609 shared_key.clone(),
610 encapsulation_key.clone().to_vec(),
611 )
612 .unwrap();
613 let unwrapped_key = PureCrypto::decapsulate_key_unsigned(
614 encapsulated_key,
615 decapsulation_key.to_der().unwrap().to_vec(),
616 )
617 .unwrap();
618 assert_eq!(shared_key, unwrapped_key);
619 }
620
621 #[test]
622 fn test_key_algorithm_for_verifying_key() {
623 let verifying_key =
624 VerifyingKey::from_cose(&CoseKeyBytes::from(VERIFYING_KEY.to_vec())).unwrap();
625 let algorithm =
626 PureCrypto::key_algorithm_for_verifying_key(verifying_key.to_cose().to_vec()).unwrap();
627 assert_eq!(algorithm, SignatureAlgorithm::Ed25519);
628 }
629
630 #[test]
631 fn test_verifying_key_for_signing_key() {
632 let wrapped_signing_key = PureCrypto::symmetric_encrypt_bytes(
633 SIGNING_KEY.to_vec(),
634 SIGNING_KEY_WRAPPING_KEY.to_vec(),
635 )
636 .unwrap();
637 let verifying_key =
638 VerifyingKey::from_cose(&CoseKeyBytes::from(VERIFYING_KEY.to_vec())).unwrap();
639 let verifying_key_derived = PureCrypto::verifying_key_for_signing_key(
640 wrapped_signing_key.to_string(),
641 SIGNING_KEY_WRAPPING_KEY.to_vec(),
642 )
643 .unwrap();
644 let verifying_key_derived =
645 VerifyingKey::from_cose(&CoseKeyBytes::from(verifying_key_derived)).unwrap();
646 assert_eq!(verifying_key.to_cose(), verifying_key_derived.to_cose());
647 }
648
649 #[test]
650 fn test_verify_and_unwrap_signed_public_key() {
651 let public_key = PureCrypto::verify_and_unwrap_signed_public_key(
652 SIGNED_PUBLIC_KEY.to_vec(),
653 VERIFYING_KEY.to_vec(),
654 )
655 .unwrap();
656 assert_eq!(public_key, PUBLIC_KEY);
657 }
658
659 #[test]
660 fn test_derive_pbkdf2_output() {
661 let password = "test_password".as_bytes();
662 let email = "[email protected]".as_bytes();
663 let kdf = Kdf::PBKDF2 {
664 iterations: NonZero::try_from(600000).unwrap(),
665 };
666 let derived_key = PureCrypto::derive_kdf_material(password, email, kdf).unwrap();
667 assert_eq!(derived_key, DERIVED_KDF_MATERIAL_PBKDF2);
668 }
669
670 #[test]
671 fn test_derived_argon2_output() {
672 let password = "test_password".as_bytes();
673 let email = "[email protected]".as_bytes();
674 let kdf = Kdf::Argon2id {
675 iterations: NonZero::try_from(3).unwrap(),
676 memory: NonZero::try_from(64).unwrap(),
677 parallelism: NonZero::try_from(4).unwrap(),
678 };
679 let derived_key = PureCrypto::derive_kdf_material(password, email, kdf).unwrap();
680 assert_eq!(derived_key, DERIVED_KDF_MATERIAL_ARGON2ID);
681 }
682
683 #[test]
684 fn test_decrypt_user_key_with_master_key() {
685 let password = "test_password";
686 let email = "[email protected]";
687 let kdf = &Kdf::Argon2id {
688 iterations: NonZero::try_from(3).unwrap(),
689 memory: NonZero::try_from(64).unwrap(),
690 parallelism: NonZero::try_from(4).unwrap(),
691 };
692 let master_key = MasterKey::derive(password, email, kdf).unwrap();
693 let (user_key, encrypted_user_key) = master_key.make_user_key().unwrap();
694 let master_key_bytes = master_key.to_base64().into_bytes();
695
696 let decrypted_user_key = PureCrypto::decrypt_user_key_with_master_key(
697 encrypted_user_key.to_string(),
698 master_key_bytes,
699 )
700 .unwrap();
701 assert_eq!(user_key.0.to_encoded().to_vec(), decrypted_user_key);
702 }
703}