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