本文档是
strhide::stego对外接口的权威说明:公开面分层、命名规范、 凭据优先级、第三方编译期定制配方(以 CarrotHash 为范本)与 CLI 映射。 线格式细节见 spec/CONTENT-ENVELOPE.md 及其载体文档 CONTENT-PNG / CONTENT-JPEG / CONTENT-HEVC / CONTENT-AUDIO, 密钥派生见 spec/CRYPTO.md,架构总览见 ARCHITECTURE.md。随接口变更同步更新。阶段 4 变更:
StegoOptions已删除并拆成强类型选项 (EmbedOptions/ProbeOptions/ExtractOptions/InspectOptions/VerifyOptions+StegoTuning);方言类型由params::Profile改为stego::params::StegoProfile(facade::Dialect组合它);统一入口的_with_profile后缀改为_with_dialect。V4 内容信封变更:凭据统一为
Credential::{Password, FileKey}; 套件枚举CipherSuiteId(1 = AES-256-GCM 默认,2 = ChaCha20-Poly1305, append-only);选项新增key/suite_id/extensions: Vec<Tlv>; 旧CipherSuite/SUITES/FeatureWord/header_v3::Superblock已删除,FeatureWord的 epsilon 量化改为header::quantize_epsilon_k。 CLI 暴露--cipher-suite(别名--suite)、--key-file(embed/capacity/ extract/inspect/verify,接受 32 原始字节或 64 位十六进制)与--max-payload(extract);--extensions仍未接线。2026-11-04 API 整理:
StegoCodec::id()更名为StegoCodec::wire_id(),明确它返回信封头部的线格式 id(Auto与Stc都为 1),不是 Rust 层的算法区分;heif::BridgeTargetKind::DirectSpatial已删除(全仓从未构造该变体,unci原始像素并非 PNG 流)。
| 层 | 内容 | 稳定性承诺 |
|---|---|---|
| 稳定面 Stable | 统一入口 stego::{embed_carrier, embed_carrier_with_dialect, extract_carrier, extract_carrier_with_dialect, extract_carrier_payload, inspect_carrier[_with_dialect], verify_carrier[_with_dialect], probe_carrier_capacity[_with_dialect], list_stego_algorithms, algorithms_for_format};选项 EmbedOptions / ProbeOptions / ExtractOptions / InspectOptions / VerifyOptions / StegoTuning / SafetyPolicy / SafetyLevel / SafetyEnforcement / PngParams / JpegParams / AudioParams / StegoCodec / ExtractParams / Freshness;凭据 core::crypto::Credential(Password / FileKey);套件 core::crypto::CipherSuiteId;扩展 stego::Tlv;方言 params::StegoProfile;结果 StegoCapacityInfo / StegoHeaderInfo / StegoVerifyResult / EmbedOutput / StegoAlgorithmInfo / core::media::MediaInfo;格式身份 format::{JpegFormatProfile, PngFormatProfile, HevcFormatProfile, GridRule, DEFAULT_JPEG_FORMAT, OFFICIAL_PNG_FORMAT, DEFAULT_HEVC_FORMAT};CostModelRegistry;traits::{PngCostModel, JpegCostModel, JpegGeometry};io::{embed_carrier_file, extract_carrier_file, extract_carrier_file_payload};facade::StrHide::stego() |
破坏性变更只随 major |
| 专家面 Expert | 域引擎入口 png::engine::{embed_png, extract_png, probe_png_capacity}、jpeg::engine::{embed_jpeg, extract_jpeg, probe_jpeg_capacity}、heif::*、hevc::{embed_hevc, extract_hevc, probe_hevc_capacity};图像编解码与解析;模型实现 png::cost::*、jpeg::cost::* |
小版本可演进,CHANGES 公告 |
内部面 Internal(#[doc(hidden)],无承诺) |
coding、envelope、header、prng、wavelet、jpeg::{dht, geometry, header_v4, precover, v3_layout}、hevc::{bitstream, error, heif_boxes, slot, sniff} |
路径可达但不入文档;随时可变 |
命名规范:按载体格式命名(Jpeg / Png / Hevc 前缀),参数类型 XxxParams、
线格式身份 XxxFormatProfile、常量 DEFAULT_XXX_FORMAT / OFFICIAL_XXX_FORMAT。
统一入口以 carrier(载体)命名,域引擎与 facade 与之一致。
只读结果:公开结果结构体(EmbedStats、EmbedOutput、StegoEmbedResult、StegoHeaderInfo、StegoVerifyResult 等)标注 #[non_exhaustive],下游只读字段、不使用结构体字面量构造或穷尽解构;未来新增字段不构成破坏性变更。
// 推荐入口(自动格式嗅探:PNG / JPEG / HEIF / HEVC Annex-B / MP4·MOV)
stego::embed_carrier(carrier_bytes, &payload, &options) // 官方方言
stego::embed_carrier_with_dialect(carrier_bytes, &payload, &options, &dialect) // 私有方言
stego::extract_carrier[_with_dialect](carrier_bytes, &options[, &dialect])
stego::probe_carrier_capacity[_with_dialect](carrier_bytes, &options[, &dialect])| 旋钮 | 解析顺序 |
|---|---|
| credential(KDF 凭据) | Credential::{Password(str), FileKey(&[u8; 32])}:password 与 key 互斥(同时给非空值报错);都没有时取 StegoProfile.default_secret,再没有则公开默认常量 PUBLIC_DEFAULT_SECRET。空串密码视为未提供 |
| suite(AEAD 套件) | EmbedOptions.suite_id(运行时覆盖)> WireCipherProfile.default_suite(编译期)。读取端始终以头部 suite_id 为准,ExtractParams.allowed_suites 只做试枚举白名单 |
| domain(HKDF 域隔离) | EmbedOptions.domain(运行时)> StegoProfile.domain(编译期)> 官方默认派生 |
| safety(容量策略) | EmbedOptions.safety: SafetyPolicy { level, enforcement }——单一事实源,tuning 不携带 safety |
| freshness | EmbedOptions.freshness: Freshness(Random 生产默认;Seeded([u8; 32]) 可复现运行,PNG/JPEG/HEVC 全部支持;CLI 为 --seed) |
| extensions | EmbedOptions.extensions: Vec<Tlv>;ProbeOptions.extensions 必须与将要写入的一致 |
| 线格式身份 | 仅来自 StegoProfile.{jpeg, png, hevc}(编译期),无运行时覆盖——可切换的格式就是可枚举的指纹 |
规则:读写必须一致的量(P 类)走 StegoProfile 或 facade::Dialect 并保持两侧相同;
只影响写侧行为的量(L 类)随便每次调用变。
阶段 4 起写侧与读侧的选项彻底分开:提取端不再被迫传代价图超参数,
extract_carrier 头部那句 png_params.validate()? 的误拦也随之消失。
use strhide::crypto::CipherSuiteId;
use strhide::stego::{
EmbedOptions, ExtractOptions, ExtractParams, ProbeOptions, StegoTuning, SpatialAlgorithm,
PngParams, SafetyLevel, SafetyEnforcement, Tlv,
};
// 写侧:给算法与参数,二者绑在同一个枚举臂里,不可能错配格式。
let embed = EmbedOptions::default()
.with_password("pw")
.with_suite_id(1) // 1=AES-256-GCM(默认),2=ChaCha20-Poly1305
.with_extensions(vec![Tlv { type_id: 0x01, value: b"x".to_vec() }])
.with_safety(SafetyLevel::High, SafetyEnforcement::Advisory)
.with_tuning(StegoTuning::Png { model: SpatialAlgorithm::Hill, params: PngParams::default() });
// 读侧:只有凭据与上限(默认 max_pbkdf2_iterations = 200,000)。
let extract = ExtractOptions::default()
.with_password("pw")
.with_limits(ExtractParams::default());
// 只读探测:与 embed 同一组调参、同一套扩展,容量答案才对得上将要执行的那次嵌入。
let probe = ProbeOptions::default()
.with_tuning(embed.tuning.clone())
.with_extensions(embed.extensions.clone());所有选项与参数类型(EmbedOptions / ProbeOptions / ExtractOptions /
InspectOptions / VerifyOptions、PngParams / JpegParams /
ExtractParams / SafetyPolicy,以及结构域 ReadOptions / WriteOptions /
RestoreOptions)都以 Default 起步、用 with_* 逐项设置;字段为 Option
的可选量另有 with_*_option(Option<T>) 形式。它们均为 #[non_exhaustive],
下游不要使用结构体字面量构造或穷尽解构。
StegoTuning 是 Auto 与四个按格式分臂的联合体(content-* 特性未启用时对应变体不编译):
pub enum StegoTuning {
#[default] Auto,
Png { model: SpatialAlgorithm, params: PngParams },
Jpeg { model: JpegAlgorithm, params: JpegParams },
Hevc { mode: HevcMode, params: HevcParams },
Audio { params: AudioParams },
}AudioParams 目前是空结构体且为 #[non_exhaustive]:音频引擎的容量、槽位顺序与漂移预算全部
由载体自身的采样格式与安全档位推导,提取端不读代价模型,因此当前没有可调项。变体的作用是
把音频域显式钉住(与 PNG/JPEG/HEVC 对称),并让后续新增的调优旋钮以加字段而非改变枚举形状
的方式落地。用 StegoTuning::audio(AudioParams::default()) 构造。
SafetyLevel 实现 FromStr:paranoid|high|balanced 或数字别名 0|1|2。
以 CarrotHash 为范本——一份 const Dialect 声明全部私有方言,
cargo build 即得与官方互不兼容的二进制,零运行时成本:
use strhide::facade::Dialect;
use strhide::stego::format::{HevcFormatProfile, JpegFormatProfile, PngFormatProfile};
use strhide::stego::params::StegoProfile;
// 以官方常量为模板,只替换派生标签/几何。
// 字段全集与默认值见 format::JpegFormatProfile / HevcFormatProfile / PngFormatProfile 的 rustdoc。
const STEGO_JPEG: JpegFormatProfile = JpegFormatProfile { /* cover_digest_tag + cipher + 44B 几何 */ };
const STEGO_PNG: PngFormatProfile = PngFormatProfile { /* 派生标签 + cipher + body 引用 */ };
const STEGO_HEVC: HevcFormatProfile = HevcFormatProfile {
/* cipher + magic_label + cover_salt + stc_h/stc_u */
};
pub const DIALECT: Dialect = Dialect::new()
.with_default_secret("acme-deployment-secret") // 两域共用一把部署密钥
.with_stego_profile(
StegoProfile::new()
.with_stego_domain("org.acme.stego") // 可选:域隔离
.with_jpeg_format(STEGO_JPEG)
.with_png_format(STEGO_PNG)
.with_hevc_format(STEGO_HEVC),
);要点:
- 改任意派生标签即产生不同线格式;官方二进制读私有载体报
NoHiddenData(与错密码不可区分),反之亦然。 - HEVC 的
magic_label:官方格式的魔数按SHA-256(magic_label ‖ effective_secret)[..4]派生——私有构建改标签即可 消除开源指纹,且无凭据者无法用固定魔数判定载体存在性(头部槽位仅由 参数集决定,与密码无关,这是设计要求;威胁模型见 spec/CONTENT-HEVC.md)。 - 套件默认值在
WireCipherProfile.default_suite中;私有构建可改默认套件, 但读写仍以头部suite_id为准(1=AES-256-GCM,2=ChaCha20-Poly1305)。 - 只想私有化图像域时用
StegoProfile;Dialect::with_default_secret会同时 设置结构域与图像域两半,两域派生域不同,同一字符串得到两把不相关密钥。 - 仅开启
features = ["content-png"]/["content-jpeg"]/["content-hevc"]即可只编入需要的内容域引擎;strhide::stego::io::embed_carrier_file提供 临时文件 + rename 原子提交、.bak备份与时间戳保留,宿主无需自建 I/O。 - 文件级便捷入口(
StrHide::stego().embed_file/extract_file)内部委托 同一stego::io实现;GUI 不依赖cli特性即可用。
核心库提供算法元数据自省机制(StegoAlgorithmInfo),消除前端与调用方的硬编码:
use strhide::stego::{list_stego_algorithms, algorithms_for_format, StegoAlgorithmInfo};
use strhide::formats::FileFormat;
// 获取全量算法列表(覆盖 PNG, JPEG, HEVC, Audio)
let all_algos: Vec<StegoAlgorithmInfo> = list_stego_algorithms();
// 获取适用于特定格式的算法(如 PNG -> HILL, S-UNIWARD, MiPOD)
let png_algos = algorithms_for_format(FileFormat::Png);
for info in png_algos {
println!("{}: {} ({})", info.id, info.name, info.desc);
}支持算法矩阵:
- PNG:
hill(默认),suniward,mipod - JPEG:
uerd(默认),juniward,jmipod - HEVC:
hevc(CABAC 旁路符号位原位隐写,支持 MP4, MOV, MKV, HEIF/HEIC, Annex-B) - Audio:
wav_pcm(WAV PCM LSB 匹配),flac_residual(FLAC 预测残差多项式匹配)
- 自定义代价模型:实现
traits::PngCostModel/JpegCostModel, 经专家面域引擎入口以&dyn传入(见examples/stego_profile.rs)。 注意:PNG 提取端由 64B V4 基础头(algorithm_id)声明算法, 统一入口不接受 trait 对象;自有模型请直接调用域引擎,并保证嵌入与 提取传入同一模型实例。 - 容量探测前置嗅探:
formats::sniff::sniff_bytes(bytes) -> Option<FileFormat>, 调用方可在嵌入前预判格式与路由(CarrierFormat枚举在阶段 0 已删除: 它与FileFormat重复且漏了 MP4)。
| 命令 | 库入口 | 说明 |
|---|---|---|
embed |
embed_carrier_with_dialect |
日常层:-t/-d/-p/-o/--in-place/-a/--safety/--enforce-safety;专家层按格式分成两节——PNG Spatial Tuning(--exclusion-rate/--p1-window/--p2-window)与 JPEG DCT Tuning(--neighbor-weight/--stc-h);Stego Envelope 节:--key-file/--cipher-suite(别名 --suite)/--seed;隐藏参数(hide = true,--help 不展示但可解析):--slot-budget 及上述六个调参项;Reproducibility 节:--seed;--dry-run 全内存演练不落盘(rust/src/cli/args.rs:427-530) |
extract |
extract_carrier_with_dialect |
只有凭据与上限参数:-p/--key-file/--max-payload;PNG 代价图参数、算法、排除率、codec、h/u 等全部由载体头自描述,ExtractArgs 不暴露 --p1-window/--p2-window,提取端也无需重复;-a/--auto 在无内容域载荷时回退结构域 read;支持 CARRIER... + -o <DIR> 批量 |
capacity |
probe_carrier_capacity_with_dialect |
独立只读探测子命令(sth capacity,别名 sth c / sths c),--json 输出 StegoCapacityInfo;--exact 强制全量精确扫描(长视频默认开启前 20% 样本加权快速估算);与 embed 共享同一组调参/凭据参数(同一 StegoTuningArgs),因此探测结论可与写入参数逐项对齐 |
容量口径(max_raw_payload_bytes):按最小信封开销(BODY_OVERHEAD = 22,
不含文件名;携带文件名额外消耗 1 + name_len 字节,见
docs/CHANGES-20261104.md P2-8);且已按引擎工作内存预算折算(PNG 8 GiB)。
统一入口(probe_carrier_capacity[_with_dialect] / embed_carrier[_with_dialect] /
embed_carrier_file / facade)还会为最长 255 字节文件名预留
MAX_FILENAME_OVERHEAD = 256 字节,因此报告值是对文件载荷安全的上限;
Payload::bytes 裸载荷实际可多写 256 字节(见
tests/test_lifecycle/stego.rs::test_stego_capacity_model_is_tight)。
专家面域引擎(probe_png_capacity / probe_jpeg_capacity 等)不做该预留,
两条 API 的数值相差 256 字节。recommended_max_bytes / tier_limits
是各引擎 enforce_safety 使用的原值,不参与该预留。
未实现的 CLI 能力:--extensions(TLV 扩展区);库 API 已支持,CLI/GUI 未接线。
--key-file(Credential::FileKey)与 --max-payload(ExtractParams.max_payload_bytes)
已接线(GUI 仍只有密码)。套件参数为 --cipher-suite(别名 --suite,1/2,
对所有内容格式生效,归在 Stego Envelope 分组)。
提取端自描述范围(无需在提取时重复):算法 id、排除率(exclusion_permille)、
PNG 的 p1_window / p2_window / neg_log2_epsilon / sigma、codec、h、u、
通道模式、format_id、suite_id、body_len、扩展区(64B/44B/32B 基础头)。
png::engine::extract_png_with_keys 直接用头部值覆盖传入的 PngParams
(png/engine.rs:2042-2046)。
调用方仍需提供:凭据(password/key/domain)、方言(Dialect)、
以及可选的 ExtractParams::max_payload_bytes 上限。
配置文件中可用 [stego] 段固定三个部署策略项,命令行标志始终优先:
[stego]
safety = "high" # paranoid | high | balanced
enforce_safety = false # true 时超限直接拒绝而非只告警
algorithm = "auto"tests/cli_help_guard.rs:localize(en/zh)后全命令树每个可见参数 help 非空——stego 参数 help 的事实源在 i18n 消息表,条目缺失即测试失败。hevc::engine::dialect_tests:DEFAULT_HEVC_FORMAT字面量与 spec/CONTENT-HEVC.md 钉死;魔数随凭据变化;公开默认密钥唯一。tests/test_lifecycle/facade.rs:一个Dialect::with_default_secret必须同时隔离两域;只私有化图像域时结构域仍保持官方行为。