Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
RRC_steganography — 通过旋转范围编码将秘密信息嵌入到LLM生成的文本中,实现可证明安全的语言学隐写。包含嵌入、提取和往返验证脚本。 | Kitploit
工具/GitHubGitHub/ryehr/rrc_steganography
隐写术密码学机器学习论文与研究学习与教育AI 安全
GitHubryehr/rrc_steganography

RRC_steganography

通过旋转范围编码将秘密信息嵌入到LLM生成的文本中,实现可证明安全的语言学隐写。包含嵌入、提取和往返验证脚本。

查看仓库
61801个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

RRC 隐写术

旋转范围编码(RRC)隐写术 —— 一种高效且可证明安全的 语言隐写方法,可将秘密消息嵌入由大型语言模型生成的 自然语言文本中。

论文:Efficient Provably Secure Linguistic Steganography via Range Coding (ACL 2026)

工作原理

步骤描述
嵌入(算法 3)将秘密消息转换为十进制值,并在由语言模型概率分布和 PRNG 生成的偏移量引导的收缩区间内迭代地旋转它。每次旋转步骤产生一个 token。
提取(算法 4)在隐写文本上重新运行语言模型以恢复区间边界,然后反向旋转回原始十进制值并将其二值化。

旋转机制解决了普通范围编码隐写术的两个问题:

  1. 概率分布保持 —— 旋转后的秘密值在每个区间内均匀分布,因此 token 选择遵循原始语言模型分布。
  2. 新鲜随机性 —— 每一步使用新的 PRNG 偏移量可防止随机性重用。

仓库结构

.
├── rrc_core.py        # 算法 3 和 4,由每个入口点共享
├── RRC_embed.py       # 嵌入 CLI
├── RRC_extract.py     # 提取 CLI(报告恢复准确率)
├── test_roundtrip.py  # 跨多个消息长度的往返测试
├── fastest_embed.py   # 嵌入速度基准测试
├── 0.Prompts.tsv      # 1000 个提示(C4 序列的前约 10 个词)
└── requirements.txt

编码器和解码器共享 rrc_core.py,而不是各自持有循环的独立副本。双方必须逐位一致,而两个独立维护的副本之间的分歧只会表现为往返失败,而不会在检查时显现。

环境要求

  • Python >= 3.10
  • PyTorch >= 2.0
  • Transformers >= 4.35(已测试至 5.x)
pip install -r requirements.txt

快速开始

1. 验证正确性

python test_roundtrip.py                                  # GPT-2, 32/128/512 bits
python test_roundtrip.py --model meta-llama/Llama-2-7b-hf

2. 嵌入

python RRC_embed.py \
    --language_model meta-llama/Llama-2-7b-hf \
    --bit_length 128 --key 42 --top_k -1

3. 提取

python RRC_extract.py \
    --language_model meta-llama/Llama-2-7b-hf \
    --bit_length 128 --key 42 \
    --input_file 1.RC_decimal_Llama-2-7b-hf_bit128.tsv

编码器记录其嵌入的秘密以及携带该秘密的 token id,因此提取会报告恢复率。对两个接收方模型进行评分:

  • ids —— 接收方获得 token 序列。这隔离了编码方案;任何低于 100% 的结果都是数值或逻辑故障。
  • text —— 接收方获得去 token 化后的字符串并再次对其进行 token 化,正如文本信道所要求的那样。重新 token 化并不总能重现发送方的分词,因此这是一个下界;两者之间的差距衡量的是分词歧义而非编码方案。在 Llama-2-7b 上,128 位时:ids 为 100%,text 约为 91%。

重要:发送方和接收方必须共享语言模型、密钥、位长度和 top-k 设置,并且还必须运行相同的硬件和库版本。参见数值要求。

CLI 参数

由 RRC_embed.py 和 RRC_extract.py 共享:

参数默认值描述
--language_modelmeta-llama/Llama-3.1-8BHuggingFace 模型 id
--bit_length128秘密消息长度(以位为单位)
--top_k-1Top-k 截断;-1 = 完整词汇表
--key42对称密钥 K(PRNG 种子)
--precision_margin40超出 2**bit_length 所需位数的小数位数
--max_ctx_len3900KV 缓存窗口
--deviceautocuda 或 cpu

