bitwarden_wasm_internal/
pure_crypto.rs

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/// This module represents a stopgap solution to provide access to primitive crypto functions for JS
13/// clients. It is not intended to be used outside of the JS clients and this pattern should not be
14/// proliferated. It is necessary because we want to use SDK crypto prior to the SDK being fully
15/// responsible for state and keys.
16#[wasm_bindgen]
17pub struct PureCrypto {}
18
19// Encryption
20#[wasm_bindgen]
21impl PureCrypto {
22    /// DEPRECATED: Use `symmetric_decrypt_string` instead.
23    /// Cleanup ticket: <https://bitwarden.atlassian.net/browse/PM-21247>
24    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    /// DEPRECATED: Use `symmetric_decrypt_filedata` instead.
43    /// Cleanup ticket: <https://bitwarden.atlassian.net/browse/PM-21247>
44    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    /// Wraps (encrypts) a symmetric key using a symmetric wrapping key, returning the wrapped key
114    /// as an EncString.
115    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        // Note: The order of arguments is different here, and should probably be refactored
132        Ok(context
133            .wrap_symmetric_key(
134                SymmetricKeyId::Local("wrapping_key"),
135                SymmetricKeyId::Local("key_to_wrap"),
136            )?
137            .to_string())
138    }
139
140    /// Unwraps (decrypts) a wrapped symmetric key using a symmetric wrapping key, returning the
141    /// unwrapped key as a serialized byte array.
142    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        // Note: The order of arguments is different here, and should probably be refactored
154        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    /// Wraps (encrypts) an SPKI DER encoded encapsulation (public) key using a symmetric wrapping
165    /// key. Note: Usually, a public key is - by definition - public, so this should not be
166    /// used. The specific use-case for this function is to enable rotateable key sets, where
167    /// the "public key" is not public, with the intent of preventing the server from being able
168    /// to overwrite the user key unlocked by the rotateable keyset.
169    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        // Note: The order of arguments is different here, and should probably be refactored
181        Ok(encapsulation_key
182            .encrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))?
183            .to_string())
184    }
185
186    /// Unwraps (decrypts) a wrapped SPKI DER encoded encapsulation (public) key using a symmetric
187    /// wrapping key.
188    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        // Note: The order of arguments is different here, and should probably be refactored
200        EncString::from_str(wrapped_key.as_str())?
201            .decrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))
202    }
203
204    /// Wraps (encrypts) a PKCS8 DER encoded decapsulation (private) key using a symmetric wrapping
205    /// key,
206    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        // Note: The order of arguments is different here, and should probably be refactored
218        Ok(decapsulation_key
219            .encrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))?
220            .to_string())
221    }
222
223    /// Unwraps (decrypts) a wrapped PKCS8 DER encoded decapsulation (private) key using a symmetric
224    /// wrapping key.
225    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        // Note: The order of arguments is different here, and should probably be refactored
237        EncString::from_str(wrapped_key.as_str())?
238            .decrypt(&mut context, SymmetricKeyId::Local("wrapping_key"))
239    }
240
241    /// Encapsulates (encrypts) a symmetric key using an asymmetric encapsulation key (public key)
242    /// in SPKI format, returning the encapsulated key as a string. Note: This is unsigned, so
243    /// the sender's authenticity cannot be verified by the recipient.
244    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    /// Decapsulates (decrypts) a symmetric key using an decapsulation key (private key) in PKCS8
257    /// DER format. Note: This is unsigned, so the sender's authenticity cannot be verified by the
258    /// recipient.
259    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    /// Given a wrapped signing key and the symmetric key it is wrapped with, this returns
271    /// the corresponding verifying key.
272    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    /// Returns the algorithm used for the given verifying key.
283    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    /// For a given signing identity (verifying key), this function verifies that the signing
292    /// identity claimed ownership of the public key. This is a one-sided claim and merely shows
293    /// that the signing identity has the intent to receive messages encrypted to the public
294    /// key.
295    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        // Cannot test encrypted string content because IV is unique per encryption
434    }
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        // Cannot test encrypted string content because IV is unique per encryption
467    }
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}