SecurityRonin/signal-desktop-forensic

GitHub: SecurityRonin/signal-desktop-forensic

一款 Rust 编写的 Signal Desktop 取证解析器,通过 OS Safe Storage 密钥解密 SQLCipher 数据库并提取对话、消息、联系人和附件等类型化记录。

Stars: 0 | Forks: 0

# signal-desktop-forensic [![Crates.io core](https://img.shields.io/crates/v/signal-desktop-core.svg?label=signal-desktop-core)](https://crates.io/crates/signal-desktop-core) [![Crates.io forensic](https://img.shields.io/crates/v/signal-desktop-forensic.svg?label=signal-desktop-forensic)](https://crates.io/crates/signal-desktop-forensic) [![文档](https://img.shields.io/badge/docs-signal--desktop--forensic-blue)](https://securityronin.github.io/signal-desktop-forensic/) [![Rust 1.85+](https://img.shields.io/badge/rust-1.85%2B-orange.svg)](https://www.rust-lang.org) [![许可证:Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) [![赞助](https://img.shields.io/badge/sponsor-h4x0r-ea4aaa)](https://github.com/sponsors/h4x0r) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/SecurityRonin/signal-desktop-forensic/actions/workflows/ci.yml) [![禁止 unsafe](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) [![安全公告](https://img.shields.io/badge/advisories-clean-success.svg)](https://rustsec.org/) **解密 Signal Desktop 配置文件并读取其消息 —— 为您处理密钥恢复、 SQLCipher 以及 Signal 的 schema。** Signal Desktop 将每条消息、对话、联系人和附件记录 保存在一个 **SQLCipher 加密**的数据库中。密钥并非明文:它 被 OS Safe Storage 封装在 `config.json` 中。此 crate 走完整个 链路并为您提供带有类型的记录。 ``` use signal_desktop_core::{config::SignalConfig, keys::unwrap_sqlcipher_key, store::SignalStore}; use chromium_safestorage_core::RecoveredKey; # fn demo(profile: &std::path::Path, os_key: RecoveredKey) -> signal_desktop_core::Result<()> { // 1. Parse config.json and unwrap the SQLCipher key with the OS Safe Storage key. let config = SignalConfig::from_profile(profile)?; let sqlcipher_key = unwrap_sqlcipher_key(&os_key, &config)?; // 2. Open the encrypted database and read typed records + a timeline. let store = SignalStore::open_profile(profile, &sqlcipher_key)?; for msg in store.messages()? { println!("{} [{}] {}", msg.sent_at.unwrap_or(0), msg.direction, msg.body.unwrap_or_default()); } for entry in store.timeline()? { println!("{:?}", entry); } # Ok(()) # } ``` **错误或缺失的密钥会明确报错** —— 返回类型化的 `SignalError`,绝不会返回空行, 也绝不会伪造明文。所有加密操作均经过审计:使用 RustCrypto AES-128-CBC 进行 `encryptedKey` 解封,使用参考的 SQLCipher 库处理数据库。 ## 两个 crate | Crate | 角色 | |---|---| | `signal-desktop-core` | 读取器:恢复密钥,打开 DB,暴露 `Conversation` / `Message` / `Contact` / `Attachment` 以及 `TimelineEntry` 流。无发现。 | | `signal-desktop-forensic` | 分析器:将记录评级为规范化的 `forensicnomicon` 发现(采用 consistent-with(与……一致)表述语言,绝非直接定论)。 | ## Pipeline ``` OS Safe Storage key ─▶ decrypt config.json encryptedKey (v10, AES-128-CBC) ─▶ SQLCipher raw key (64 hex = 32 bytes) ─▶ PRAGMA key ─▶ sql/db.sqlite ─▶ messages · conversations · contacts · attachments · timeline ``` OS Safe Storage 密钥本身由 [`chromium-safestorage`](https://github.com/SecurityRonin/chromium-safestorage) 恢复(macOS Keychain / Windows DPAPI / Linux libsecret);此 crate 将 `RecoveredKey` 作为输入。 ## 信任,但须验证 - **输入经过模糊测试。** 每个解析的结构对应一个 `cargo-fuzz` 目标 —— 包括 `config.json` 解码、v10 密钥解封路径,以及每条消息的 JSON —— 每次推送时进行冒烟测试,并按计划进行限时测试。不变式:遇到任意字节绝不 panic。 - **通过 lint 实现 panic-free。** 在生产环境中设为 `unsafe_code = forbid`,`unwrap_used`/`expect_used = deny`,通过 `safe-read` 进行有界读取。 - **基于真实应用程序的字节进行验证。** `config.json` 的 schema 和 `encryptedKey` 的 v10 格式已对照真实的宿主机 Signal profile 进行了确认; 记录解析在 Signal 文档记录的 schema 中铸造的 SQLCipher DB 上进行了验证。有关诚实的分级,请参阅 [`docs/validation.md`](docs/validation.md)。 [隐私政策](https://securityronin.github.io/signal-desktop-forensic/privacy/) · [服务条款](https://securityronin.github.io/signal-desktop-forensic/terms/) · © 2026 Security Ronin Ltd
标签:HTTP工具, Rust, Signal, SQLCipher, 可视化界面, 安全助手, 数字取证, 数据解密, 网络流量审计, 自动化脚本