Delta-Sec/StegX

GitHub: Delta-Sec/StegX

一款采用认证加密与抗隐写分析技术的现代 LSB 图像隐写工具包,专注于在 PNG 图像中安全隐蔽地嵌入和提取机密数据。

Stars: 24 | Forks: 4

![Stegx_Github](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/c2b8e70da7082128.jpg) # StegX 2.0: 基于 Argon2id + AES-GCM 的认证非线性 LSB 隐写术 [![Python 版本](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/) [![许可证: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Parrot OS 已验证](https://img.shields.io/badge/Parrot%20OS-Verified-brightgreen?logo=linux)](https://parrotsec.org/) [![隐写分析已测试](https://img.shields.io/badge/Steganalysis-Tested-blueviolet)]() [![安全性: AES-GCM + ChaCha20](https://img.shields.io/badge/Security-AES--256--GCM%20%2B%20ChaCha20--Poly1305-critical)]() [![KDF: Argon2id](https://img.shields.io/badge/KDF-Argon2id-brightgreen)]() [![测试: 255 项通过](https://img.shields.io/badge/Tests-255%20passed-brightgreen)]() [![在 Grokipedia 中被引用](https://img.shields.io/badge/Referenced%20in-Grokipedia-orange)](https://grokipedia.com/page/Steganography_in_Python) StegX 使用密码洗牌的 LSB 嵌入和认证加密技术将文件隐藏在 PNG 图像中。版本 2 是一次彻底的安全重写,围绕版本化的容器格式构建,引入了 Argon2id 密钥派生、域分离的 HKDF 子密钥、可抵御卡方隐写分析的 LSB 匹配 (±1) 嵌入,以及(可选的)ChaCha20-Poly1305 双密码、F5 风格的矩阵嵌入、自适应代价图过滤、密钥文件双因素认证(2FA)、合理推诿的诱饵负载,以及跨多个载体图像的 k-of-n Shamir 秘密共享。 ## 2.0 版本更新内容 ### 密码学 * **Argon2id** 取代 PBKDF2 成为默认的密码 KDF(仍可通过 `--kdf pbkdf2` 选择使用 600k 次迭代的 PBKDF2,并且为了向后兼容,仍可读取传统的 v1 格式)。 * **HKDF 子密钥** 从一个主密钥派生出独立的 AES-GCM、ChaCha20-Poly1305、位置洗牌种子和哨兵密钥——因此缓慢的密码 KDF 每次操作只需运行一次。 * **带有关联数据的 AEAD** 将整个容器头部(版本/标志/KDF 参数/盐值/nonce)绑定到密文,因此任何篡改都会使 GCM 标签失效。 * **双密码模式**(`--dual-cipher`)使用独立密钥在 AES-256-GCM 之上叠加 ChaCha20-Poly1305——深度防御,以应对其中任何一种密码被灾难性破解的情况。 * **密钥文件双因素认证**(`--keyfile PATH`)将外部二进制文件混合到 KDF 输入中;仅凭密码将不再足够。 ### 压缩 * **多算法压缩器**(`--compression best`,默认):每个负载都会并行输入到 zlib-9、LZMA2-extreme、bzip2-9、zstd-22、**带有捆绑预训练字典的 zstd-22** 以及 brotli-11 中;体积最小的输出将胜出并在元数据中打上标签,以便解码器知道如何逆向还原。对于可压缩数据(文本/JSON/代码),通常比单独使用 zlib **小 40-75%**。该字典(约 5 KiB,随程序发布在 `src/stegx/data/stegx_dict_v1.zstd`)是在常见文件类型头(PE/ELF/PDF/ZIP/JSON/文本/图像)的语料库上训练的,因此它特别适用于小于 1 KiB 的小型负载,在这些负载下普通的 zstd 需要支付其头部开销。随机/加密负载将直接退回到 `none`(存储原始字节)。 * **`--compression fast`** 适用于对延迟要求严格的场景——仅使用 zlib,行为与 2.0 之前的版本相同。 ### 多文件批量嵌入 * `stegx encode -f a.zip b.txt c.pdf -o out.png` 将多个输入文件打包到一个内存中的 tar 存档中,然后再进行压缩和加密。在解码时,元数据中的 bundle 标志会触发透明解压——每个成员都将以其原始文件名写入目标目录。在解压期间会拒绝路径遍历尝试(`../`、绝对路径、符号链接、设备文件)。 ### 载体选择 (`stegx pick-cover`) * `stegx pick-cover --dir ./covers --payload secret.zip` 根据容量和香农熵对目录中的每张图像进行排名,并为给定的负载挑选最合适的图像。这对于选择既有足够空间又有足够纹理来隐藏 LSB 修改的载体非常有用。 ### 隐写术 * **LSB 匹配 (±1)** 默认取代了 LSB 替换——击败了卡方和 RS 分析所利用的不对称性。 * **自适应嵌入**(`--adaptive`)通过代价图过滤像素位置。可通过 `--adaptive-mode` 使用两种模式: - `laplacian`(默认,快速)——保留边缘响应最高的位置。足以应对经典的隐写分析器。 - `hill`——受 HILL 启发的代价图(Li 等人,ICIP 2014),带有 KB 高通 + 双重盒模糊管线。以少量的额外计算成本更强地抵御基于 CNN 的隐写分析器(SRNet / YeNet)。 * **矩阵 (F5) 嵌入**(`--matrix-embedding`)使用 Hamming(7,3) 编码,将每位更改率降低约 2.3 倍。 * **每图像 HMAC 哨兵** 取代了固定的 `STEGX_EOD` 标记,因此哨兵随密码和载体而变化,无法进行模式匹配。 * **容量上限**(`--max-fill PCT`,默认为 25%)拒绝过大的负载,这些负载很容易被 CNN 隐写分析器检测到。 * **PNG 元数据剥离** 清除了 Pillow 的 `Software` 指纹块;输出的编码器参数与载体匹配(`compress_level`),因此文件大小和块比较不会标记隐写图像。 ### 操作强化 * 默认使用 **`getpass`** 输入密码,外加用于脚本编程的 `--password-stdin`。`-p` 仍然有效但会发出强烈警告——它可能会泄漏到 shell 历史记录和 `ps` 中。 * **`zxcvbn` 密码强度关卡**:在分数 < 3 时发出警告;`--strict-password` 会直接拒绝弱密码。 * **统一的解码错误消息**——错误的密码、错误的密钥文件和非 StegX 图像都报告相同的文本,消除了信息泄露的预言机。 * 通过 `hmac.compare_digest` 进行 **恒定时间哨兵比较**。 * 在 Linux / macOS 上通过 ``mlock(2)`` 以及在 Windows 上通过 ``VirtualLock`` 为每个主密钥和 HKDF 子密钥实现 **操作系统级别的内存锁定**——防止秘密被分页到交换区 / 休眠文件。如果操作系统拒绝锁定(例如没有 ``CAP_IPC_LOCK`` 或足够的工作集配额),则回退到普通的内存清零。 * 使用后对主密钥和派生子密钥进行 **尽力而为的内存擦除**。 * **`--fips` 模式** 将流水线限制为经过 FIPS 140 验证的原语:PBKDF2-HMAC-SHA256、AES-256-GCM、HKDF-SHA256 和仅限 zlib 的压缩。拒绝使用 Argon2id、ChaCha20-Poly1305、brotli、lzma、bz2 和 zstd。适用于受合规约束的环境。 * **版本化容器**(magic 字节 + 版本字节 + 标志)使未来的算法升级不会造成破坏性变更。 ### 高级功能 * **合理推诿诱饵**(`--decoy-file` / `--decoy-password`)——载体被分割成两个不相交的区域;任一密码仅能解锁其对应的区域。如果没有两个密码,观察者无法判断第二个区域是否携带数据。 * **偏执狂载体分割**(`--always-split-cover`)——始终保留诱饵那一半,并在没有提供真实诱饵时用加密随机位填充它。均衡两半的 LSB 修改密度,使统计观察者无法区分“正在使用诱饵”和“没有诱饵”的情况。消耗 50% 的载体容量;仅限按需启用。 * **k-of-n Shamir 分割**(`stegx shamir-split` / `stegx shamir-combine`)——将秘密分布在 n 个载体图像中;任意 k 个即可重建它。 ## ⚠️ 相对于 1.x 的破坏性变更 v2 的负载格式与 StegX ≤ 1.2.1 生成的隐写图像**不向后兼容**(哨兵、种子派生和容器布局均已更改)。StegX 2.0 *仍然可以通过*回退路径透明地读取 v1 隐写图像,但新的隐写图像使用 v2。请重新编码任何重要内容。 ## 安装 可以使用您喜欢的包管理器在多个平台上安装 StegX 2.0。 ### 📦 PyPI (Python 包) 大多数用户的推荐方式。需要 Python 3.8+。 ``` pip install stegx-cli ``` *可选:* 要安装压缩算法和密码强度评估功能: ``` pip install stegx-cli[compression,strength] ``` ### 🐧 Arch Linux (AUR) 如果您使用的是 Arch Linux 或 Manjaro,可以从 Arch 用户仓库安装原生软件包: ``` yay -S stegx ``` ### 🐳 Docker Docker Hub 和 GitHub Container Registry 上提供了预构建的多架构 Docker 镜像。 ``` docker pull ayhamasfoor/stegx:latest ``` **使用示例:** ``` docker run --rm -i -v "$PWD:/work" ayhamasfoor/stegx \ encode -i /work/cover.png -f /work/secret.zip \ -o /work/out.png --password-stdin <<< "YourStrongPassword" ``` ### 🛍️ Snap (Ubuntu & Linux) 在任何受支持的 Linux 发行版上通过 Snap Store 安全安装: ``` sudo snap install stegx ``` ### 🛠️ 从源代码构建 如果您喜欢直接从源代码运行: ``` git clone https://github.com/Delta-Sec/StegX cd StegX pip install -e . ``` *注意:`completions/` 目录中提供了 Shell 补全功能。* ## 持续集成 GitHub Actions 工作流已检入 `.github/workflows/` 中: * [ci.yml](.github/workflows/ci.yml) 在每次推送 + PR 时运行: - 在 Python 3.9 / 3.10 / 3.11 / 3.12 / 3.13 (Linux) + 3.12 Windows 行上的 `pytest` 矩阵。 - `docker build` + 对构建镜像内部的 `stegx --version` 和 `stegx benchmark` 进行冒烟测试。 - `python -m build` + `twine check` 为每次成功的运行生成构件。 * [release.yml](.github/workflows/release.yml) 在 `v*.*.*` 标签(或手动调度)上触发: - 构建并发布 wheel 和 sdist 到 PyPI(需要一个 `PYPI_API_TOKEN` 仓库机密——或者切换到 OIDC 受信任的发布;工作流中有注释指导)。 - 使用标准的 `GITHUB_TOKEN` 构建并将多架构(`amd64` + `arm64`)Docker 镜像推送到 `ghcr.io//stegx`。 ## 用法 StegX 提供四个子命令:`encode`、`decode`、`shamir-split`、`shamir-combine`。 ### 编码(隐藏文件) ``` stegx encode -i -f -o [options] ``` 默认情况下(`getpass`),密码从 TTY 提示符读取。如需在脚本中使用,请通过 `--password-stdin` 管道输入。旧的 `-p` 标志仍可接受,但会发出警告。 **常用选项:** | 标志 | 描述 | |------|-------------| | `-p, --password PW` | 密码(不推荐——可能泄漏到 shell 历史记录中)。 | | `--password-stdin` | 从 stdin 的单行读取密码。 | | `--keyfile PATH` | 将外部二进制文件作为第二因素混入 KDF。 | | `--yubikey` | 要求 YubiKey HMAC-SHA1 响应(插槽 2)作为额外的硬件因素。需要 `pip install ykman`。 | | `--panic-password PW` | 启用自毁:在解码时输入此密码会在报告之前擦除真实区域的 LSB。与 `--decoy-file` 互斥。 | | `--panic-decoy PATH` | 在自毁后返回的牺牲性负载(省略 = 静默模式)。 | | `--polyglot-zip PATH...` | 在写入隐写 PNG 后,附加包含列出文件的 ZIP 存档,使得输出同时是有效的 PNG 和有效的 ZIP。仅限公共侧信道;不影响隐藏的 StegX 负载。 | | `--kdf {argon2id,pbkdf2}` | 基于密码的 KDF(默认:argon2id)。 | | `--dual-cipher` | 在 AES256-GCM 之上叠加 ChaCha20-Poly1305。 | | `--adaptive` | 仅嵌入到高边缘代价区域中(抵御 CNN 隐写分析器)。 | | `--matrix-embedding` | 针对密文主体使用 F5 风格的 Hamming(7,3) 矩阵嵌入。 | | `--max-fill PCT` | 拒绝填充超过容量 PCT % 的负载(默认为 25%)。 | | `--strict-password` | 拒绝 zxcvbn 分数 < 3 的密码(默认:警告)。 | | `--no-preserve-cover` | 保存时不保留载体的 PNG 编码器参数。 | | `--no-compress` | 禁用负载压缩。 | | `--compression {fast,best}`| `fast` = 仅限 zlib-9;`best`(默认)尝试 zlib、LZMA、bzip2、zstd-22(+ 捆绑字典变体)和 brotli-11,存储最小的结果。 | | `--always-split-cover` | 偏执模式:始终保留诱饵那一半并填充随机位,即使未设置 `--decoy-file`。减半载体容量;按需启用。 | | `--fips` | 限制为经过 FIPS 140 验证的原语(PBKDF2 + AES-GCM + zlib)。拒绝 Argon2id / ChaCha / brotli / lzma / bz2 / zstd。 | | `--decoy-file PATH` | 在真实负载旁隐藏诱饵负载(合理推诿)。 | | `--decoy-password PW` | 诱饵的密码(如果省略则提示输入)。 | **从 URL 获取载体图像:**`-i`/`--image` 参数接受 `http(s)://…` URL。StegX 将字节下载到临时文件中(仅接受 `Content-Type: image/*`,上限为 50 MiB,超时时间为 30 秒),使用 Pillow 验证图像,将其用作载体,并在退出时删除临时文件。仅限图像解码——不涉及任何形式的脚本执行或运行。 **示例:** ``` # Interactive: 通过 getpass 提示输入密码 stegx encode -i landscape.png -f secret.pdf -o out.png # 直接从 URL 提取 Cover (Imgur, S3 等) stegx encode -i https://i.imgur.com/abc123.png -f secret.zip -o out.png # Hardened: 双密码 + adaptive + matrix embedding + keyfile stegx encode -i cover.png -f secret.bin -o out.png \ --dual-cipher --adaptive --matrix-embedding --keyfile token.bin # Plausible-deniability 诱饵 stegx encode -i cover.png -f real.zip -o out.png \ --decoy-file harmless.txt ``` ### 解码(提取文件) ``` stegx decode -i (-d | --stdout | -d -) [--keyfile PATH] ``` 除非 `-p`、`--password-stdin` 或 `--keyfile` 更改了身份验证输入,否则将通过交互方式提示输入密码。所有失败模式(密码错误、密钥文件错误、非 StegX 图像、数据损坏)都会故意报告**相同的**错误消息——以避免向攻击者泄露信息。 **输出目标:** * `-d ` — 将提取的文件写入 ``(默认行为)。 * `--stdout` — 将解密后的字节写入标准输出(不保留文件名)。使用此选项可直接管道传输到另一个程序而不触及磁盘。 * `-d -` — 与 `--stdout` 相同。 **示例:** ``` # 常规磁盘输出 stegx decode -i out.png -d ./extracted # 将解密后的字节通过管道传递给另一个工具 (例如将 SSH 密钥传递给 ssh-agent) stegx decode -i out.png --stdout --password-stdin <<< "$PW" | ssh-add - # 通过管道传递给 jq、openssl 等 stegx decode -i out.png --stdout | jq . ``` ### 基准测试您的机器 ``` stegx benchmark [--iterations N] [--size-kib K] stegx benchmark --calibrate [--target-ms 500] ``` 对 Argon2id KDF 的运行进行计时,并在混合 ASCII 样本上运行压缩多路复用器。`--calibrate` 扫描 Argon2id 内存大小,以找到在您的 CPU 上最接近 `--target-ms` 的设置——这在提升 `src/stegx/kdf.py` 中的项目级默认值之前非常有用。 ### 轮换隐写图像的凭证 ``` stegx rewrap -i stego.png [-o new.png] ``` 在现有隐写图像上轮换密码 / 密钥文件 / YubiKey,**无需在磁盘上实际还原明文**。旧凭证在内存中解密内部负载,旧的 LSB 位置会被加密噪声覆盖,使其无法复活,然后使用新凭证重新嵌入负载。当怀疑密码泄露或在进行定期密钥轮换时非常有用。 ### 哈希链审计日志 每个 `encode` / `decode` / `rewrap` 子命令都接受 `--audit-log PATH`。每次操作都会追加一条 JSONL 记录,包含: * UTC 时间戳 * 操作名称 + 成功/失败位 * 载体和/或隐写文件的 SHA-256 * 所使用的与安全相关的标志名称(从不包含值) * 指向前一条记录的 `chain` 哈希的 `prev` 链接 + 针对记录规范形式的自身 `chain` 哈希 篡改任何中间记录都会破坏后续所有的 `chain` 哈希;`stegx.audit_log.verify_chain(path)` 会遍历文件并报告第一行错误记录。负载内容永远不会被记录。 ### Shamir k-of-n 分割 / 合并 将一个秘密分割为隐藏在 `n` 个载体图像中的 `n` 个份额——任意 `k` 个即可重建它。 ``` # Split: 跨 5 个 cover 的 5 选 3 stegx shamir-split -k 3 -n 5 -f secret.bin \ -c c1.png c2.png c3.png c4.png c5.png -O shares/ # Combine: 任意 3 个 shares 恢复 secret stegx shamir-combine -i shares/stego_share_01.png \ shares/stego_share_02.png shares/stego_share_03.png \ -d ./out -o recovered.bin ``` ## 技术细节 (v2) ### 嵌入字节流布局(在像素 LSB 内部) ``` [16 B sentinel ] HMAC(sentinel_key, cover_fingerprint)[:16] [56 B header ] magic | version | kdf_id | flags | kdf_params | salt(16) | aes_nonce(12) | chacha_nonce(12) | inner_ct_length(4) [N B ciphertext] AEAD(AES-256-GCM, optionally chained with ChaCha20-Poly1305) ``` ### 密钥层次结构 ``` position_key = Argon2id(password ‖ keyfile?, FIXED_APP_SALT, default_params) ├─ HKDF("stegx/v2/pixel-shuffle-seed" ‖ fingerprint) → shuffle seed └─ HKDF("stegx/v2/sentinel" ‖ fingerprint) → sentinel key master_key = Argon2id(password ‖ keyfile?, random_salt_from_header, params_from_header) ├─ HKDF("stegx/v2/aes-256-gcm") → AES key (32 B) └─ HKDF("stegx/v2/chacha20-poly1305") → ChaCha key (optional) ``` Argon2id 默认设置:`time_cost=3`、`memory_cost=64 MiB`、`parallelism=4`。 ### 加密 1. 构建内部负载:`[4-B metadata_len][JSON metadata][file data (可选择 zlib 压缩)]`。 2. 派生 `master_key`(Argon2id);通过 HKDF 派生 `aes_key` 和可选的 `chacha_key`。 3. `aes_ct = AES-GCM(aes_key, aes_nonce, inner, aad=header_with_length_zeroed)`。 4. 如果使用了 `--dual-cipher`:`final_ct = ChaCha20-Poly1305(chacha_key, chacha_nonce, aes_ct, aad=header)`。 5. 最终容器:`header.pack() ‖ final_ct`(长度字段在步骤 3 之后填充)。 ### 嵌入 1. `position_key` → `seed_int` → 洗牌每个像素通道的索引。 2. 如果使用了 `--adaptive`:丢弃超出顶级拉普拉斯边缘百分位数的位置。 3. 如果使用了 `--decoy-file`:通过仅依赖载体指纹的确定性洗牌,将所有位置划分为两个不相交的区域;真实负载使用一个区域,诱饵使用另一个。 4. 在哨兵 + 头部 + 密文上进行 LSB 匹配 (±1);可选地仅在密文主体上进行矩阵(F5 Hamming 7-3)操作。 5. 保存为 PNG,剥离元数据块并匹配载体的 `compress_level`。 ### 提取 1. 派生 `position_key` → 洗牌后的位置 → 读取前 16 个字节;与 HMAC 派生的哨兵进行比较(恒定时间)。 2. 匹配成功时,读取 56 字节的头部,解析 KDF 参数,派生 `master_key`。 3. 读取 `inner_ct_length` 字节的密文,如果有标记则逆向解密双密码,使用 AES-GCM 解密。AEAD 标签验证头部未被篡改。 4. 解析元数据,如果有标记则解压,使用净化的文件名写入输出目录。 哨兵优先于 AEAD 标签检查意味着**密码错误 / 密钥文件错误 / 非 StegX 图像**都会因相同的通用错误而失败——没有提供预言机泄露。 ## 🛡️ 安全性与隐写分析抗性 StegX 已针对多种隐写分析工具和技术进行了测试。它能够**抵御提取**并**避免被**以下工具检测到: | 工具 | 状态 | |------------------|--------------| | Stegseek | ❌ 提取失败 | | zsteg | ❌ 未发现模式 | | binwalk | ✅ 输出无异常 | ## 故障排除 / 常见问题 * **错误:图像容量不足:** 文件(在经过潜在的压缩和加密开销之后)太大,无法放入所选载体图像的 LSB 中。请尝试使用更大的图像,确保载体图像为 PNG/BMP 格式,或隐藏较小的文件。 * **错误:解密失败。密码可能不正确...:** 此 `InvalidTag` 错误几乎总是意味着解码时提供的密码与编码时使用的密码不匹配,或者隐写图像文件已被修改或损坏。 * **错误:找不到隐藏数据标记...:** 找不到 `STEGX_EOD` 哨兵。这表明该图像可能不是由 StegX 创建的,或者已被显著更改(例如,使用 JPEG 等有损压缩重新保存)。 * **错误:负载或元数据似乎已损坏:** 提取的数据可以解密,但其内部结构(元数据长度、JSON 格式或解压大小)不一致。图像可能已损坏。 * **不支持的图像模式:** 确保输入的载体图像采用受支持的格式(RGB、RGBA、L、P)。CMYK 等格式不直接支持 LSB 嵌入。 * **输出图像大于预期:** PNG 压缩可能会有所不同。使用 PNG 的主要目的是 LSB 数据的无损存储,而不是最小的文件体积。 ## 许可证 本项目基于 MIT 许可证授权 - 详见 [许可证](https://github.com/Delta-Sec/StegX/blob/main/LICENSE) 文件。
标签:AES-GCM, Argon2id, ChaCha20-Poly1305, ChaChi平方攻击规避, F5矩阵嵌入, LSB隐写, Parrot OS, plausible deniability, Python, Shamir秘密共享, 二进制发布, 图像隐写, 密码学, 开源工具, 手动系统调用, 提示词注入, 数字取证, 数字水印, 数据加密, 数据隐藏, 无后门, 网络安全, 自动化脚本, 请求拦截, 跨格式兼容, 逆向工具, 防分析逃避, 防检测, 隐写分析, 隐写术, 隐私保护