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> {
36 if encrypted_value.is_empty() {
37 return Ok(String::new());
38 }
39
40 #[cfg(target_os = "macos")]
41 let value = macos::decrypt(encrypted_value)?;
42
43 #[cfg(target_os = "linux")]
44 let value = linux::decrypt(encrypted_value)?;
45
46 #[cfg(target_os = "windows")]
47 let value = windows::decrypt(encrypted_value)?;
48
49 #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
50 return Err(CryptoError::UnsupportedVersion(
51 "Unsupported OS".to_string(),
52 ));
53
54 Ok(strip_chrome_value_prefix(&value))
55}
56
57fn strip_chrome_value_prefix(value: &str) -> String {
63 let bytes = value.as_bytes();
64 if bytes.len() >= 2 && bytes[0].is_ascii_digit() {
65 if bytes[1] == b't' {
66 return value[2..].to_string();
67 }
68 if bytes[1] == b'e' && bytes.len() >= 3 && bytes[2] == b'`' {
69 return value[3..].to_string();
70 }
71 }
72 value.to_string()
73}