1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum CryptoError {
5 #[error("Failed to decrypt: {0}")]
6 DecryptionFailed(String),
7
8 #[error("Unsupported encryption version: {0}")]
9 UnsupportedVersion(String),
10
11 #[cfg(target_os = "macos")]
12 #[error("Keychain error: {0}")]
13 KeychainError(String),
14
15 #[cfg(target_os = "linux")]
16 #[error("Secret service error: {0}")]
17 SecretServiceError(String),
18
19 #[cfg(target_os = "windows")]
20 #[error("DPAPI error: {0}")]
21 DpapiError(String),
22}
23
24pub type Result<T> = std::result::Result<T, CryptoError>;
25
26#[cfg(target_os = "macos")]
27pub mod macos;
28
29#[cfg(target_os = "linux")]
30pub mod linux;
31
32#[cfg(target_os = "windows")]
33pub mod windows;
34
35pub fn decrypt_cookie_value(encrypted_value: &[u8]) -> Result<String> {
39 if encrypted_value.is_empty() {
40 return Ok(String::new());
41 }
42
43 #[cfg(target_os = "macos")]
44 let value = macos::decrypt(encrypted_value)?;
45
46 #[cfg(target_os = "linux")]
47 let value = linux::decrypt(encrypted_value)?;
48
49 #[cfg(target_os = "windows")]
50 let value = windows::decrypt(encrypted_value)?;
51
52 #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
53 return Err(CryptoError::UnsupportedVersion(
54 "Unsupported OS".to_string(),
55 ));
56
57 Ok(strip_chrome_value_prefix(&value))
58}
59
60fn strip_chrome_value_prefix(value: &str) -> String {
66 let bytes = value.as_bytes();
67 if bytes.len() >= 2 && bytes[0].is_ascii_digit() {
68 if bytes[1] == b't' {
69 return value[2..].to_string();
70 }
71 if bytes[1] == b'e' && bytes.len() >= 3 && bytes[2] == b'`' {
72 return value[3..].to_string();
73 }
74 }
75 value.to_string()
76}