Signal Desktop
Signal Desktop
Overview
Signal Desktop is an Electron-based messaging client for macOS that stores all conversation data in a SQLCipher-encrypted SQLite database. Signal is widely regarded as one of the most secure messaging platforms due to its end-to-end encryption protocol — however, the desktop client contains a critical forensic vulnerability: the database encryption key is stored in plaintext in a JSON configuration file (config.json) located alongside the encrypted database.
An investigator with filesystem access can read the key directly from config.json, use it to decrypt the SQLCipher database, and recover the full message history, contact network, identity keys, and attachment metadata — without any credential prompting or brute-force decryption. This architectural decision makes Signal Desktop one of the highest-value encrypted messaging artifacts on macOS.
Signal Desktop is a third-party application. Its data directory lives under ~/Library/Application Support/Signal/, not in any Apple system location. The application bundle identifier is org.whispersystems.signal-desktop.
File Locations
| Artifact | Path | Format |
|---|---|---|
| SQLCipher Database | ~/Library/Application Support/Signal/sql/db.sqlite | SQLCipher 4 / SQLite |
| Database WAL | ~/Library/Application Support/Signal/sql/db.sqlite-wal | SQLite WAL |
| Database SHM | ~/Library/Application Support/Signal/sql/db.sqlite-shm | SQLite SHM |
| Decryption Key | ~/Library/Application Support/Signal/config.json | JSON |
| Attachments | ~/Library/Application Support/Signal/attachments.noindex/ | Binary |
| Local Storage | ~/Library/Application Support/Signal/Local Storage/leveldb/ | LevelDB |
| Stickers | ~/Library/Application Support/Signal/stickers/ | Binary |
| Drafts | ~/Library/Application Support/Signal/drafts/ | Binary |
The attachments.noindex directory uses a flat hash-based directory structure. Attachment filenames on disk do not match the original filenames sent — correlation must be done through the database records.
The Critical Finding: Plaintext Encryption Key
Signal Desktop encrypts its SQLite database using SQLCipher 4 with AES-256-CBC and 256,000 PBKDF2-HMAC-SHA512 iterations. Despite this strong encryption, the 256-bit database key is stored in cleartext in config.json:
{
"key": "a3f8c2d14e5b9f07..."
}
The key field is a 64-character hexadecimal string representing the raw 256-bit key. It may optionally be prefixed with 0x. This file has no additional access controls beyond standard macOS filesystem permissions — any process running as the user (or root) can read it.
Forensic implication: A forensic image, a live acquisition with Full Disk Access, or any other method that can read ~/Library/Application Support/Signal/ is sufficient to fully decrypt the Signal database. The end-to-end encryption of Signal's transport protocol provides no protection once the device is in the investigator's hands.
How SQLCipher Works
SQLCipher is a SQLite extension that encrypts every database page using AES-256. The database appears as random bytes to any tool that does not know the key. Signal Desktop uses the following SQLCipher 4 parameters:
| Parameter | Value |
|---|---|
| Cipher | AES-256-CBC |
| KDF algorithm | PBKDF2-HMAC-SHA512 |
| KDF iterations | 256,000 |
| Page size | 4096 bytes |
| HMAC algorithm | SHA-512 |
To open the database manually with the sqlcipher CLI:
-- Open the database
sqlcipher ~/Library/Application\ Support/Signal/sql/db.sqlite
-- Set the decryption key (replace <hex_key> with the value from config.json, without 0x prefix)
PRAGMA key = "x'<hex_key>'";
PRAGMA cipher_page_size = 4096;
-- Verify decryption succeeded
SELECT count(*) FROM sqlite_master;
Once opened, all table contents are fully readable plaintext — there is no additional per-message encryption.
Key Artifacts
SQLCipher Database (sql/db.sqlite)
The primary forensic artifact. Contains all messages, conversations, contacts, identity keys, session state, and attachment metadata. See SQLCipher Database for the full schema.
config.json
The decryption key file. The key field contains the 64-character hex string needed to open db.sqlite. macfor logs a SHA-256 hash of the key for audit trail purposes without persisting the key itself in output records.
attachments.noindex
Media files sent and received by Signal. Files are stored under a hash-based directory structure and do not retain their original filenames. Attachment records in the database contain path references to these files.
Local Storage (Local Storage/leveldb/)
A LevelDB database containing application state including the registered phone number (number_id), Signal UUID (uuid_id), device name, application version, and user preferences. This data is readable without SQLCipher decryption.
macOS Version Support
| macOS Version | Support | Notes |
|---|---|---|
| 10.15 Catalina | Full | Minimum supported version |
| 11 Big Sur | Full | No schema changes |
| 12 Monterey | Full | No schema changes |
| 13 Ventura | Full | No schema changes |
| 14 Sonoma | Full | No schema changes |
| 15 Sequoia | Full | No schema changes |
Signal Desktop schema changes are driven by the Signal Desktop application release cycle, not macOS versions. The collector performs runtime column discovery to handle schema variations across Signal Desktop versions.
Forensic Analysis Notes
- Signal is not anonymous on the filesystem: The registration phone number and Signal UUID are stored in the LevelDB Local Storage in plaintext, readable without any decryption.
- Disappearing messages: Messages with active timers may have their
bodycolumn cleared (isErased = 1) while the message row itself remains. The record proves communication occurred even if the content is gone. - No deleted message tombstone table: Unlike Apple Messages, Signal does not maintain a separate table for recently deleted messages. Deleted messages are removed from the
messagestable entirely. - Identity key history: The
identityKeystable and key change events in themessagestable (type =keychange) document when a contact's cryptographic identity changed — indicating a new device, reinstall, or potential account compromise. - WAL mode: Signal operates with SQLite WAL mode enabled. Always collect the
-waland-shmcompanion files alongsidedb.sqliteto ensure all committed transactions are captured.
Tool Support
| Tool | Support Level |
|---|---|
| macfor | Full collection: messages, conversations, attachments, sessions, app state |
| AXIOM | Full Signal Desktop support |
| Cellebrite | Signal Desktop support |
| sqlcipher CLI | Manual decryption and querying |
| DB Browser for SQLite | Manual analysis after decryption |