portwatcher/rust-blind-watermark

GitHub: portwatcher/rust-blind-watermark

Rust 盲图像水印库与 CLI 工具,支持基于密钥在 RGB/RGBA 图像中嵌入和盲提取文本或字节 payload,并对常见图像编辑操作保持一定鲁棒性。

Stars: 0 | Forks: 0

# blind-watermark `blind-watermark` 是一个 Rust 库,用于在原始的 RGB8/RGBA8 图像缓冲区中嵌入和提取盲文本或字节 payload。 盲提取意味着提取过程只需要带水印的图像缓冲区和相同的密钥/配置。它不需要原始图像、原始文本或调用方提供的水印长度。 此 crate 是最初的 v0.1 核心实现。它使用确定性的密钥派生块置换、自描述的认证 payload 帧、仅亮度的 Haar + DCT 系数对嵌入以及重复比特恢复。它并不宣称具备任意的防篡改能力。 ## 示例 ``` use blind_watermark::{ embed_text, extract_text, ColorMode, ImageBufferRef, PixelFormat, RobustnessProfile, ThreadConfig, WatermarkConfig, WatermarkKey, WatermarkStrength, }; let width = 384; let height = 384; let stride = width * 3; let image = vec![128u8; stride * height]; let config = WatermarkConfig { key: WatermarkKey::from_bytes([7u8; 32]), strength: WatermarkStrength::High, robustness: RobustnessProfile::Balanced, color_mode: ColorMode::LumaOnly, threads: ThreadConfig::Single, }; let input = ImageBufferRef { data: &image, width: width as u32, height: height as u32, stride, pixel_format: PixelFormat::Rgb8, }; let watermarked = embed_text(input, "hello watermark", &config)?; let recovered = extract_text(watermarked.as_ref(), &config)?; assert_eq!(recovered, "hello watermark"); # Ok::<(), blind_watermark::WatermarkError>(()) ``` ## API 概览 - `embed_text(image, text, config) -> Result` - `extract_text(image, config) -> Result` - `embed_payload(image, payload_bytes, config) -> Result` - `extract_payload(image, config) -> Result, WatermarkError>` - `capacity(image, config) -> Result` - `estimate_robust_capacity(image, config) -> Result` 核心 API 作用于借用的输入缓冲区,并返回具有所有权的输出缓冲区。RGBA 的 alpha 字节将被完整保留。 ## CLI 此 crate 还构建了一个小型的 `bwm` 二进制程序,用于面向 JPEG 的冒烟测试: ``` cargo run --bin bwm -- embed \ --key 0707070707070707070707070707070707070707070707070707070707070707 \ --input tests/fixtures/test.jpg \ --output tests/artifacts/test-watermarked.jpg \ --text 'bwm-ok-2026' cargo run --bin bwm -- extract \ --key 0707070707070707070707070707070707070707070707070707070707070707 \ --input tests/artifacts/test-watermarked.jpg ``` `bwm extract` 会尝试原始图像方向以及 180、90 和 270 度旋转。它不执行任意裁剪的重同步。 ## CI 与发布 GitHub Actions 配置了以下功能: - 推送、拉取请求和手动触发时的 CI:格式检查、Clippy、完整测试以及明确的 JPEG 鲁棒性测试。 - 在 `v*.*.*` 标签上发布:验证并为 Linux x86_64、macOS x86_64、macOS aarch64 和 Windows x86_64 构建 `bwm` 发布二进制文件,将它们附加到 GitHub 发布中,并将 crate 发布到 crates.io。 crates.io 发布优先通过 GitHub Actions OIDC 使用 crates.io Trusted Publishing。对于首次发布,请创建一个新的 crates.io API token,并将其存储为名为 `CARGO_REGISTRY_TOKEN` 的仓库 secret。 ## Payload 格式 在嵌入之前,payload 字节被封装为以下格式: - magic bytes:`BWMK` - 格式版本:`1` - 标志:`u16` - payload 长度:`u32` - payload 类型:文本 UTF-8 或二进制 - 密钥派生的 BLAKE3 MAC 截断至 128 位 - payload 字节 完整的帧在嵌入前会使用密钥派生的流进行白化处理。提取过程会解码重复的比特位,对帧进行解白化处理,检查头部和 MAC,然后返回 payload。 ## 鲁棒性配置 鲁棒性是概率性的,取决于图像大小、payload 大小、强度以及嵌入后应用的变换。 当前已测试的行为涵盖: - 无攻击的 RGB/RGBA 往返 - UTF-8 文本往返 - 密钥错误失败 - 容量拒绝 - alpha 保留 - 确定性输出 - 轻微亮度和小范围确定性噪声测试 - 通过 `bwm` 二进制程序进行的固定装置 JPEG 嵌入/编辑/提取,包括 JPEG 质量-85 重编码、10% 同画布边界裁剪损坏、可见的对角线和矩形遮挡、更强的亮度/对比度/噪声变化,以及旋转 180 度的已编辑 JPEG `Robust` 配置使用高重复率,其 payload 容量远低于 `Fast` 或 `Balanced`。当前版本未实现任意几何同步,因此在依赖此 crate 之前,应针对您自己的图像集评估偏移裁剪、缩放、截图 pipeline 以及社交媒体重压缩等情况。 ## 实现说明 对于每个选定的 8x8 块,当前实现会: 1. 将 RGB/RGBA 像素转换为亮度, 2. 应用一次局部 Haar 变换, 3. 对低频子带应用 4x4 DCT, 4. 通过强制两个中频 DCT 系数之间的排序边距来嵌入一个比特, 5. 应用逆 DCT 和逆 Haar, 6. 根据生成的亮度差值偏移 RGB 通道,同时保持 alpha 不变。 这是一个紧凑的变换域实现,符合任务书中 v0.1 的目标,但它还不是一个完整的 DWT-DCT-SVD 移植。该 crate 保持了公共 API 和模块边界的就绪状态,以便未来进行 SVD 或 ECC 升级。 ## 限制 没有任何水印能够在任意的破坏性编辑中幸存。此 crate 有意使用“鲁棒盲水印”的措辞,而不是“防篡改水印”。如果图像被严重裁剪、旋转、缩小、模糊、压缩、覆盖或颜色截断,提取可能会失败。 容量取决于图像大小。在嵌入大型 payload 之前,请使用 `capacity`。
标签:Rust, 可视化界面, 图像处理, 数字水印, 盲水印, 网络流量审计, 通知系统