1use crate::crypto::{CryptoError, Result};
2use aes::cipher::{BlockDecryptMut, KeyIvInit};
3
4type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
5
6const SALT: &[u8] = b"saltysalt";
7const IV: &[u8] = b" "; const KEY_LENGTH: usize = 16;
9const ITERATIONS: u32 = 1;
10
11pub fn decrypt(encrypted_value: &[u8]) -> Result<String> {
15 if encrypted_value.len() < 3 {
16 return Ok(String::new());
17 }
18
19 let version = &encrypted_value[..3];
20 match version {
21 b"v10" | b"v11" => {
22 let encrypted = &encrypted_value[3..];
23 let key = get_encryption_key();
24 decrypt_aes_cbc(&key, encrypted)
25 }
26 _ => String::from_utf8(encrypted_value.to_vec())
27 .map_err(|e| CryptoError::DecryptionFailed(e.to_string())),
28 }
29}
30
31fn get_encryption_key() -> Vec<u8> {
32 if let Ok(key) = get_key_from_secret_service() {
33 key
34 } else {
35 let mut key = vec![0u8; KEY_LENGTH];
37 pbkdf2::pbkdf2_hmac::<sha1::Sha1>(b"peanuts", SALT, ITERATIONS, &mut key);
38 key
39 }
40}
41
42fn get_key_from_secret_service() -> Result<Vec<u8>> {
43 use secret_service::blocking::SecretService;
44
45 let service = SecretService::connect(secret_service::EncryptionType::Dh)
46 .map_err(|e| CryptoError::SecretServiceError(format!("Failed to connect: {e}")))?;
47
48 let collection = service
49 .get_default_collection()
50 .map_err(|e| CryptoError::SecretServiceError(format!("Failed to get collection: {e}")))?;
51
52 let items = collection
53 .search_items(std::collections::HashMap::from([("application", "chrome")]))
54 .map_err(|e| CryptoError::SecretServiceError(format!("Failed to search items: {e}")))?;
55
56 if let Some(item) = items.first() {
57 let password = item
58 .get_secret()
59 .map_err(|e| CryptoError::SecretServiceError(format!("Failed to get secret: {e}")))?;
60
61 let mut key = vec![0u8; KEY_LENGTH];
62 pbkdf2::pbkdf2_hmac::<sha1::Sha1>(&password, SALT, ITERATIONS, &mut key);
63 return Ok(key);
64 }
65
66 Err(CryptoError::SecretServiceError(
67 "Chrome password not found".to_string(),
68 ))
69}
70
71fn decrypt_aes_cbc(key: &[u8], encrypted: &[u8]) -> Result<String> {
72 let cipher = Aes128CbcDec::new(key.into(), IV.into());
73
74 let mut buffer = encrypted.to_vec();
75 let decrypted = cipher
76 .decrypt_padded_mut::<aes::cipher::block_padding::Pkcs7>(&mut buffer)
77 .map_err(|e| CryptoError::DecryptionFailed(format!("AES-CBC decryption failed: {e:?}")))?;
78
79 String::from_utf8(decrypted.to_vec())
80 .map_err(|e| CryptoError::DecryptionFailed(format!("UTF-8 conversion failed: {e}")))
81}