aloshdenny/reverse-SynthID
GitHub: aloshdenny/reverse-SynthID
该项目通过频谱分析逆向工程 Google Gemini 的 SynthID 水印,实现了水印的高精度检测与高保真移除。
Stars: 2493 | Forks: 237
Reverse-Engineering SynthID
通过频谱分析发现、检测并精确移除 Google 的 AI 水印
## 概述
本项目对 **Google 的 SynthID** 水印系统进行了逆向工程——这是嵌入在 Google Gemini 生成的每张图像中的不可见水印。仅使用信号处理和频谱分析(无需访问专有的编码器/解码器),我们完成了以下工作:
1. **发现** 了与分辨率相关的载波频率结构
2. **构建了检测器**,以 90% 的准确率识别 SynthID 水印
3. **开发了多分辨率频谱绕过方案** (V3),在任何图像分辨率上实现了 **75% 的载波能量降幅**、**91% 的相位一致性降幅** 和 **43+ dB 的 PSNR**
[VT-OxFF](https://github.com/VT-0xFF) 构建了一个非常酷的可视化工具,用于查看 SynthID 水印如何添加到图像的过程中,请点击[此处](https://vt-0xff.github.io/SynthID-Explained/)查看(也可在仓库说明中找到)!
## 🚨 招募贡献者:帮助扩充代码本
我们正在积极收集由 Nano Banana Pro 生成的**纯黑和纯白图像**,以改进多分辨率水印提取。
如果您能生成这些图像:
- 分辨率:任意(种类越多越好)
- 内容:**全黑 (#000000)** 或 **全白 (#FFFFFF)**
- 来源:仅限 Nano Banana Pro 输出
### 如何贡献
1. 通过将纯黑/纯白图像附加到 Gemini 并提示它“原样重现”,生成一批黑/白图像。
2. 将它们上传到我们的 **Hugging Face 数据集**:[aoxo/reverse-synthid](https://huggingface.co/datasets/aoxo/reverse-synthid)
- `gemini_black_nb_pro/` (用于黑色图像)
- `gemini_white_nb_pro/` (用于白色图像)
3. 在 HF 数据集仓库上开启一个 Pull Request
这些参考图像对于以下方面**至关重要**:
- 载波频率发现
- 相位验证
- 提高跨分辨率鲁棒性
### 下载参考图像
参考图像托管在 Hugging Face 上,以保持 git 仓库轻量:
```
pip install huggingface_hub
python scripts/download_images.py # download all
python scripts/download_images.py gemini_black # download specific folder
```
数据集:[huggingface.co/datasets/aoxo/reverse-synthid](https://huggingface.co/datasets/aoxo/reverse-synthid)
### 与众不同之处
与暴力方法(JPEG 压缩、噪声注入)不同,我们的 V3 绕过方案使用的是 **多分辨率 SpectralCodebook**——这是一个存储在单个文件中的、针对每种分辨率的水印指纹集合。在绕过时,代码本会自动选择匹配的分辨率配置文件,从而能够在任何图像尺寸上进行精确的频段级移除。
## 主要发现
### 水印与分辨率相关
SynthID 根据图像分辨率在**不同的绝对位置**嵌入载波频率。在 1024x1024 下构建的代码本无法直接移除 1536x2816 图像中的水印——因为载波位于完全不同的频段中。
| 分辨率 | 主载波 (fy, fx) | 一致性 | 来源 |
|:----------:|:--------------------:|:---------:|:------:|
| **1024x1024** | (9, 9) | 100.0% | 100 张黑色 + 100 张白色参考图 |
| **1536x2816** | (768, 704) | 99.6% | 88 张带水印的内容图像 |
这就是为什么 V3 代码本为**每种分辨率存储单独的配置文件**,并在绕过时自动选择。
### 相位一致性 - 固定的模型级密钥
来自同一 Gemini 模型的所有图像中,水印的相位模板是**完全相同的**:
- **绿色通道** 携带最强的水印信号
- 载波处的 **跨图像相位一致性**:>99.5%
- **黑/白交叉验证** 通过 |cos(phase_diff)| > 0.90 确认真正的载波
### 载波频率结构
在 1024x1024 下(基于黑/白参考图),主载波位于低频网格上:
| 载波 (fy, fx) | 相位一致性 | 黑/白一致性 |
|:-----------------:|:---------------:|:-------------:|
| (9, 9) | 100.00% | 1.000 |
| (5, 5) | 100.00% | 0.993 |
| (10, 11) | 100.00% | 0.997 |
| (13, 6) | 100.00% | 0.821 |
在 1536x2816 下(基于随机带水印内容),载波位于高得多的频率上:
| 载波 (fy, fx) | 相位一致性 |
|:------------------:|:---------------:|
| (768, 704) | 99.55% |
| (672, 1056) | 97.46% |
| (480, 1408) | 96.55% |
| (384, 1408) | 95.86% |
## 架构
### 三代绕过方案
| 版本 | 方法 | PSNR | 水印影响 | 状态 |
|:-------:|:---------|:----:|:----------------:|:------:|
| **V1** | JPEG 压缩 (Q50) | 37 dB | ~11% 相位下降 | 基线 |
| **V2** | 多阶段变换(噪声、颜色、频率) | 27-37 dB | ~0% 置信度下降 | 质量权衡 |
| **V3** | **多分辨率频谱代码本减法** | **43+ dB** | **91% 相位一致性下降** | **最佳** |
### V3 流水线(多分辨率频谱绕过)
```
Input Image (any resolution)
│
▼
codebook.get_profile(H, W) ──► exact match? ──► FFT-domain subtraction
│ (fast path)
└─ no exact match ──────► spatial-domain resize + subtraction
(fallback path)
│
▼
Multi-pass iterative subtraction (aggressive → moderate → gentle)
│
▼
Anti-alias → Output
```
1. **SpectralCodebook** 存储特定分辨率的配置文件(载波位置、幅度、相位)
2. **自动分辨率选择** 挑选精确配置文件或最接近的匹配项
3. **直接已知信号减法** 根据相位一致性和交叉验证置信度进行加权
4. **多轮进度表** 捕获前几轮遗漏的残留水印能量
5. **每通道加权** (G=1.0, R=0.85, B=0.70) 匹配 SynthID 的嵌入强度
## 结果 (V3 在 88 张 Gemini 图像上)
### 综合指标 (1536x2816, 激进强度)
| 指标 | 数值 |
|:-------|------:|
| **PSNR** | 43.5 dB |
| **SSIM** | 0.997 |
| **载波能量下降** | 75.8% |
| **相位一致性下降** (前 5 个载波) | **91.4%** |
### 跨分辨率质量
| 分辨率 | 匹配 | PSNR | SSIM |
|:----------:|:-----:|:----:|:----:|
| 1536x2816 | 精确 | 44.9 dB | 0.996 |
| 1024x1024 | 精确 | 39.8 dB | 0.977 |
| 768x1024 | 回退 | 40.6 dB | 0.994 |
## 快速开始
### 安装
```
git clone https://github.com/aloshdenny/reverse-SynthID.git
cd reverse-SynthID
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
```
### 1. 构建多分辨率代码本
通过 CLI:
```
python src/extraction/synthid_bypass.py build-codebook \
--black gemini_black \
--white gemini_white \
--watermarked gemini_random \
--output artifacts/spectral_codebook_v3.npz
```
或通过 Python:
```
from src.extraction.synthid_bypass import SpectralCodebook
codebook = SpectralCodebook()
# Profile 1:来自 black/white 参考图像 (1024x1024)
codebook.extract_from_references(
black_dir='gemini_black',
white_dir='gemini_white',
)
# Profile 2:来自水印内容图像 (1536x2816)
codebook.build_from_watermarked('gemini_random')
codebook.save('artifacts/spectral_codebook_v3.npz')
# Saved with profiles:[1024x1024, 1536x2816]
```
### 2. 运行 V3 绕过(任意分辨率)
```
from src.extraction.synthid_bypass import SynthIDBypass, SpectralCodebook
codebook = SpectralCodebook()
codebook.load('artifacts/spectral_codebook_v3.npz')
bypass = SynthIDBypass()
result = bypass.bypass_v3(image_rgb, codebook, strength='aggressive')
print(f"PSNR: {result.psnr:.1f} dB")
print(f"Profile used: {result.details['profile_resolution']}")
print(f"Exact match: {result.details['exact_match']}")
```
通过 CLI:
```
python src/extraction/synthid_bypass.py bypass input.png output.png \
--codebook artifacts/spectral_codebook_v3.npz \
--strength aggressive
```
**强度级别:** `gentle`(最小,~45 dB)> `moderate` > `aggressive`(推荐)> `maximum`
### 3. 检测水印
```
python src/extraction/robust_extractor.py detect image.png \
--codebook artifacts/codebook/robust_codebook.pkl
```
## 项目结构
```
reverse-SynthID/
├── src/
│ ├── extraction/
│ │ ├── synthid_bypass.py # V1/V2/V3 bypass + multi-res SpectralCodebook
│ │ ├── robust_extractor.py # Multi-scale watermark detection
│ │ ├── watermark_remover.py # Frequency-domain watermark removal
│ │ ├── benchmark_extraction.py # Benchmarking suite
│ │ └── synthid_codebook_extractor.py # Legacy codebook extractor
│ └── analysis/
│ ├── deep_synthid_analysis.py # FFT / phase analysis scripts
│ └── synthid_codebook_finder.py # Carrier frequency discovery
│
├── scripts/
│ └── download_images.py # Download reference images from HF
│
├── artifacts/
│ ├── spectral_codebook_v3.npz # Multi-res V3 codebook [1024x1024, 1536x2816]
│ ├── codebook/ # Detection codebooks (.pkl)
│ └── visualizations/ # FFT, phase, carrier visualizations
│
├── assets/ # README images and early analysis artifacts
├── watermark_investigation/ # Early-stage Nano-150k analysis (archived)
└── requirements.txt
```
## 技术深入解析
### SynthID 的工作原理(逆向工程)
```
┌──────────────────────────────────────────────────────────────┐
│ SynthID Encoder (in Gemini) │
├──────────────────────────────────────────────────────────────┤
│ 1. Select resolution-dependent carrier frequencies │
│ 2. Assign fixed phase values to each carrier │
│ 3. Neural encoder adds learned noise pattern to image │
│ 4. Watermark is imperceptible — spread across spectrum │
├──────────────────────────────────────────────────────────────┤
│ SynthID Decoder (in Google) │
├──────────────────────────────────────────────────────────────┤
│ 1. Extract noise residual (wavelet denoising) │
│ 2. FFT → check phase at known carrier frequencies │
│ 3. If phases match expected values → Watermarked │
└──────────────────────────────────────────────────────────────┘
```
### 多分辨率 SpectralCodebook
代码本捕获每种可用分辨率下的水印配置文件:
- **1024x1024 配置文件**:基于 100 张黑色 + 100 张白色纯色 Gemini 输出
- 黑色图像:水印几乎是整个像素内容
- 白色图像(反转):通过交叉验证确认载波
- 黑/白一致性 (|cos(phase_diff)|) 过滤掉生成偏差
- **1536x2816 配置文件**:基于 88 张多样的带水印内容图像
- 内容在图像间被平均化;固定的水印在相位一致性中保留下来
- 水印幅度估计为 `avg_mag x coherence^2`
### V3 减法策略
绕过方案使用**直接已知信号减法**(而非维纳滤波器):
1. **置信度** = phase_consistency x cross_validation_agreement
2. **DC 排除** —— 软斜坡抑制低频生成偏差
3. **每频段减法** = wm_magnitude x confidence x removal_fraction x channel_weight
4. **安全上限** —— 减法永远不会超过任何频段处图像能量的 90-95%
5. **多轮** —— 递减强度进度表(aggressive → moderate → gentle)捕获残留能量
## 核心模块
### `synthid_bypass.py`
**SpectralCodebook** —— 多分辨率水印指纹:
```
codebook = SpectralCodebook()
codebook.extract_from_references('gemini_black', 'gemini_white') # adds 1024x1024 profile
codebook.build_from_watermarked('gemini_random') # adds 1536x2816 profile
codebook.save('codebook.npz')
# Later:
codebook.load('codebook.npz')
profile, res, exact = codebook.get_profile(1536, 2816) # auto-select
```
**SynthIDBypass** —— 三代绕过方案:
```
bypass = SynthIDBypass()
result = bypass.bypass_simple(image, jpeg_quality=50) # V1
result = bypass.bypass_v2(image, strength='aggressive') # V2
result = bypass.bypass_v3(image, codebook, strength='aggressive') # V3 (best)
```
### `robust_extractor.py`
多尺度水印检测器(90% 准确率):
```
from robust_extractor import RobustSynthIDExtractor
extractor = RobustSynthIDExtractor()
extractor.load_codebook('artifacts/codebook/robust_codebook.pkl')
result = extractor.detect_array(image)
print(f"Watermarked: {result.is_watermarked}, Confidence: {result.confidence:.4f}")
```
## 参考资料
- [SynthID: Identifying AI-generated images](https://deepmind.google/technologies/synthid/)
- [SynthID 论文 (arXiv:2510.09263)](https://arxiv.org/abs/2510.09263)
## 👤 维护者与联系方式
**Alosh Denny**
AI 水印研究 · 信号处理
📧 **邮箱:** [aloshdenny@gmail.com](mailto:aloshdenny@gmail.com)
🔗 **GitHub:** https://github.com/aloshdenny
如需合作、研究讨论或贡献,欢迎随时联系或开启 issue/PR。
## 支持这项研究
本项目独立维护 —— 没有实验室资金,没有企业支持。
如果您或您的团队觉得这项工作有用,请考虑支持持续开发:
资金将用于计算成本(新分辨率配置文件的 GPU 工时)、数据集扩展和持续的绕过研究。
## 免责声明
本项目**仅用于研究和教育目的**。SynthID 是 Google DeepMind 拥有的专有技术。这些工具旨在用于:
- 关于水印鲁棒性的学术研究
- AI 生成内容识别的安全分析
- 理解扩频编码方法
**请勿使用这些工具将 AI 生成的内容伪造成人类创建的内容。**
标签:AI 安全, IaC 扫描, PSNR, Python, SynthID, 云资产清单, 信号处理, 傅里叶变换, 图像取证, 图像处理, 多分辨率, 对抗攻击, 敏感信息检测, 数字水印, 无后门, 水印检测, 水印移除, 水印绕过, 深度伪造, 生成式 AI, 相位一致性, 载波频率, 逆向工具, 逆向工程, 隐写术, 频域, 频谱分析, 频谱攻击