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