neverlone/hushglyph

GitHub: neverlone/hushglyph

一个基于零宽 Unicode 字符的纯文本隐写 CLI 工具,可将秘密信息不可见地嵌入普通文本中,并可选 passphrase 加密保护。

Stars: 0 | Forks: 0

# hushglyph 使用零宽 Unicode 字符将秘密信息不可见地隐藏在看似普通的文本中,并提供可选的 passphrase,这样即使隐写文本被盗也无法单独使用。 ## 它是什么 / 为什么有趣 在任何两个词之间都有一个空格,而在空格之后你可以插入一个**零宽度**的字符:它渲染出来什么都没有,复制出来也什么都没有,大多数字体和终端会直接跳过它。`hushglyph` 将这个特性变成了一个微型隐写通道: - 你的秘密信息被转换为比特(bit)。 - 每个比特都会变成两个不可见的标记字符之一(`U+200B` 零宽空格 = `0`,`U+200C` 零宽非连字符 = `1`)。 - 这些标记被穿插到载体文本中,每个词的间隔处插入一个,并在前面加上一个 32 位的长度 header,以便解码器能确切知道 payload 在哪里结束。 - 可选地,在进行上述所有操作之前,秘密字节会使用 repeating-key XOR(一种经典的“玩具”密码,可以看作是在字节上运作的 Vigenère)进行扰乱。 它的密码学强度并不高,但这意味着仅凭隐藏的比特并不是明文:你还需要 passphrase。 最终生成的文本文件在人类看来——以及打印出来时——与原始载体文本逐字符完全相同,但却在其内部默默地携带了一条信息。你可以将其粘贴到电子邮件、文档或推文中;只要不对 Unicode 进行规范化处理,payload 通常就能保留下来。 ## 安装 / 运行 要求 Node.js >= 14。无依赖。 ``` git clone cd hushglyph npm test # run the smoke tests ``` 使用 `node bin/hushglyph.js ...` 直接运行,或者将其链接为 CLI: ``` npm link # makes the `hushglyph` command available globally ``` ## 用法 ``` hushglyph encode --cover (--secret "text" | --secret-file ) [--key ] [--out ] hushglyph decode --input [--key ] hushglyph capacity --cover ``` ### 示例 ``` $ node bin/hushglyph.js capacity --cover examples/cover.txt word gaps: 204 max payload: 172 bits (21 bytes) after the 32-bit length header $ node bin/hushglyph.js encode --cover examples/cover.txt \ --secret "meet at dawn" --key raven --out stego.txt wrote 1600 bytes to stego.txt $ wc -c examples/cover.txt stego.txt 1216 examples/cover.txt 1600 stego.txt $ diff examples/cover.txt stego.txt # 每一行在 raw bytes 上有所不同,但将它们粘贴到 browser/editor 中 # 它们渲染出来完全一样——差异 100% 是不可见字符 $ node bin/hushglyph.js decode --input stego.txt # 未提供 --key -> 无法读取的 non-printable byte 垃圾,而不是 secret $ node bin/hushglyph.js decode --input stego.txt --key raven meet at dawn ``` 即使没有任何可见的变化,`stego.txt` 也比载体文本大了 384 字节——这正是 32 位长度 header 加上“meet at dawn”每个比特(首先经过 XOR)对应的一个不可见字符的总和,每一个都被插入到一个词之后。 ## 工作原理 1. **容量**:载体文本的容量是其中空格字符(`' '`)的数量——每个空格都是一个比特的潜在插入点。`hushglyph capacity` 会报告这一点,这样你就可以根据你的秘密信息来调整载体文本的大小,或者根据你的载体文本调整秘密信息的大小。 2. **编码**:秘密字符串采用 UTF-8 编码,可选择与重复的 passphrase 进行 XOR,并在前面加上一个 32 位的大端序字节长度 header。然后从左到右遍历组合后的 bitstream;对于每个 `0` 比特,在载体文本的下一个空格后插入一个 `U+200B`,对于每个 `1` 比特,插入一个 `U+200C`。一旦 bitstream 耗尽,载体文本的其余部分将保持不变。 3. **解码**:扫描隐写文本中的 `U+200B`/`U+200C` 字符(忽略其他所有内容)。前 32 个比特表示以字节为单位的 payload 长度;接下来的 `length * 8` 个比特会被重新组合成字节,与 passphrase(如果提供)进行 XOR,并解码为 UTF-8。 4. **为什么还要使用 XOR?** 仅靠零宽隐写术只是“隐藏式安全”——任何知道寻找 `U+200B`/`U+200C` 的人都可以读取原始比特。添加基于 passphrase 的 XOR 意味着*比特*并不是信息本身;你还需要密钥,这与任何流密码的原理相同。 ## 测试 ``` npm test ``` 覆盖范围:包括有 passphrase 和没有 passphrase 的往返测试,字节完全相同的可见渲染,错误的密钥永远无法恢复真正的秘密信息,容量计算与 `encode` 实际接受的内容相符,解码没有隐藏 payload 的纯文本时会明确报错,以及全角 Unicode/emoji 秘密信息在往返测试中能够完整保留。 ## 许可证 MIT — 见 [许可证](LICENSE)。
标签:DNS 反向解析, GNU通用公共许可证, MITM代理, Node.js, Unicode, 信息隐藏, 数据可视化, 文本隐写, 文档结构分析, 自定义脚本