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

ArtifactPathFormat
SQLCipher Database~/Library/Application Support/Signal/sql/db.sqliteSQLCipher 4 / SQLite
Database WAL~/Library/Application Support/Signal/sql/db.sqlite-walSQLite WAL
Database SHM~/Library/Application Support/Signal/sql/db.sqlite-shmSQLite SHM
Decryption Key~/Library/Application Support/Signal/config.jsonJSON
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:

ParameterValue
CipherAES-256-CBC
KDF algorithmPBKDF2-HMAC-SHA512
KDF iterations256,000
Page size4096 bytes
HMAC algorithmSHA-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 VersionSupportNotes
10.15 CatalinaFullMinimum supported version
11 Big SurFullNo schema changes
12 MontereyFullNo schema changes
13 VenturaFullNo schema changes
14 SonomaFullNo schema changes
15 SequoiaFullNo 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 body column 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 messages table entirely.
  • Identity key history: The identityKeys table and key change events in the messages table (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 -wal and -shm companion files alongside db.sqlite to ensure all committed transactions are captured.

Tool Support

ToolSupport Level
macforFull collection: messages, conversations, attachments, sessions, app state
AXIOMFull Signal Desktop support
CellebriteSignal Desktop support
sqlcipher CLIManual decryption and querying
DB Browser for SQLiteManual analysis after decryption

References

Previous
Call History