Open x3ro opened 1 week ago
Hi and thanks for writing this, it was very helpful that someone already did most of the reserach 😅
I gave your code a try and found that it does indeed return a decrypted key, but this key did not successfully decrypt the test database. I played around with it a little bit and eventually noticed that the key does not have the right length: 48 bytes as opposed to the expected 64 bytes.
I eventually narrowed this down to
decrypt_string
, where you take the ciphertext and treat the first 16 bytes as the IV. However, looking at the OSCrypt code from Chromium, I noticed that it just uses an IV made up of0x20
instead.My resulting
decrypt_string
function looks like this, and works at least on my machine:fn decrypt_string(&self, encrypted_hex: &str) -> Result<String, Box<dyn std::error::Error>> { let encrypted_data = decode(encrypted_hex)?; // Decode the hex string if !encrypted_data.starts_with(ENCRYPTION_VERSION_PREFIX.as_bytes()) { return Err("Invalid encryption version prefix".into()); // Validate encryption version prefix } let encrypted_text = &encrypted_data[ENCRYPTION_VERSION_PREFIX.len()..]; // Extract encrypted text // Create AES-CBC cipher with empty IV // https://chromium.googlesource.com/chromium/src/+/refs/tags/130.0.6686.2/components/os_crypt/sync/os_crypt_mac.mm#208 let cipher = Aes128Cbc::new_from_slices(&self.aes_key, &[b' '; KEY_LENGTH])?; let decrypted = cipher.decrypt_vec(encrypted_text)?; // Decrypt the text String::from_utf8(decrypted).map_err(|e| e.into()) // Convert decrypted bytes to a UTF-8 string }
The decryption key is x'decrypt_key', including x and the quotation marks on both sides. For example, if decrypt_key=1234, then the complete key would be x'1234'.
SignalDecryption
Config file: /Users/hacker/Library/Application Support/Signal/config.json
Encrypted key: 7631307d7b10316d9f44d3381af53523b696324dcbb7f6dab87df980b18392d9d3e1cd435c85d3a032b9dfdcf55219cba6ae81c3ec2d3972d1408f6ddeaddfa3fef3bf66ba1f8bdc6f30486abe8a7a5e57fd6b
Decrypted key: e44131c698c3623fc526e95410f6c520eaef7cd7987e426a03fb7a50988f6b83
db file: '~/Library/Application Support/Signal/sql/db.sqlite'
Hi and thanks for the overview :) I'm aware of how to use the decrypted key, and I already have a working implementation of this. Maybe there are differences between Signal versions, but in your example the decrypted key is 64 bytes long. This was not the case for me, when I ran your code without modification, where I only got a 48 byte key, which naturally didn't work.
Hi and thanks for writing this, it was very helpful that someone already did most of the reserach 😅
I gave your code a try and found that it does indeed return a decrypted key, but this key did not successfully decrypt the test database. I played around with it a little bit and eventually noticed that the key does not have the right length: 48 bytes as opposed to the expected 64 bytes.
I eventually narrowed this down to
decrypt_string
, where you take the ciphertext and treat the first 16 bytes as the IV. However, looking at the OSCrypt code from Chromium, I noticed that it just uses an IV made up of0x20
instead.My resulting
decrypt_string
function looks like this, and works at least on my machine: