aegis-watermark 0.1.1__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aegis_watermark-0.2.0/PKG-INFO +83 -0
- aegis_watermark-0.2.0/README.md +51 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/cli.py +75 -9
- aegis_watermark-0.2.0/aegis/core/signature.py +158 -0
- aegis_watermark-0.2.0/aegis/handlers/image.py +69 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/handlers/ppt.py +34 -8
- aegis_watermark-0.2.0/aegis_watermark.egg-info/PKG-INFO +83 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis_watermark.egg-info/SOURCES.txt +1 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis_watermark.egg-info/requires.txt +1 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/setup.py +4 -3
- aegis_watermark-0.1.1/PKG-INFO +0 -104
- aegis_watermark-0.1.1/README.md +0 -73
- aegis_watermark-0.1.1/aegis/handlers/image.py +0 -15
- aegis_watermark-0.1.1/aegis_watermark.egg-info/PKG-INFO +0 -104
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/__init__.py +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/core/__init__.py +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/core/deep.py +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/core/frequency.py +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/core/spatial.py +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/handlers/__init__.py +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis/handlers/pdf.py +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis_watermark.egg-info/dependency_links.txt +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis_watermark.egg-info/entry_points.txt +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis_watermark.egg-info/top_level.txt +0 -0
- {aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aegis-watermark
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: 图片与PPT专业级隐形盲水印工具 | Professional blind watermarking tool for images and PPTX documents.
|
|
5
|
+
Home-page: https://github.com/your-repo/Aegis-Watermark
|
|
6
|
+
Author: LingQingyang
|
|
7
|
+
Author-email: 1739677116@qq.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: blind-watermark
|
|
14
|
+
Requires-Dist: opencv-python
|
|
15
|
+
Requires-Dist: numpy<2.0.0
|
|
16
|
+
Requires-Dist: click
|
|
17
|
+
Requires-Dist: Pillow
|
|
18
|
+
Requires-Dist: pyfiglet
|
|
19
|
+
Requires-Dist: rich
|
|
20
|
+
Requires-Dist: python-pptx
|
|
21
|
+
Requires-Dist: questionary
|
|
22
|
+
Requires-Dist: cryptography
|
|
23
|
+
Dynamic: author
|
|
24
|
+
Dynamic: author-email
|
|
25
|
+
Dynamic: classifier
|
|
26
|
+
Dynamic: description
|
|
27
|
+
Dynamic: description-content-type
|
|
28
|
+
Dynamic: home-page
|
|
29
|
+
Dynamic: requires-dist
|
|
30
|
+
Dynamic: requires-python
|
|
31
|
+
Dynamic: summary
|
|
32
|
+
|
|
33
|
+
# Aegis (神盾) - 专业级隐形水印与数字签名工具 🛡️
|
|
34
|
+
### Professional Blind Watermarking & Digital Signature Tool
|
|
35
|
+
|
|
36
|
+
Aegis 是一款结合了 **频域盲水印 (Blind Watermarking)** 与 **RSA 数字签名** 技术的版权保护工具。它不仅能为图像及 PPTX 文档嵌入肉眼不可见的“视觉指纹”,还能加盖不可伪造的“数字印章”。
|
|
37
|
+
|
|
38
|
+
Aegis is a copyright protection tool combining **frequency domain blind watermarking** and **RSA digital signatures**. It embeds invisible "visual fingerprints" and attaches unforgable "digital stamps" to images and PPTX documents.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🌟 核心亮点 | Key Features
|
|
43
|
+
|
|
44
|
+
- **视觉水印技术 (Visual Watermarking)**: 不同于脆弱的文本编码,Aegis 嵌入的是视觉轮廓,对截图、压缩、翻拍具有极强的抗性。
|
|
45
|
+
- **RSA-4096 数字签名 (Digital Signature)**: 集成自签名证书体系,一键证明身份并确保文件“未被篡改”。
|
|
46
|
+
- **SHA-256 安全加固 (Security Hardening)**: 支持任意长度字符串密钥,杜绝暴力破解撞库。
|
|
47
|
+
- **交互式控制台 (Interactive CLI)**: 中英双语菜单,无需记忆复杂指令,像使用独立 App 一样简单。
|
|
48
|
+
- **全自动文档保护 (Automated PPTX Protection)**: 自动识别并保护 PPT 内部的所有高价值图像素材。
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚀 快速开始 | Quick Start
|
|
53
|
+
|
|
54
|
+
### 1. 安装
|
|
55
|
+
```bash
|
|
56
|
+
pip install aegis-watermark
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. 身份初始化 (首次使用)
|
|
60
|
+
运行 `aegis` -> 选择 **身份管理 (Identity)** -> 输入你的姓名和邮箱,生成专属的加密证书。
|
|
61
|
+
|
|
62
|
+
### 3. 运行模式
|
|
63
|
+
- **嵌入 (Embed)**: 处理文件时,系统会询问是否附加数字签名。
|
|
64
|
+
- **提取 (Extract)**: 系统将自动校验数字签名(身份与完整性)并提取盲水印。
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🛠️ 技术栈 | Tech Stack
|
|
69
|
+
|
|
70
|
+
- **算法核心**: `blind-watermark` (DCT/DWT 变换)
|
|
71
|
+
- **安全保障**: `cryptography` (RSA-4096 / SHA-256 / X.509)
|
|
72
|
+
- **UI 引擎**: `Rich` & `questionary`
|
|
73
|
+
- **文件处理**: `OpenCV`, `Pillow`, `python-pptx`
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 🔒 安全建议
|
|
78
|
+
|
|
79
|
+
- **私钥保护**: 身份证书保存在本地 `.aegis_identity` 目录,请务必妥善保管。
|
|
80
|
+
- **三重防护**: 建议同时使用“视觉水印 + 字符串加密 + 数字签名”以获得最高级别的保护。
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
**Aegis - 为每一份智力成果披上隐形神盾。**
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Aegis (神盾) - 专业级隐形水印与数字签名工具 🛡️
|
|
2
|
+
### Professional Blind Watermarking & Digital Signature Tool
|
|
3
|
+
|
|
4
|
+
Aegis 是一款结合了 **频域盲水印 (Blind Watermarking)** 与 **RSA 数字签名** 技术的版权保护工具。它不仅能为图像及 PPTX 文档嵌入肉眼不可见的“视觉指纹”,还能加盖不可伪造的“数字印章”。
|
|
5
|
+
|
|
6
|
+
Aegis is a copyright protection tool combining **frequency domain blind watermarking** and **RSA digital signatures**. It embeds invisible "visual fingerprints" and attaches unforgable "digital stamps" to images and PPTX documents.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 🌟 核心亮点 | Key Features
|
|
11
|
+
|
|
12
|
+
- **视觉水印技术 (Visual Watermarking)**: 不同于脆弱的文本编码,Aegis 嵌入的是视觉轮廓,对截图、压缩、翻拍具有极强的抗性。
|
|
13
|
+
- **RSA-4096 数字签名 (Digital Signature)**: 集成自签名证书体系,一键证明身份并确保文件“未被篡改”。
|
|
14
|
+
- **SHA-256 安全加固 (Security Hardening)**: 支持任意长度字符串密钥,杜绝暴力破解撞库。
|
|
15
|
+
- **交互式控制台 (Interactive CLI)**: 中英双语菜单,无需记忆复杂指令,像使用独立 App 一样简单。
|
|
16
|
+
- **全自动文档保护 (Automated PPTX Protection)**: 自动识别并保护 PPT 内部的所有高价值图像素材。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 🚀 快速开始 | Quick Start
|
|
21
|
+
|
|
22
|
+
### 1. 安装
|
|
23
|
+
```bash
|
|
24
|
+
pip install aegis-watermark
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2. 身份初始化 (首次使用)
|
|
28
|
+
运行 `aegis` -> 选择 **身份管理 (Identity)** -> 输入你的姓名和邮箱,生成专属的加密证书。
|
|
29
|
+
|
|
30
|
+
### 3. 运行模式
|
|
31
|
+
- **嵌入 (Embed)**: 处理文件时,系统会询问是否附加数字签名。
|
|
32
|
+
- **提取 (Extract)**: 系统将自动校验数字签名(身份与完整性)并提取盲水印。
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🛠️ 技术栈 | Tech Stack
|
|
37
|
+
|
|
38
|
+
- **算法核心**: `blind-watermark` (DCT/DWT 变换)
|
|
39
|
+
- **安全保障**: `cryptography` (RSA-4096 / SHA-256 / X.509)
|
|
40
|
+
- **UI 引擎**: `Rich` & `questionary`
|
|
41
|
+
- **文件处理**: `OpenCV`, `Pillow`, `python-pptx`
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 🔒 安全建议
|
|
46
|
+
|
|
47
|
+
- **私钥保护**: 身份证书保存在本地 `.aegis_identity` 目录,请务必妥善保管。
|
|
48
|
+
- **三重防护**: 建议同时使用“视觉水印 + 字符串加密 + 数字签名”以获得最高级别的保护。
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
**Aegis - 为每一份智力成果披上隐形神盾。**
|
|
@@ -15,16 +15,20 @@ os.environ["OPENCV_LOG_LEVEL"] = "OFF"
|
|
|
15
15
|
|
|
16
16
|
from aegis.handlers.ppt import PPTHandler
|
|
17
17
|
from aegis.handlers.image import ImageHandler
|
|
18
|
+
from aegis.core.signature import SignatureManager
|
|
18
19
|
|
|
19
20
|
console = Console()
|
|
21
|
+
sig_mgr = SignatureManager()
|
|
20
22
|
|
|
21
23
|
# --- 多语言配置 ---
|
|
22
24
|
MESSAGES = {
|
|
23
25
|
"zh": {
|
|
24
26
|
"title": "Aegis",
|
|
27
|
+
"subtitle": "盲水印与数字签名工具 | v0.2.0",
|
|
25
28
|
"menu_prompt": "主菜单",
|
|
26
29
|
"menu_embed": "嵌入水印 (Embed)",
|
|
27
30
|
"menu_extract": "提取分析 (Extract)",
|
|
31
|
+
"menu_identity": "身份管理 (Identity)",
|
|
28
32
|
"menu_exit": "退出程序 (Exit)",
|
|
29
33
|
"path_input": "输入文件路径",
|
|
30
34
|
"path_output": "保存结果为",
|
|
@@ -44,13 +48,25 @@ MESSAGES = {
|
|
|
44
48
|
"note_title": "核验提示",
|
|
45
49
|
"note_body": "请查看结果图片。若文字轮廓清晰,则版权校验通过。",
|
|
46
50
|
"fail_extract": "分析失败: 未发现有效水印。",
|
|
47
|
-
"error_file": "路径错误,请重新输入。"
|
|
51
|
+
"error_file": "路径错误,请重新输入。",
|
|
52
|
+
"ident_name": "请输入您的真实姓名/机构名",
|
|
53
|
+
"ident_email": "请输入您的联系邮箱",
|
|
54
|
+
"ident_success": "✅ 身份证书创建成功!",
|
|
55
|
+
"ident_exists": "⚠️ 身份已存在。是否重新创建?(将覆盖旧证书)",
|
|
56
|
+
"sign_ask": "是否同时附加数字签名?(增强防篡改能力)",
|
|
57
|
+
"sig_status": "数字签名",
|
|
58
|
+
"sig_signer": "签署人",
|
|
59
|
+
"sig_verified": "✅ 已验证 (完整性通过)",
|
|
60
|
+
"sig_none": "未发现数字签名",
|
|
61
|
+
"sig_fail": "❌ 签名失效 (文件可能已被篡改)"
|
|
48
62
|
},
|
|
49
63
|
"en": {
|
|
50
64
|
"title": "Aegis",
|
|
65
|
+
"subtitle": "Watermarking & Digital Signature | v0.2.0",
|
|
51
66
|
"menu_prompt": "Main Menu",
|
|
52
67
|
"menu_embed": "Embed Watermark",
|
|
53
68
|
"menu_extract": "Extract & Analyze",
|
|
69
|
+
"menu_identity": "Manage Identity",
|
|
54
70
|
"menu_exit": "Exit",
|
|
55
71
|
"path_input": "File Path",
|
|
56
72
|
"path_output": "Save As",
|
|
@@ -70,7 +86,17 @@ MESSAGES = {
|
|
|
70
86
|
"note_title": "NOTICE",
|
|
71
87
|
"note_body": "Verification passed if text outlines are visible.",
|
|
72
88
|
"fail_extract": "Failed: No watermark detected.",
|
|
73
|
-
"error_file": "Invalid path."
|
|
89
|
+
"error_file": "Invalid path.",
|
|
90
|
+
"ident_name": "Enter your name or organization",
|
|
91
|
+
"ident_email": "Enter your email",
|
|
92
|
+
"ident_success": "✅ Identity certificate created!",
|
|
93
|
+
"ident_exists": "⚠️ Identity already exists. Overwrite?",
|
|
94
|
+
"sign_ask": "Add digital signature as well? (Anti-tamper)",
|
|
95
|
+
"sig_status": "Digital Signature",
|
|
96
|
+
"sig_signer": "Signer",
|
|
97
|
+
"sig_verified": "✅ Verified (Integrity Passed)",
|
|
98
|
+
"sig_none": "No signature found",
|
|
99
|
+
"sig_fail": "❌ Invalid (File might be tampered)"
|
|
74
100
|
}
|
|
75
101
|
}
|
|
76
102
|
|
|
@@ -107,6 +133,7 @@ def interactive_menu():
|
|
|
107
133
|
choices=[
|
|
108
134
|
msg["menu_embed"],
|
|
109
135
|
msg["menu_extract"],
|
|
136
|
+
msg["menu_identity"],
|
|
110
137
|
msg["menu_exit"]
|
|
111
138
|
],
|
|
112
139
|
qmark=">",
|
|
@@ -128,11 +155,15 @@ def interactive_menu():
|
|
|
128
155
|
|
|
129
156
|
output_file = questionary.text(msg["path_output"] + ":", default=input_file + "_protected.png", qmark=">").ask()
|
|
130
157
|
text = questionary.text(msg["watermark_text"] + ":", qmark=">").ask()
|
|
131
|
-
# 密钥改为普通文本,且无默认值显示
|
|
132
158
|
key = questionary.text(msg["key_prompt"] + ":", qmark=">").ask()
|
|
133
159
|
if not key: key = "1"
|
|
134
160
|
|
|
135
|
-
|
|
161
|
+
# 询问是否签名
|
|
162
|
+
should_sign = False
|
|
163
|
+
if sig_mgr.has_identity():
|
|
164
|
+
should_sign = questionary.confirm(msg["sign_ask"], default=True, qmark=">").ask()
|
|
165
|
+
|
|
166
|
+
run_embed(input_file, output_file, text, key, should_sign=should_sign)
|
|
136
167
|
|
|
137
168
|
elif "Extract" in action or "提取" in action:
|
|
138
169
|
input_file = questionary.path(msg["path_input"] + ":", qmark=">").ask()
|
|
@@ -146,7 +177,25 @@ def interactive_menu():
|
|
|
146
177
|
|
|
147
178
|
run_extract(input_file, output, key)
|
|
148
179
|
|
|
149
|
-
|
|
180
|
+
elif "Identity" in action or "身份" in action:
|
|
181
|
+
run_identity_setup()
|
|
182
|
+
|
|
183
|
+
def run_identity_setup():
|
|
184
|
+
"""设置或更新身份信息"""
|
|
185
|
+
msg = MESSAGES[CURRENT_LANG]
|
|
186
|
+
if sig_mgr.has_identity():
|
|
187
|
+
if not questionary.confirm(msg["ident_exists"], default=False, qmark=">").ask():
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
name = questionary.text(msg["ident_name"] + ":", qmark=">").ask()
|
|
191
|
+
email = questionary.text(msg["ident_email"] + ":", qmark=">").ask()
|
|
192
|
+
|
|
193
|
+
if name and email:
|
|
194
|
+
with console.status("[bold green]Generating RSA-4096 Keys...[/bold green]"):
|
|
195
|
+
sig_mgr.create_identity(name, email)
|
|
196
|
+
console.print(f"[bold green]{msg['ident_success']}[/bold green]")
|
|
197
|
+
|
|
198
|
+
def run_embed(input, output, text, key, should_sign=False):
|
|
150
199
|
"""执行嵌入核心逻辑"""
|
|
151
200
|
msg = MESSAGES[CURRENT_LANG]
|
|
152
201
|
ext = input.lower().split('.')[-1]
|
|
@@ -161,12 +210,16 @@ def run_embed(input, output, text, key):
|
|
|
161
210
|
success = handler.process(input, output, text, key=key)
|
|
162
211
|
else:
|
|
163
212
|
success = False
|
|
213
|
+
|
|
214
|
+
# 如果成功且需要签名
|
|
215
|
+
if success and should_sign:
|
|
216
|
+
handler.attach_signature(output, sig_mgr)
|
|
217
|
+
|
|
164
218
|
except Exception as e:
|
|
165
219
|
console.print(f"[bold red]Error:[/bold red] {e}")
|
|
166
220
|
success = False
|
|
167
221
|
|
|
168
222
|
if success:
|
|
169
|
-
# 使用 Text 对象防止路径字符触发 MarkupError
|
|
170
223
|
res_text = Text(f"{msg['success_embed']} ", style="bold green")
|
|
171
224
|
res_text.append(output, style="underline cyan")
|
|
172
225
|
console.print(res_text)
|
|
@@ -178,17 +231,22 @@ def run_extract(input, output, key):
|
|
|
178
231
|
msg = MESSAGES[CURRENT_LANG]
|
|
179
232
|
ext = input.lower().split('.')[-1]
|
|
180
233
|
result = None
|
|
234
|
+
sig_status = "none"
|
|
235
|
+
sig_info = None
|
|
181
236
|
|
|
182
237
|
with console.status(f"[bold blue]{msg['scanning']}[/bold blue]...", spinner="earth"):
|
|
183
238
|
try:
|
|
184
239
|
if ext == 'pptx':
|
|
185
240
|
handler = PPTHandler()
|
|
186
241
|
result = handler.extract(input, key=key)
|
|
242
|
+
sig_status, sig_info = handler.get_signature(input, sig_mgr)
|
|
187
243
|
elif ext in ['png', 'jpg', 'jpeg', 'bmp']:
|
|
188
244
|
handler = ImageHandler()
|
|
189
245
|
result = handler.extract(input, output_wm_path=output, key=key)
|
|
246
|
+
sig_status, sig_info = handler.get_signature(input, sig_mgr)
|
|
190
247
|
except Exception as e:
|
|
191
248
|
console.print(f"[bold red]Error:[/bold red] {e}")
|
|
249
|
+
sig_status = "error"
|
|
192
250
|
|
|
193
251
|
console.print()
|
|
194
252
|
|
|
@@ -199,6 +257,16 @@ def run_extract(input, output, key):
|
|
|
199
257
|
|
|
200
258
|
table.add_row(msg["target_file"], os.path.basename(input))
|
|
201
259
|
table.add_row(msg["key_fingerprint"], f"SHA256(***{key[-3:] if len(key) >= 3 else key})")
|
|
260
|
+
|
|
261
|
+
# --- 签名状态展示 ---
|
|
262
|
+
if sig_status == "valid" and sig_info:
|
|
263
|
+
table.add_row(msg["sig_status"], msg["sig_verified"])
|
|
264
|
+
table.add_row(msg["sig_signer"], f"{sig_info['name']} <{sig_info['email']}>")
|
|
265
|
+
elif sig_status == "invalid":
|
|
266
|
+
table.add_row(msg["sig_status"], f"[bold red]{msg['sig_fail']}[/bold red]")
|
|
267
|
+
else:
|
|
268
|
+
table.add_row(msg["sig_status"], f"[gray]{msg['sig_none']}[/gray]")
|
|
269
|
+
|
|
202
270
|
table.add_row(msg["status"], "SUCCESS")
|
|
203
271
|
table.add_row(msg["evidence"], result)
|
|
204
272
|
|
|
@@ -214,7 +282,6 @@ def main(ctx):
|
|
|
214
282
|
if ctx.invoked_subcommand is None:
|
|
215
283
|
interactive_menu()
|
|
216
284
|
else:
|
|
217
|
-
# 命令行模式默认不打印 Banner 以保持静默
|
|
218
285
|
pass
|
|
219
286
|
|
|
220
287
|
@main.command()
|
|
@@ -224,7 +291,6 @@ def main(ctx):
|
|
|
224
291
|
@click.option('--key', '-k', default="1", type=str)
|
|
225
292
|
def embed(input, output, text, key):
|
|
226
293
|
"""Embed mode"""
|
|
227
|
-
# 命令行模式也需要确保 Banner 已打印(如果没选交互模式的话)
|
|
228
294
|
print_banner()
|
|
229
295
|
run_embed(input, output, text, key)
|
|
230
296
|
|
|
@@ -238,4 +304,4 @@ def extract(input, output, key):
|
|
|
238
304
|
run_extract(input, output, key)
|
|
239
305
|
|
|
240
306
|
if __name__ == '__main__':
|
|
241
|
-
main()
|
|
307
|
+
main()
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import datetime
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
import base64
|
|
6
|
+
from cryptography import x509
|
|
7
|
+
from cryptography.x509.oid import NameOID
|
|
8
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
|
9
|
+
from cryptography.hazmat.primitives.asymmetric import rsa, padding
|
|
10
|
+
from cryptography.hazmat.backends import default_backend
|
|
11
|
+
|
|
12
|
+
class SignatureManager:
|
|
13
|
+
"""
|
|
14
|
+
数字签名管理器:负责 RSA 密钥对、自签名证书的生成、签署与验证。
|
|
15
|
+
"""
|
|
16
|
+
SIG_BOUNDARY = b"\x00--AEGIS-SIGNATURE-DATA--"
|
|
17
|
+
|
|
18
|
+
def __init__(self, keys_dir=".aegis_identity"):
|
|
19
|
+
# 默认存储身份信息的目录(建议放在用户家目录,这里暂设在项目内)
|
|
20
|
+
self.keys_dir = os.path.abspath(keys_dir)
|
|
21
|
+
self.priv_path = os.path.join(self.keys_dir, "private.key")
|
|
22
|
+
self.cert_path = os.path.join(self.keys_dir, "identity.crt")
|
|
23
|
+
|
|
24
|
+
if not os.path.exists(self.keys_dir):
|
|
25
|
+
os.makedirs(self.keys_dir)
|
|
26
|
+
|
|
27
|
+
def has_identity(self):
|
|
28
|
+
"""检查本地是否已创建身份"""
|
|
29
|
+
return os.path.exists(self.priv_path) and os.path.exists(self.cert_path)
|
|
30
|
+
|
|
31
|
+
def create_identity(self, name, email):
|
|
32
|
+
"""
|
|
33
|
+
创建 RSA 4096 位密钥及自签名 X.509 证书。
|
|
34
|
+
"""
|
|
35
|
+
# 1. 生成私钥
|
|
36
|
+
private_key = rsa.generate_private_key(
|
|
37
|
+
public_exponent=65537,
|
|
38
|
+
key_size=4096,
|
|
39
|
+
backend=default_backend()
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# 2. 生成证书
|
|
43
|
+
subject = issuer = x509.Name([
|
|
44
|
+
x509.NameAttribute(NameOID.COMMON_NAME, name),
|
|
45
|
+
x509.NameAttribute(NameOID.EMAIL_ADDRESS, email),
|
|
46
|
+
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Aegis Protection"),
|
|
47
|
+
])
|
|
48
|
+
|
|
49
|
+
cert = x509.CertificateBuilder().subject_name(
|
|
50
|
+
subject
|
|
51
|
+
).issuer_name(
|
|
52
|
+
issuer
|
|
53
|
+
).public_key(
|
|
54
|
+
private_key.public_key()
|
|
55
|
+
).serial_number(
|
|
56
|
+
x509.random_serial_number()
|
|
57
|
+
).not_valid_before(
|
|
58
|
+
datetime.datetime.utcnow()
|
|
59
|
+
).not_valid_after(
|
|
60
|
+
# 有效期 20 年
|
|
61
|
+
datetime.datetime.utcnow() + datetime.timedelta(days=365*20)
|
|
62
|
+
).sign(private_key, hashes.SHA256(), default_backend())
|
|
63
|
+
|
|
64
|
+
# 3. 保存到本地
|
|
65
|
+
with open(self.priv_path, "wb") as f:
|
|
66
|
+
f.write(private_key.private_bytes(
|
|
67
|
+
encoding=serialization.Encoding.PEM,
|
|
68
|
+
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
|
69
|
+
encryption_algorithm=serialization.NoEncryption()
|
|
70
|
+
))
|
|
71
|
+
|
|
72
|
+
with open(self.cert_path, "wb") as f:
|
|
73
|
+
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
|
74
|
+
|
|
75
|
+
return self.cert_path
|
|
76
|
+
|
|
77
|
+
def sign_file(self, file_path):
|
|
78
|
+
"""
|
|
79
|
+
对文件进行数字签署。
|
|
80
|
+
返回:(签名Base64, 证书PEM)
|
|
81
|
+
注意:签署的是文件此时此刻的完整二进制流。
|
|
82
|
+
"""
|
|
83
|
+
if not self.has_identity():
|
|
84
|
+
raise Exception("No identity found. Run 'identity' first.")
|
|
85
|
+
|
|
86
|
+
# 读取私钥
|
|
87
|
+
with open(self.priv_path, "rb") as f:
|
|
88
|
+
private_key = serialization.load_pem_private_key(
|
|
89
|
+
f.read(), password=None, backend=default_backend()
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# 读取证书
|
|
93
|
+
with open(self.cert_path, "rb") as f:
|
|
94
|
+
cert_pem = f.read().decode('utf-8')
|
|
95
|
+
|
|
96
|
+
# 计算文件哈希 (SHA-256)
|
|
97
|
+
file_hash = self._calculate_hash(file_path)
|
|
98
|
+
|
|
99
|
+
# 进行签名
|
|
100
|
+
signature = private_key.sign(
|
|
101
|
+
file_hash,
|
|
102
|
+
padding.PSS(
|
|
103
|
+
mgf=padding.MGF1(hashes.SHA256()),
|
|
104
|
+
salt_length=padding.PSS.MAX_LENGTH
|
|
105
|
+
),
|
|
106
|
+
hashes.SHA256()
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
sig_b64 = base64.b64encode(signature).decode('utf-8')
|
|
110
|
+
return sig_b64, cert_pem
|
|
111
|
+
|
|
112
|
+
def verify_signature(self, file_bytes_without_sig, sig_b64, cert_pem):
|
|
113
|
+
"""
|
|
114
|
+
验证签名。
|
|
115
|
+
参数:
|
|
116
|
+
file_bytes_without_sig: 剔除签名元数据后的原始文件二进制
|
|
117
|
+
sig_b64: 提取到的签名
|
|
118
|
+
cert_pem: 提取到的证书
|
|
119
|
+
返回:(是否通过, 签署人信息字典)
|
|
120
|
+
"""
|
|
121
|
+
try:
|
|
122
|
+
# 1. 加载证书并提取公钥
|
|
123
|
+
cert = x509.load_pem_x509_certificate(cert_pem.encode(), default_backend())
|
|
124
|
+
public_key = cert.public_key()
|
|
125
|
+
|
|
126
|
+
# 提取签署者信息
|
|
127
|
+
subject = cert.subject
|
|
128
|
+
info = {
|
|
129
|
+
"name": subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value,
|
|
130
|
+
"email": subject.get_attributes_for_oid(NameOID.EMAIL_ADDRESS)[0].value,
|
|
131
|
+
"expiry": cert.not_valid_after.strftime("%Y-%m-%d")
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# 2. 计算当前文件哈希
|
|
135
|
+
file_hash = hashlib.sha256(file_bytes_without_sig).digest()
|
|
136
|
+
|
|
137
|
+
# 3. 验证签名
|
|
138
|
+
signature = base64.b64decode(sig_b64)
|
|
139
|
+
public_key.verify(
|
|
140
|
+
signature,
|
|
141
|
+
file_hash,
|
|
142
|
+
padding.PSS(
|
|
143
|
+
mgf=padding.MGF1(hashes.SHA256()),
|
|
144
|
+
salt_length=padding.PSS.MAX_LENGTH
|
|
145
|
+
),
|
|
146
|
+
hashes.SHA256()
|
|
147
|
+
)
|
|
148
|
+
return True, info
|
|
149
|
+
except Exception as e:
|
|
150
|
+
print(f"[Debug] Verify Failed: {e}")
|
|
151
|
+
return False, None
|
|
152
|
+
|
|
153
|
+
def _calculate_hash(self, file_path):
|
|
154
|
+
sha256_hash = hashlib.sha256()
|
|
155
|
+
with open(file_path, "rb") as f:
|
|
156
|
+
for byte_block in iter(lambda: f.read(4096), b""):
|
|
157
|
+
sha256_hash.update(byte_block)
|
|
158
|
+
return sha256_hash.digest()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from aegis.core.frequency import FrequencyWatermarker
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import piexif
|
|
6
|
+
import json
|
|
7
|
+
import hashlib
|
|
8
|
+
from aegis.core.frequency import FrequencyWatermarker
|
|
9
|
+
|
|
10
|
+
class ImageHandler:
|
|
11
|
+
def process(self, input_path, output_path, watermark_text, key="1"):
|
|
12
|
+
"""处理单张图片"""
|
|
13
|
+
print(f"[*] Processing Image: {input_path}")
|
|
14
|
+
engine = FrequencyWatermarker(key=key)
|
|
15
|
+
return engine.embed(input_path, output_path, watermark_text)
|
|
16
|
+
|
|
17
|
+
def extract(self, input_path, output_wm_path=None, key="1"):
|
|
18
|
+
"""从单张图片提取"""
|
|
19
|
+
print(f"[*] Extracting from Image: {input_path}")
|
|
20
|
+
engine = FrequencyWatermarker(key=key)
|
|
21
|
+
return engine.extract(input_path, output_wm_path=output_wm_path)
|
|
22
|
+
|
|
23
|
+
def attach_signature(self, file_path, sig_mgr):
|
|
24
|
+
"""将数字签名追加到文件物理末尾"""
|
|
25
|
+
try:
|
|
26
|
+
# 1. 读取当前文件内容(签署的是当前状态)
|
|
27
|
+
with open(file_path, "rb") as f:
|
|
28
|
+
original_content = f.read()
|
|
29
|
+
|
|
30
|
+
# 2. 生成签名包
|
|
31
|
+
sig_b64, cert_pem = sig_mgr.sign_file(file_path)
|
|
32
|
+
sig_bundle = {
|
|
33
|
+
"sig": sig_b64,
|
|
34
|
+
"cert": cert_pem
|
|
35
|
+
}
|
|
36
|
+
sig_data = json.dumps(sig_bundle).encode('utf-8')
|
|
37
|
+
|
|
38
|
+
# 3. 追加到文件末尾: [原始数据] + [边界符] + [签名JSON]
|
|
39
|
+
with open(file_path, "ab") as f:
|
|
40
|
+
f.write(sig_mgr.SIG_BOUNDARY)
|
|
41
|
+
f.write(sig_data)
|
|
42
|
+
return True
|
|
43
|
+
except Exception as e:
|
|
44
|
+
print(f"[Debug] Failed to attach signature: {e}")
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
def get_signature(self, file_path, sig_mgr):
|
|
48
|
+
"""从文件末尾提取并验证签名"""
|
|
49
|
+
try:
|
|
50
|
+
with open(file_path, "rb") as f:
|
|
51
|
+
content = f.read()
|
|
52
|
+
|
|
53
|
+
# 1. 寻找边界符
|
|
54
|
+
if sig_mgr.SIG_BOUNDARY not in content:
|
|
55
|
+
return "none", None
|
|
56
|
+
|
|
57
|
+
# 2. 切分数据
|
|
58
|
+
parts = content.split(sig_mgr.SIG_BOUNDARY)
|
|
59
|
+
original_bytes = parts[0]
|
|
60
|
+
sig_json_bytes = parts[1]
|
|
61
|
+
|
|
62
|
+
# 3. 解析并验证
|
|
63
|
+
sig_bundle = json.loads(sig_json_bytes.decode('utf-8'))
|
|
64
|
+
valid, info = sig_mgr.verify_signature(original_bytes, sig_bundle["sig"], sig_bundle["cert"])
|
|
65
|
+
return ("valid" if valid else "invalid"), info
|
|
66
|
+
|
|
67
|
+
except Exception as e:
|
|
68
|
+
print(f"[Debug] Verify error: {e}")
|
|
69
|
+
return "none", None
|
|
@@ -91,11 +91,37 @@ class PPTHandler:
|
|
|
91
91
|
ext = filename.lower().split('.')[-1]
|
|
92
92
|
return ext in ['png', 'jpg', 'jpeg', 'bmp', 'tiff']
|
|
93
93
|
|
|
94
|
-
def
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
def attach_signature(self, file_path, sig_mgr):
|
|
95
|
+
"""将数字签名追加到文件物理末尾"""
|
|
96
|
+
try:
|
|
97
|
+
with open(file_path, "rb") as f:
|
|
98
|
+
original_content = f.read()
|
|
99
|
+
|
|
100
|
+
sig_b64, cert_pem = sig_mgr.sign_file(file_path)
|
|
101
|
+
sig_bundle = {"sig": sig_b64, "cert": cert_pem}
|
|
102
|
+
sig_data = json.dumps(sig_bundle).encode('utf-8')
|
|
103
|
+
|
|
104
|
+
with open(file_path, "ab") as f:
|
|
105
|
+
f.write(sig_mgr.SIG_BOUNDARY)
|
|
106
|
+
f.write(sig_data)
|
|
107
|
+
return True
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(f"[Debug] Failed to attach signature: {e}")
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
def get_signature(self, file_path, sig_mgr):
|
|
113
|
+
"""从文件末尾提取并验证签名"""
|
|
114
|
+
try:
|
|
115
|
+
with open(file_path, "rb") as f:
|
|
116
|
+
content = f.read()
|
|
117
|
+
|
|
118
|
+
if sig_mgr.SIG_BOUNDARY not in content:
|
|
119
|
+
return "none", None
|
|
120
|
+
|
|
121
|
+
parts = content.split(sig_mgr.SIG_BOUNDARY)
|
|
122
|
+
# 同样验证第一个部分
|
|
123
|
+
sig_bundle = json.loads(parts[1].decode('utf-8'))
|
|
124
|
+
valid, info = sig_mgr.verify_signature(parts[0], sig_bundle["sig"], sig_bundle["cert"])
|
|
125
|
+
return ("valid" if valid else "invalid"), info
|
|
126
|
+
except:
|
|
127
|
+
return "none", None
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aegis-watermark
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: 图片与PPT专业级隐形盲水印工具 | Professional blind watermarking tool for images and PPTX documents.
|
|
5
|
+
Home-page: https://github.com/your-repo/Aegis-Watermark
|
|
6
|
+
Author: LingQingyang
|
|
7
|
+
Author-email: 1739677116@qq.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: blind-watermark
|
|
14
|
+
Requires-Dist: opencv-python
|
|
15
|
+
Requires-Dist: numpy<2.0.0
|
|
16
|
+
Requires-Dist: click
|
|
17
|
+
Requires-Dist: Pillow
|
|
18
|
+
Requires-Dist: pyfiglet
|
|
19
|
+
Requires-Dist: rich
|
|
20
|
+
Requires-Dist: python-pptx
|
|
21
|
+
Requires-Dist: questionary
|
|
22
|
+
Requires-Dist: cryptography
|
|
23
|
+
Dynamic: author
|
|
24
|
+
Dynamic: author-email
|
|
25
|
+
Dynamic: classifier
|
|
26
|
+
Dynamic: description
|
|
27
|
+
Dynamic: description-content-type
|
|
28
|
+
Dynamic: home-page
|
|
29
|
+
Dynamic: requires-dist
|
|
30
|
+
Dynamic: requires-python
|
|
31
|
+
Dynamic: summary
|
|
32
|
+
|
|
33
|
+
# Aegis (神盾) - 专业级隐形水印与数字签名工具 🛡️
|
|
34
|
+
### Professional Blind Watermarking & Digital Signature Tool
|
|
35
|
+
|
|
36
|
+
Aegis 是一款结合了 **频域盲水印 (Blind Watermarking)** 与 **RSA 数字签名** 技术的版权保护工具。它不仅能为图像及 PPTX 文档嵌入肉眼不可见的“视觉指纹”,还能加盖不可伪造的“数字印章”。
|
|
37
|
+
|
|
38
|
+
Aegis is a copyright protection tool combining **frequency domain blind watermarking** and **RSA digital signatures**. It embeds invisible "visual fingerprints" and attaches unforgable "digital stamps" to images and PPTX documents.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🌟 核心亮点 | Key Features
|
|
43
|
+
|
|
44
|
+
- **视觉水印技术 (Visual Watermarking)**: 不同于脆弱的文本编码,Aegis 嵌入的是视觉轮廓,对截图、压缩、翻拍具有极强的抗性。
|
|
45
|
+
- **RSA-4096 数字签名 (Digital Signature)**: 集成自签名证书体系,一键证明身份并确保文件“未被篡改”。
|
|
46
|
+
- **SHA-256 安全加固 (Security Hardening)**: 支持任意长度字符串密钥,杜绝暴力破解撞库。
|
|
47
|
+
- **交互式控制台 (Interactive CLI)**: 中英双语菜单,无需记忆复杂指令,像使用独立 App 一样简单。
|
|
48
|
+
- **全自动文档保护 (Automated PPTX Protection)**: 自动识别并保护 PPT 内部的所有高价值图像素材。
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚀 快速开始 | Quick Start
|
|
53
|
+
|
|
54
|
+
### 1. 安装
|
|
55
|
+
```bash
|
|
56
|
+
pip install aegis-watermark
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. 身份初始化 (首次使用)
|
|
60
|
+
运行 `aegis` -> 选择 **身份管理 (Identity)** -> 输入你的姓名和邮箱,生成专属的加密证书。
|
|
61
|
+
|
|
62
|
+
### 3. 运行模式
|
|
63
|
+
- **嵌入 (Embed)**: 处理文件时,系统会询问是否附加数字签名。
|
|
64
|
+
- **提取 (Extract)**: 系统将自动校验数字签名(身份与完整性)并提取盲水印。
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🛠️ 技术栈 | Tech Stack
|
|
69
|
+
|
|
70
|
+
- **算法核心**: `blind-watermark` (DCT/DWT 变换)
|
|
71
|
+
- **安全保障**: `cryptography` (RSA-4096 / SHA-256 / X.509)
|
|
72
|
+
- **UI 引擎**: `Rich` & `questionary`
|
|
73
|
+
- **文件处理**: `OpenCV`, `Pillow`, `python-pptx`
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 🔒 安全建议
|
|
78
|
+
|
|
79
|
+
- **私钥保护**: 身份证书保存在本地 `.aegis_identity` 目录,请务必妥善保管。
|
|
80
|
+
- **三重防护**: 建议同时使用“视觉水印 + 字符串加密 + 数字签名”以获得最高级别的保护。
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
**Aegis - 为每一份智力成果披上隐形神盾。**
|
|
@@ -5,10 +5,10 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='aegis-watermark',
|
|
8
|
-
version='0.
|
|
8
|
+
version='0.2.0',
|
|
9
9
|
author='LingQingyang',
|
|
10
10
|
author_email='1739677116@qq.com',
|
|
11
|
-
description='
|
|
11
|
+
description='图片与PPT专业级隐形盲水印工具 | Professional blind watermarking tool for images and PPTX documents.',
|
|
12
12
|
long_description=long_description,
|
|
13
13
|
long_description_content_type="text/markdown",
|
|
14
14
|
url='https://github.com/your-repo/Aegis-Watermark',
|
|
@@ -22,7 +22,8 @@ setup(
|
|
|
22
22
|
'pyfiglet',
|
|
23
23
|
'rich',
|
|
24
24
|
'python-pptx',
|
|
25
|
-
'questionary'
|
|
25
|
+
'questionary',
|
|
26
|
+
'cryptography'
|
|
26
27
|
],
|
|
27
28
|
classifiers=[
|
|
28
29
|
"Programming Language :: Python :: 3",
|
aegis_watermark-0.1.1/PKG-INFO
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: aegis-watermark
|
|
3
|
-
Version: 0.1.1
|
|
4
|
-
Summary: A professional hidden watermark tool for images and PPTX documents.
|
|
5
|
-
Home-page: https://github.com/your-repo/Aegis-Watermark
|
|
6
|
-
Author: LingQingyang
|
|
7
|
-
Author-email: 1739677116@qq.com
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.8
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
Requires-Dist: blind-watermark
|
|
14
|
-
Requires-Dist: opencv-python
|
|
15
|
-
Requires-Dist: numpy<2.0.0
|
|
16
|
-
Requires-Dist: click
|
|
17
|
-
Requires-Dist: Pillow
|
|
18
|
-
Requires-Dist: pyfiglet
|
|
19
|
-
Requires-Dist: rich
|
|
20
|
-
Requires-Dist: python-pptx
|
|
21
|
-
Requires-Dist: questionary
|
|
22
|
-
Dynamic: author
|
|
23
|
-
Dynamic: author-email
|
|
24
|
-
Dynamic: classifier
|
|
25
|
-
Dynamic: description
|
|
26
|
-
Dynamic: description-content-type
|
|
27
|
-
Dynamic: home-page
|
|
28
|
-
Dynamic: requires-dist
|
|
29
|
-
Dynamic: requires-python
|
|
30
|
-
Dynamic: summary
|
|
31
|
-
|
|
32
|
-
# Aegis (神盾) - 专业级隐形水印保护工具
|
|
33
|
-
|
|
34
|
-
Aegis 是一个基于频域盲水印技术的版权保护工具。它能够为图像及 PPTX 文档嵌入肉眼不可见的“视觉指纹”,即使文件经过截图、压缩或格式转换,依然可以提取出清晰的版权证据。
|
|
35
|
-
|
|
36
|
-
## 🌟 核心亮点
|
|
37
|
-
|
|
38
|
-
- **视觉水印技术**: 不同于脆弱的文本编码,Aegis 嵌入的是视觉轮廓,对图像损伤具有极强的抗性。
|
|
39
|
-
- **SHA-256 安全加固**: 支持任意长度字符串密钥,通过哈希拉伸技术,彻底杜绝暴力破解和撞库。
|
|
40
|
-
- **交互式控制台**: 输入 `aegis` 即可进入专业感十足的中英双语交互式主菜单,无需记忆复杂指令。
|
|
41
|
-
- **全自动文档保护**: 针对 `.pptx` 格式提供深度加固,自动识别并保护文档内部的所有高价值图像素材。
|
|
42
|
-
- **极简专业 UI**: 借鉴现代 CLI 设计,提供 ASCII Banner、动态加载动画及结构化分析报告。
|
|
43
|
-
|
|
44
|
-
## 🛠️ 技术栈
|
|
45
|
-
|
|
46
|
-
- **核心驱动**: `blind-watermark` (频率域 DCT/DWT 变换)
|
|
47
|
-
- **界面引擎**: `Rich` (终端美化) & `questionary` (交互菜单)
|
|
48
|
-
- **图像处理**: `OpenCV`, `Pillow`, `NumPy`
|
|
49
|
-
- **文档处理**: `python-pptx`
|
|
50
|
-
|
|
51
|
-
## 🚀 快速开始
|
|
52
|
-
|
|
53
|
-
### 1. 环境准备
|
|
54
|
-
确保你的系统安装了 Python 3.8+。
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
# 克隆项目并进入目录
|
|
58
|
-
git clone https://github.com/your-repo/Aegis-Watermark.git
|
|
59
|
-
cd Aegis-Watermark
|
|
60
|
-
|
|
61
|
-
# 安装依赖
|
|
62
|
-
pip install -r requirements.txt
|
|
63
|
-
|
|
64
|
-
# 以开发模式安装
|
|
65
|
-
pip install -e .
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### 2. 运行工具
|
|
69
|
-
在终端输入命令即可启动:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
aegis
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### 3. 使用模式
|
|
76
|
-
|
|
77
|
-
- **交互模式**: 直接输入 `aegis`,跟随菜单引导完成操作。
|
|
78
|
-
- **命令模式**: 支持静默调用,适合脚本集成:
|
|
79
|
-
- 嵌入:`aegis embed -i input.png -o output.png -t "ID:716" -k "MyPassword"`
|
|
80
|
-
- 提取:`aegis extract -i output.png -k "MyPassword"`
|
|
81
|
-
|
|
82
|
-
## 📂 目录结构
|
|
83
|
-
|
|
84
|
-
```text
|
|
85
|
-
aegis/
|
|
86
|
-
├── cli.py # 交互式双语 CLI 入口
|
|
87
|
-
├── core/ # 核心算法 (视觉水印 & 哈希加固)
|
|
88
|
-
└── handlers/ # 格式适配 (Image & PPTX)
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## 🔒 安全建议
|
|
92
|
-
|
|
93
|
-
- **密钥设置**: 建议使用包含字母和数字的长字符串作为密钥。
|
|
94
|
-
- **默认机制**: 若不输入密钥,系统将默认使用密钥 "1"。
|
|
95
|
-
- **版权验证**: 提取出的结果图片若能清晰辨认文字轮廓,即具备版权铁证效力。
|
|
96
|
-
|
|
97
|
-
## 📝 路线图
|
|
98
|
-
|
|
99
|
-
- [ ] 支持 PDF 矢量图层水印
|
|
100
|
-
- [ ] 增加多线程批量处理模式
|
|
101
|
-
- [ ] 集成 AI 深度学习水印算法
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
**Aegis - 为每一份智力成果披上隐形神盾。**
|
aegis_watermark-0.1.1/README.md
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# Aegis (神盾) - 专业级隐形水印保护工具
|
|
2
|
-
|
|
3
|
-
Aegis 是一个基于频域盲水印技术的版权保护工具。它能够为图像及 PPTX 文档嵌入肉眼不可见的“视觉指纹”,即使文件经过截图、压缩或格式转换,依然可以提取出清晰的版权证据。
|
|
4
|
-
|
|
5
|
-
## 🌟 核心亮点
|
|
6
|
-
|
|
7
|
-
- **视觉水印技术**: 不同于脆弱的文本编码,Aegis 嵌入的是视觉轮廓,对图像损伤具有极强的抗性。
|
|
8
|
-
- **SHA-256 安全加固**: 支持任意长度字符串密钥,通过哈希拉伸技术,彻底杜绝暴力破解和撞库。
|
|
9
|
-
- **交互式控制台**: 输入 `aegis` 即可进入专业感十足的中英双语交互式主菜单,无需记忆复杂指令。
|
|
10
|
-
- **全自动文档保护**: 针对 `.pptx` 格式提供深度加固,自动识别并保护文档内部的所有高价值图像素材。
|
|
11
|
-
- **极简专业 UI**: 借鉴现代 CLI 设计,提供 ASCII Banner、动态加载动画及结构化分析报告。
|
|
12
|
-
|
|
13
|
-
## 🛠️ 技术栈
|
|
14
|
-
|
|
15
|
-
- **核心驱动**: `blind-watermark` (频率域 DCT/DWT 变换)
|
|
16
|
-
- **界面引擎**: `Rich` (终端美化) & `questionary` (交互菜单)
|
|
17
|
-
- **图像处理**: `OpenCV`, `Pillow`, `NumPy`
|
|
18
|
-
- **文档处理**: `python-pptx`
|
|
19
|
-
|
|
20
|
-
## 🚀 快速开始
|
|
21
|
-
|
|
22
|
-
### 1. 环境准备
|
|
23
|
-
确保你的系统安装了 Python 3.8+。
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
# 克隆项目并进入目录
|
|
27
|
-
git clone https://github.com/your-repo/Aegis-Watermark.git
|
|
28
|
-
cd Aegis-Watermark
|
|
29
|
-
|
|
30
|
-
# 安装依赖
|
|
31
|
-
pip install -r requirements.txt
|
|
32
|
-
|
|
33
|
-
# 以开发模式安装
|
|
34
|
-
pip install -e .
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### 2. 运行工具
|
|
38
|
-
在终端输入命令即可启动:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
aegis
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### 3. 使用模式
|
|
45
|
-
|
|
46
|
-
- **交互模式**: 直接输入 `aegis`,跟随菜单引导完成操作。
|
|
47
|
-
- **命令模式**: 支持静默调用,适合脚本集成:
|
|
48
|
-
- 嵌入:`aegis embed -i input.png -o output.png -t "ID:716" -k "MyPassword"`
|
|
49
|
-
- 提取:`aegis extract -i output.png -k "MyPassword"`
|
|
50
|
-
|
|
51
|
-
## 📂 目录结构
|
|
52
|
-
|
|
53
|
-
```text
|
|
54
|
-
aegis/
|
|
55
|
-
├── cli.py # 交互式双语 CLI 入口
|
|
56
|
-
├── core/ # 核心算法 (视觉水印 & 哈希加固)
|
|
57
|
-
└── handlers/ # 格式适配 (Image & PPTX)
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## 🔒 安全建议
|
|
61
|
-
|
|
62
|
-
- **密钥设置**: 建议使用包含字母和数字的长字符串作为密钥。
|
|
63
|
-
- **默认机制**: 若不输入密钥,系统将默认使用密钥 "1"。
|
|
64
|
-
- **版权验证**: 提取出的结果图片若能清晰辨认文字轮廓,即具备版权铁证效力。
|
|
65
|
-
|
|
66
|
-
## 📝 路线图
|
|
67
|
-
|
|
68
|
-
- [ ] 支持 PDF 矢量图层水印
|
|
69
|
-
- [ ] 增加多线程批量处理模式
|
|
70
|
-
- [ ] 集成 AI 深度学习水印算法
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
**Aegis - 为每一份智力成果披上隐形神盾。**
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from aegis.core.frequency import FrequencyWatermarker
|
|
3
|
-
|
|
4
|
-
class ImageHandler:
|
|
5
|
-
def process(self, input_path, output_path, watermark_text, key="1"):
|
|
6
|
-
"""处理单张图片"""
|
|
7
|
-
print(f"[*] Processing Image: {input_path}")
|
|
8
|
-
engine = FrequencyWatermarker(key=key)
|
|
9
|
-
return engine.embed(input_path, output_path, watermark_text)
|
|
10
|
-
|
|
11
|
-
def extract(self, input_path, output_wm_path=None, key="1"):
|
|
12
|
-
"""从单张图片提取"""
|
|
13
|
-
print(f"[*] Extracting from Image: {input_path}")
|
|
14
|
-
engine = FrequencyWatermarker(key=key)
|
|
15
|
-
return engine.extract(input_path, output_wm_path=output_wm_path)
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: aegis-watermark
|
|
3
|
-
Version: 0.1.1
|
|
4
|
-
Summary: A professional hidden watermark tool for images and PPTX documents.
|
|
5
|
-
Home-page: https://github.com/your-repo/Aegis-Watermark
|
|
6
|
-
Author: LingQingyang
|
|
7
|
-
Author-email: 1739677116@qq.com
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.8
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
Requires-Dist: blind-watermark
|
|
14
|
-
Requires-Dist: opencv-python
|
|
15
|
-
Requires-Dist: numpy<2.0.0
|
|
16
|
-
Requires-Dist: click
|
|
17
|
-
Requires-Dist: Pillow
|
|
18
|
-
Requires-Dist: pyfiglet
|
|
19
|
-
Requires-Dist: rich
|
|
20
|
-
Requires-Dist: python-pptx
|
|
21
|
-
Requires-Dist: questionary
|
|
22
|
-
Dynamic: author
|
|
23
|
-
Dynamic: author-email
|
|
24
|
-
Dynamic: classifier
|
|
25
|
-
Dynamic: description
|
|
26
|
-
Dynamic: description-content-type
|
|
27
|
-
Dynamic: home-page
|
|
28
|
-
Dynamic: requires-dist
|
|
29
|
-
Dynamic: requires-python
|
|
30
|
-
Dynamic: summary
|
|
31
|
-
|
|
32
|
-
# Aegis (神盾) - 专业级隐形水印保护工具
|
|
33
|
-
|
|
34
|
-
Aegis 是一个基于频域盲水印技术的版权保护工具。它能够为图像及 PPTX 文档嵌入肉眼不可见的“视觉指纹”,即使文件经过截图、压缩或格式转换,依然可以提取出清晰的版权证据。
|
|
35
|
-
|
|
36
|
-
## 🌟 核心亮点
|
|
37
|
-
|
|
38
|
-
- **视觉水印技术**: 不同于脆弱的文本编码,Aegis 嵌入的是视觉轮廓,对图像损伤具有极强的抗性。
|
|
39
|
-
- **SHA-256 安全加固**: 支持任意长度字符串密钥,通过哈希拉伸技术,彻底杜绝暴力破解和撞库。
|
|
40
|
-
- **交互式控制台**: 输入 `aegis` 即可进入专业感十足的中英双语交互式主菜单,无需记忆复杂指令。
|
|
41
|
-
- **全自动文档保护**: 针对 `.pptx` 格式提供深度加固,自动识别并保护文档内部的所有高价值图像素材。
|
|
42
|
-
- **极简专业 UI**: 借鉴现代 CLI 设计,提供 ASCII Banner、动态加载动画及结构化分析报告。
|
|
43
|
-
|
|
44
|
-
## 🛠️ 技术栈
|
|
45
|
-
|
|
46
|
-
- **核心驱动**: `blind-watermark` (频率域 DCT/DWT 变换)
|
|
47
|
-
- **界面引擎**: `Rich` (终端美化) & `questionary` (交互菜单)
|
|
48
|
-
- **图像处理**: `OpenCV`, `Pillow`, `NumPy`
|
|
49
|
-
- **文档处理**: `python-pptx`
|
|
50
|
-
|
|
51
|
-
## 🚀 快速开始
|
|
52
|
-
|
|
53
|
-
### 1. 环境准备
|
|
54
|
-
确保你的系统安装了 Python 3.8+。
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
# 克隆项目并进入目录
|
|
58
|
-
git clone https://github.com/your-repo/Aegis-Watermark.git
|
|
59
|
-
cd Aegis-Watermark
|
|
60
|
-
|
|
61
|
-
# 安装依赖
|
|
62
|
-
pip install -r requirements.txt
|
|
63
|
-
|
|
64
|
-
# 以开发模式安装
|
|
65
|
-
pip install -e .
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### 2. 运行工具
|
|
69
|
-
在终端输入命令即可启动:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
aegis
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### 3. 使用模式
|
|
76
|
-
|
|
77
|
-
- **交互模式**: 直接输入 `aegis`,跟随菜单引导完成操作。
|
|
78
|
-
- **命令模式**: 支持静默调用,适合脚本集成:
|
|
79
|
-
- 嵌入:`aegis embed -i input.png -o output.png -t "ID:716" -k "MyPassword"`
|
|
80
|
-
- 提取:`aegis extract -i output.png -k "MyPassword"`
|
|
81
|
-
|
|
82
|
-
## 📂 目录结构
|
|
83
|
-
|
|
84
|
-
```text
|
|
85
|
-
aegis/
|
|
86
|
-
├── cli.py # 交互式双语 CLI 入口
|
|
87
|
-
├── core/ # 核心算法 (视觉水印 & 哈希加固)
|
|
88
|
-
└── handlers/ # 格式适配 (Image & PPTX)
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## 🔒 安全建议
|
|
92
|
-
|
|
93
|
-
- **密钥设置**: 建议使用包含字母和数字的长字符串作为密钥。
|
|
94
|
-
- **默认机制**: 若不输入密钥,系统将默认使用密钥 "1"。
|
|
95
|
-
- **版权验证**: 提取出的结果图片若能清晰辨认文字轮廓,即具备版权铁证效力。
|
|
96
|
-
|
|
97
|
-
## 📝 路线图
|
|
98
|
-
|
|
99
|
-
- [ ] 支持 PDF 矢量图层水印
|
|
100
|
-
- [ ] 增加多线程批量处理模式
|
|
101
|
-
- [ ] 集成 AI 深度学习水印算法
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
**Aegis - 为每一份智力成果披上隐形神盾。**
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aegis_watermark-0.1.1 → aegis_watermark-0.2.0}/aegis_watermark.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|