RRC_embed.py 还接受 --prompts、--output、--limit、--seed、 --max_tokens、--resume、--no_verify,以及用于跨进程分片提示集的 --part / --part_max(--part_max 3 配合 --part 0,1,2,每个 GPU 一个)。

RRC_extract.py 还接受 --input_file、--mode {ids,text,both}、 --limit 和 --verbose。

数值要求

RRC 将宽度为 2**l 的区间缩小到宽度约 1,因此恢复值对相对误差的敏感度是 2**l 倍:在 128 位时,链中任何位置 1e-16 的相对扰动都会使结果偏移约 1e22,而容差为 0.5。提取不会优雅降级——它要么返回消息,要么返回无关的位。在 Llama-2-7b 上测得:

设置概率的相对扰动提取
重复相同的 batch-1 解码0(逐位相同)有效
batch 2 / 8 / 16 中的同一行~1e-2失败
对提示进行左填充~1e-2失败
一次 teacher-forced 传递而非增量解码~4e-3失败

两个后果塑造了实现。批处理不可用,因此序列一次处理一个。并且接收方逐步重放发送方的增量解码,而不是在单次前向传递中对隐写文本进行评分,即使它事先持有每个 token。两种捷径测得约快 9 倍,且都不保持概率。

logits 之后的所有内容都是 float64,并在 CPU 和 GPU 上产生逐位相同的边界,因此前向传递是唯一将隐写文本与其硬件绑定的步骤。

小数精度

精度由消息长度推导得出,为 ceil(bit_length * log10(2)) + margin,并在其他任何内容运行之前设置。它随消息缩放:2**256 需要 78 位数字,2**8192 需要 2466 位。

低于该阈值的精度不会干净地失败。秘密值的低位数字被舍入掉,区间在几个 token 内崩溃,终止测试提前触发,因此一次运行可以完成并报告在算术上不可达的数字。无论消息长度如何都将精度保持在 50 位数字会得到:

bits50 位数字时的利用率完成的样本使用推导精度
256157.05%8/20100.17%
512299.67%9/20102.48%
1024660.91%7/10102.58%
20481046.40%1/598.18%
40962483.92%3/3,未引发错误100.87%
81924766.49%1/299.07%

--precision_margin 调整推导最小值之上的余量;最小值本身是强制执行的。

已验证的终止

算法 3 在 (L + R) / 2 - d_s 落入 (-0.5, 0.5] 时停止。该测试可能在区间窄于 1 时触发,此时窗口 [mid - 0.5, mid + 0.5) 比承载它的区间更宽。反向旋转是模区间宽度的等距变换,因此跨越切口的窗口会使接收方距离 d_s 整整一个区间。

因此,发送方在决定停止之前会重放接收方的反向旋转,如果重放未返回秘密,则再发出一个 token。重放是纯 Decimal 工作(约 0.05 ms,而一次前向传递约 20 ms),因此该保护措施没有可测量的成本。--no_verify 禁用它。

在 Llama-2-7b 上测得:

bits无保护时恢复有保护时
128291/300 (97.0%)300/300
51264/65 (98.5%)40/40
102420/2020/20
204810/1010/10

在 128 位时,保护措施额外生成了 0.095% 的 token。1024 和 2048 位的样本太少,无法界定该比率——在 3% 的比率下,0/20 比非 0/20 更可能——因此它们不能证明更长的消息表现不同。有保护时,370/370 被恢复。

没有保护时,发送方无法分辨差异:它报告成功并发出一个解码为无关位的隐写文本。该比率随抽样而变化;一次 99 个提示的运行未见到任何失败,而 3% 的比率大约有 5% 的时间会产生这种情况,并且重新运行时它完全重现。相同的样本在从 45 到 200 位数字的每个可用精度下都失败,因此该行为源于终止测试而非算术。

该保护措施通过禁用保护进行嵌入并运行真实提取器来对照真实情况进行检查:它标记的样本正是接收方失败的样本,没有假阳性,也没有遗漏。

性能说明

