Mirrowel/plain-conversation-crypto
GitHub: Mirrowel/plain-conversation-crypto
一个研究型隐写术原型项目,探索将加密消息编码到自然对话文本中进行隐蔽传输的方法。
Stars: 0 | Forks: 0
# Plain Conversation Crypto
Plain Conversation Crypto 探索了在看似普通的对话文本中携带一条加密逻辑消息的方法。其灵感来源于电视剧《*The Agency*》第二季中描绘的加密聊天应用。
该实现也参考了 [`nethical6/conversation-steganography`](https://github.com/nethical6/conversation-steganography),并与之进行了直接对比。
Plain Conversation Crypto 是一个独立的原型,而不是该项目的分支或生产环境的替代品。
接收方粘贴属于同一逻辑消息的可见掩护气泡,即可获得一条明文消息。一条逻辑消息可能需要多个掩护气泡;基础协议不会对单独的隐藏消息进行批量处理。
## 安装
```
python -m pip install -e .
```
在 Windows 上,安装可选的 DirectML 运行时以使用兼容的 GPU:
```
python -m pip install -e ".[gpu-windows]"
```
对于 CUDA 12 GPU 和驱动程序,请改为安装指定的 CUDA 运行时配置:
```
python -m pip install -e ".[gpu-cuda12]"
```
CPU 推理是协议的默认设置。仅当双方使用相同的 provider/runtime 并有意选择特定于 provider 的载体 ID 时,才设置 `PCC_ONNX_PROVIDER=cuda` 或 `dml`。不能假设不同硬件上的 provider 输出在数值上是完全相同的。在受测的 GTX 1060 上,量化后的 SmolLM 计算图在 CUDA 上运行得更慢,因为 provider 的数据拷贝主导了序列生成过程。
载体 ID 还绑定了 ONNX Runtime、tokenizer、NumPy 和计算图执行设置;在将神经传输称为可移植之前,仍需要解决跨机器确定性的向量问题。
该 runtime 没有网络要求,也没有 LLM 要求。可选的神经载体使用本地的 ONNX 文件。请单独下载一个:
```
python tools/download_models.py smollm360
```
有关模型大小、哈希值、许可证以及受测模型的对比,请参阅[模型文档](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/models/README.md)。
## V2 CLI
将一条消息编码到本地 JSON 记录中:
```
python -m pcc encode-v2 \
--carrier packs/semantic_demo.json \
--profile secure \
--message-file secret.txt \
--sequence 0 \
--output transcript.json
```
如果需要面向复制/粘贴的输出,请省略 JSON 包装器:
```
python -m pcc encode-v2 \
--carrier packs/semantic_demo.json \
--profile secure \
--message "hello" \
--sequence 1 \
--plain-output > cover.txt
```
当省略 `--key` 时,系统会在不回显的情况下提示输入密钥。使用以下命令解码粘贴的、以空行分隔的掩护气泡:
```
python -m pcc decode-v2 \
--carrier packs/semantic_demo.json \
--profile secure \
--sequence 1 \
--plain-input < cover.txt
```
使用模型清单代替对话包时,相同的命令依然有效:
```
python -m pcc encode-v2 \
--carrier models/smollm2-360m-int8/carrier-huffman16.json \
--profile secure \
--message "hello" \
--sequence 1 \
--plain-output > cover.txt
```
`--key` 和 `--message` 可用于演示,但会将密钥暴露给 shell 历史记录和进程列表。在实际使用时,请使用提示输入的密钥和文件。口令必须至少包含 12 个字节;请使用随机密钥,而不是容易记忆的句子。
## 配置
| Profile | 加密 | 完整性 | 用途 |
|---|---|---|---|
| `secure` | AES-SIV | 128 位认证加密 | 强默认选项 |
| `compact` | ChaCha20 | 64 位截断 HMAC | 更小的认证消息,但防伪造余量较低 |
| `dense` | ChaCha20 | 无 | 仅用于被动保密实验 |
compact 和 dense 配置仍然使用强流密码。它们并未使用故意弱化的加密算法。其密度的提升来自于移除或减少认证开销。在无法容忍未检测到的篡改的场景下,绝不能使用 `dense`。
CLI 需要使用 `--allow-unsafe-dense` 才能运行未经认证的 dense 配置。
Compact 和 dense 模式的序列在同一密钥和载体下绝不能重复。复用会重复 ChaCha20 的 keystream,并可能暴露明文之间的关系。JSON 输出在省略序列时会生成一个随机序列;而普通的复制/粘贴输出则需要接收方也提供一个明确的序列。
库调用方必须始终显式传递 `sequence`。CLI 仅针对 JSON 输出生成随机序列,因为该序列由本地包装器携带。
所有配置都会在加密前进行压缩。密钥交织默认启用:它会在进行载体编码之前,对封装后的字节进行伪随机置换,且不会增加可见的数据量。双方可以通过 `--no-interleave` 明确选择退出。这只是一种混淆手段,并非额外的加密强度。
## 载体
### 确定性对话包
[`packs/semantic_demo.json`](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/packs/semantic_demo.json) 是无 LLM 的基线。它包含人工编写的、有明确类型的对话弧线,说话者交替发言,且每回合有四个独立的 8 选 1 从句组。它每回合携带 12 位数据,是最可预测的质量基线。
[`packs/dense_semantic_pack.json`](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/packs/dense_semantic_pack.json) 是一个实验性的、每回合携带 21 位的包。其更大的分支因子提高了密度,但每个生成的组合仍需经过人工审查。在通过该质量门禁之前,它不会被选为默认选项。
### 紧凑型统计模型
[`packs/chat_dense_model.json`](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/packs/chat_dense_model.json) 是一个基于 [`model_corpus.txt`](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/packs/model_corpus.txt) 语料库训练的小型 4 阶字词模型。它轻量且快速,仍作为一个选项提供。其输出比对话包更密集,但无法保证对话层面的连贯性。
[`packs/chat_topic_model.json`](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/packs/chat_topic_model.json) 捆绑了特定于主题的统计模型。它以牺牲密度为代价,减少了不相关的主题跳跃。
### 本地神经模型
经测试,质量和密度之间的最佳折衷方案是带有 [`carrier-huffman16.json`](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/models/smollm2-360m-int8/carrier-huffman16.json) 的本地 `SmolLM2-360M-Instruct` INT8 ONNX 模型。它利用模型概率构建密钥控的 Huffman 选择,而不是强制所有 top-k token 出现的频率完全相同。
135M 的同系列模型更轻量,但也更通用。Huffman-32 密度更高,但产生了过多奇怪的词法选择,因此仍处于实验阶段。此外还测试了 Gemma3-270M、Qwen3-0.6B 和 LFM2.5-350M。算术编码改善了一些样本,但目前这些模型中没有一个能被公认为与人类文本无法区分。
请参阅模型 README 和基准测试产物。神经质量检查在达到配置的尝试次数后会进行 fail-closed(关闭失败)处理;它们属于启发式方法,并不能证明其具有与人类无法区分的特性。
## 压缩
V2 会评估一个确定性的算法组合,并选择最短的自描述 payload:
- 精确的单字节公共消息代码。
- 原始字节回退。
- zlib 和原始 DEFLATE(带和不带固定聊天字典)。
- BZ2 和 LZMA 基线。
- Zstandard 级别 3 和 19(带和不带固定字典)。
- Brotli 质量 5 和 11。
- 自定义短语 token 编码以及 token 化的 DEFLATE/Zstandard 混合体。
每个候选方案都有边界解码器和往返测试。针对人工编写的 626 条消息的聊天语料库运行编解码器基准测试:
```
python tools/benchmark_compression_corpus.py \
--corpus packs/model_corpus.txt \
--output benchmarks/compression_chat_corpus.json
```
在该语料库上的观测结果,包含单字节模式标记:
| 输入 | 输入中位数 | 压缩后中位数 | 中位比率 | 主要胜出者 |
|---|---:|---:|---:|---|
| 1 个句子 | 48 B | 40 B | 0.847 | Dictionary DEFLATE,占 92.8% 的消息 |
| 2 个句子 | 97 B | 73 B | 0.765 | Brotli-11 57.8%, dictionary DEFLATE 39.0% |
| 3 个句子 | 146 B | 98 B | 0.680 | Brotli-11,85.1% |
对于高熵输入,原始字节毫无疑问会胜出。压缩无法使随机数据变得更小。
## 基准测试
运行载体对比:
```
python -m pcc benchmark \
--pack packs/semantic_demo.json \
--model packs/chat_dense_model.json \
--output benchmarks/carrier_comparison.json
```
基准测试会报告所有三种配置下 pack 和统计模型的可见字符数、掩护气泡数、压缩模式以及编码/解码时间。神经载体是单独进行基准测试的,因为其模型启动和 CPU 推理占据了主要耗时。
目前的工程结论是:
- 人工编写的 pack 是最强大的无 runtime 模型连贯性基线。
- 统计模型是最轻量的高密度选项,但其文本需要人工质量把关。
- SmolLM2-360M Huffman-16 是经测试最佳的神经质量/密度折衷方案,但如果不进行特定设备的优化,对于廉价手机而言它太慢了,无法作为默认选项。
- SmolLM2-135M 是实用的轻量级神经实验,但能明显感觉到质量下降。
- 更高的分支因子增加了名义上的密度,但很快就会违背正常文本的要求。
完整的基于源码的参考对比、模型扫描、算术编码实验和 GPU 计时研究详见[优化报告](https://github.com/Mirrowel/plain-conversation-crypto/blob/main/docs/optimization_report.md)。
## 安全边界
明文的安全边界在于加密配置,而不是 pack 或模型。Pack/模型产物可能已被攻击者知晓;口令仍必须保护明文。
secure 配置提供:
- Scrypt 密钥派生和 HKDF 域分离子密钥。
- 来自 `cryptography` 的 AES-SIV 认证加密。
- 将序列、载体身份、配置和交织模式绑定为关联数据。
- 针对错误密钥、错误载体、篡改、重排、截断和格式错误输入的测试。
该原型并不声称能够抵御专门受过训练以检测其生成分布的对手。它也无法隐藏时间、参与者身份、消息计数或社交图谱元数据。确切的可见文本至关重要;规范化、重写、智能标点符号替换或编辑都可能破坏解码。
即使生成的消息看起来很自然,也不能证明它与人类写作无法区分。应将该代码库视为用于实验、测量和讨论的平台,而不是一个已完成的的安全通信应用程序。
## 测试
```
python -m unittest discover -s tests -v
```
测试套件涵盖了 V1 回归行为、所有压缩候选方案、Unicode 和二进制往返测试、所有 V2 配置、两种载体、密钥交织、错误密钥、篡改、格式错误的 pack 以及 topic-model 的加载。
标签:DNS 反向解析, ONNX, Python, 密码学, 手动系统调用, 无后门, 逆向工具, 隐写术