在 Llama-2-7b 上,语言模型前向传递占生成步骤的 95–97%,而 7B fp16 模型的 batch-1 解码处于内存带宽屋顶线(每 token 约 13.5 ms,而实测约 18.7 ms)。因此嵌入速度跟随模型的解码速度,编码本身对其影响很小。

在较小的模型上,前向传递不再占主导地位,每步的 CPU 工作变得可见。在 GPT-2 上以 128 位端到端测得,共享机器上每格 100 条消息:

torch CPU 线程bits/s
11320, 1205
161232, 756
20(torch 默认)352

吞吐量由 CPU 线程争用而非编码路径中的任何内容决定,并且多线程数字在每次运行之间不可重现。因此每个入口点都调用 torch.set_num_threads(1):这里的每个 CPU 操作都是单次词汇表大小的传递,太小而无法从线程池中获益,又大到在线程池与其他工作争用时严重受损。这带来的是可预测性,而不是在空闲机器上的加速。

其余每步选择在孤立情况下都很廉价,并且在一个线程下不会可测量地改变端到端吞吐量;做出这些选择是因为它们没有成本:

  • 熵在概率的主机副本上减少,该步骤已经需要它,而不是使用单独的 GPU 内核和同步。它是一个报告的统计量,不会反馈到编码中。
  • 候选选择对单调边界谓词进行二分搜索,每步评估约 15 次 Decimal 乘积,而不是每个扫描的候选一次。这界定了最坏情况;线性扫描在性能分析中达到索引 2923。
  • 边界被写入预分配的缓冲区,而不是为每个 token 分配一个词汇表大小的张量。
  • 生成超过 token 预算的提示会被跳过,而不是用新的秘密重试:预算取决于提示的熵,因此重新抽取消息不会改变结果。
  • Logits 被切片为 min(config.vocab_size, len(tokenizer.vocab)) 以使其与分词器对齐。这避免了重新分配嵌入矩阵,并使模型对象保持不变,这在同一模型跨运行共享时很重要。

实测吞吐量

128 位消息,完整词汇表,温度 1.0,RTX 6000 Ada,一个 CPU 线程,GPU 其他方面空闲。每个模型 100 条消息(Llama-2-7b 为 60 条),每一条都经过往返并检查:

模型嵌入提取tokens/msg利用率
GPT-21386 bits/s1385 bits/s22.399.4%
OPT-1.3b754 bits/s753 bits/s30.498.7%
Llama-2-7b183 bits/s183 bits/s45.498.9%

提取以嵌入速度运行,因为两者每个 token 都执行一次前向传递,而反向旋转链与它们相比可忽略不计。

吞吐量对 GPU 上的其他作业不敏感——在满载的卡上会得到相差几个百分点以内的相同数字——因为工作负载是一系列延迟受限的单 token 前向传递,而不是任何使设备饱和的东西。约 6% 的运行间变化来自抽取的提示:bits/s 是 bit_length / time,而时间随消息所需的 token 缩放,因此较低熵提示的样本读起来更慢。

技术说明:Decimal 取模

Python 的 Decimal % 使用截断除法,可能返回负余数(Decimal('-19672') % Decimal('65536') 给出 -19672,而不是 45864)。反向旋转需要真正的取模,因此 decimal_mod 使用向下取整除法语义:

def decimal_mod(a, m):
    return a - m * (a / m).to_integral_value(rounding=ROUND_FLOOR)

引用

@inproceedings{yan-murawaki-2026-efficient,
    title = "Efficient Provably Secure Linguistic Steganography via Range Coding",
    author = "Yan, Ruiyi  and
      Murawaki, Yugo",
    editor = "Liakata, Maria  and
      Moreira, Viviane P.  and
      Zhang, Jiajun  and
      Jurgens, David",
    booktitle = "Proceedings of the 64th Annual Meeting of the {A}ssociation for {C}omputational {L}inguistics (Volume 1: Long Papers)",
    month = jul,
    year = "2026",
    address = "San Diego, California, United States",
    publisher = "Association for Computational Linguistics",
    url = "https://aclanthology.org/2026.acl-long.39/",
    doi = "10.18653/v1/2026.acl-long.39",
    pages = "890--907",
    ISBN = "979-8-89176-390-6"
}
下载工具