meidielo/AES-256-GCM-Python-Tool
GitHub: meidielo/AES-256-GCM-Python-Tool
一个实现 AES-256-GCM 对称加密的 Python 工具,采用 Argon2id 密钥派生,输出自包含的加密载荷。
Stars: 0 | Forks: 0
# AES-256-GCM 安全保险库
[](https://pypi.org/project/aes-secure-vault/)
[](https://pypi.org/project/aes-secure-vault/)
[](LICENSE)
一个实现 AES-256-GCM 对称加密模块,采用 Argon2id 密钥派生,遵循成熟的信封加密模式(类似于 JWE/Fernet)。载荷是自包含的 JSON blob — 无需共享状态或配置文件即可解密。
构建此模块的目的是从基础原理理解认证加密、KDF 参数绑定和防御性输入验证,而不是简单封装高级库。
## 威胁模型
### 此模块能防护的内容
- **静态数据机密性。** 攻击者即使能访问加密后的 blob 但没有密码短语,也无法恢复明文。AES-256-GCM 提供 256 位密钥强度的认证加密。
- **密文篡改。** GCM 的认证标签能检测密文的任何修改。解密会失败而不是返回损坏的数据。
- **头部篡改。** AAD 绑定意味着修改任何未加密的元数据字段(版本、KDF 参数、salt、nonce)也会导致认证标签验证失败 — 即使不触碰密文本身。
- **KDF 降级攻击。** 对 Argon2id 参数强制执行最低限制(ops ≥ 2,memory ≥ 32 MiB)可防止攻击者使用弱密钥派生伪造载荷。
- **离线暴力破解(在合理范围内)。** Argon2id 是内存硬化的,这使得基于 GPU/ASIC 的字典攻击比使用 PBKDF2 或 bcrypt 代价高得多。有效性完全取决于密码熵 — 参见下方限制。
### 此模块无法防护的内容
- **弱密码短语。** Argon2id 可以减缓暴力破解,但无法弥补 4 位密码的不足。密码熵由调用者负责。没有强度检测,也没有强制执行。
- **内存抓取 / 冷启动攻击。** 派生密钥、明文和中间缓冲区在加密和解密过程中存在于进程内存中。具有内存访问权限的攻击者(恶意软件、内存转储、冷启动)可以提取密钥。此模块不会固定、清零或锁定敏感内存 — Python 的垃圾回收器使这不可靠。
- **侧信道 / 时序攻击。** 除了 `cryptography` 库内部提供的常量时间比较外,没有其他保护。Python 运行时本身不具备侧信道抗性。不要在攻击者可以测量执行时间或功耗的场景中使用。
- **量子对手。** AES-256 通过 Grover 算法提供约 128 位后量子安全强度,仍然很强。然而,密钥交换(密码短语 → KDF → 密钥)从更广泛的密码学角度来说不是量子抗性的。这是一个纯对称工具 — 不暴露非对称组件。
- **密钥管理和轮换。** 没有内置机制来轮换密码短语、用新密钥重新加密现有 blob 或使旧载荷失效。每个 blob 都是独立的。
- **依赖项被攻破。** 如果 `cryptography` 库或底层 OpenSSL 实现存在漏洞,此模块也会继承。没有对原语正确性的独立验证。
- **数 GB 级别的文件。** 峰值 RAM 约为载荷大小的 3 倍。100 MiB 的硬限制是为了防止 OOM。对于大文件,请使用分块流式处理(例如 Tink 或 STREAM 密码)。
- **Nonce 重用。** 每次加密都会生成随机的 12 字节 nonce。使用随机 nonce 时,AES-GCM 在同一密钥下约进行 2³² 次加密后碰撞风险才会变得不可忽略。此模块不跟踪 nonce 使用情况 — 依赖 `os.urandom` 的唯一性。
## 安全属性
| 属性 | 详情 |
|---|---|
| 密码算法 | AES-256-GCM(认证加密)|
| 密钥派生 | Argon2id |
| KDF 默认值 | ops=3, memory=64 MiB, p=4, key_len=32 — 超过 OWASP 2023/2024 最低基线(19 MiB / 2 次迭代)。p=4 不是 OWASP 建议;并行度应根据部署硬件调整。|
| KDF 最低限制(解密)| ops ≥ 2, memory ≥ 32 MiB, p ∈ [1, 16] — 弱于默认值;为向后兼容而存在,非安全目标 |
| Salt | 16 字节,每次加密随机生成 |
| Nonce | 12 字节,每次加密随机生成(NIST 标准)|
| 认证标签 | 16 字节,由 GCM 附加到密文 |
| AAD | 版本 + KDF 参数 + salt + nonce 绑定到密文 |
| 载荷限制 | 100 MiB(加密前和解析后强制执行)|
## 内存使用
单次加密/解密操作期间的峰值 RAM 大约是**载荷大小的 3 倍**(100 MiB 载荷约 300 MiB),原因是 base64 编码、中间字符串分配和密文字节数组同时存在。
## 版本控制
| 版本 | AAD 包含 `key_len` | 状态 |
|---|---|---|
| `1.0` | 否 | 支持(仅读取)|
| `2.0` | 是 | 当前版本 |
新载荷始终以 v2.0 写入。v1.0 载荷可以解密,无需任何迁移步骤。
## 需求
**Web UI:** 现代浏览器。无需安装。
**Python CLI / 库:**
- Python 3.8+
- `cryptography>=44.0.0`(自动安装)
## 安装
```
pip install aes-secure-vault
```
开发用(包含 pytest 和 Hypothesis):
```
pip install aes-secure-vault[dev]
```
## Web UI
推荐打开方式:
```
python -m http.server 8000
```
然后在浏览器中访问 `http://localhost:8000`。这可以避免浏览器对通过 `file://` 加载的 WASM 的安全限制。
或者,在文件资源管理器中双击 `index.html` 或运行 `start index.html` — 这在大多数浏览器中有效,但在某些浏览器(尤其是 Chrome)可能会静默失败,因为它会阻止来自 `file://` 的 WASM。
- **加密选项卡** — 输入消息,输入密码短语,复制加密后的 blob
- **解密选项卡** — 粘贴 blob,输入密码短语,读取原始消息
- 完全在客户端运行,通过 [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) 和 [argon2-browser](https://github.com/nicktindall/argon2-browser)(从 CDN 加载,带有 [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) 验证)
- 内容安全策略将脚本执行限制为可信来源
- 载荷大小限制与 Python CLI 相同(100 MiB)
- Blob 与 CLI **完全可互换** — 在浏览器中加密,用 Python 解密,反之亦然
- 限制:二进制载荷和文件加密需要 CLI
## CLI 用法
```
# 加密文件(通过 stdin 安全提示输入密码,并确认)
secure-vault encrypt --file secret.txt --out secret.enc
# 加密内联文本
secure-vault encrypt --text "my secret data" --out secret.enc
# 解密到 stdout
secure-vault decrypt --file secret.enc
# 解密二进制数据到文件
secure-vault decrypt --file secret.enc --out recovered.bin --bytes
```
`python -m secure_vault` 也可作为 `secure-vault` 的替代方案。
加密时,CLI 会提示输入密码短语两次以防止输入错误。Ctrl+C 可在任何提示符下干净退出。
## 库用法
```
from secure_vault import SecureVault
vault = SecureVault()
# 加密(str 或 bytes)
blob = vault.encrypt("my secret data", "a-strong-passphrase-here")
blob = vault.encrypt(b"\x00\xFF binary data", "a-strong-passphrase-here")
# 解密到 str(默认)
plaintext = vault.decrypt(blob, "a-strong-passphrase-here")
# 解密到原始 bytes
raw = vault.decrypt(blob, "a-strong-passphrase-here", return_bytes=True)
```
加密后的 blob 是一个可安全存储或传输的 JSON 字符串:
```
{
"header": {
"v": "2.0",
"kdf": { "ops": 3, "mem": 65536, "p": 4, "key_len": 32 },
"salt": "",
"nonce": ""
},
"ciphertext": ""
}
```
## 异常
| 异常 | 原因 |
|---|---|
| `ValueError` | 空数据、空密码短语、载荷过大、格式错误、不支持的版本、无效的 KDF 参数 |
| `DecryptionError` | 密码短语错误、密文被修改或头部被篡改(AAD 验证失败)|
| `RuntimeError` | Argon2 内存不足、意外的密码错误或解密数据不是有效的 UTF-8 |
## 测试
```
# 完整套件(包括 Hypothesis 模糊测试 — 可能需要几分钟)
pytest test_secure_vault.py -v
# 跳过慢速模糊测试
pytest test_secure_vault.py -v -k "not arbitrary"
```
覆盖率包括:往返正确性、非确定性验证、认证/完整性失败、KDF 边界强制执行、类型规避防护、格式错误载荷拒绝、OOM 限制、MemoryError 路径、传统 v1.0 解密以及使用 Hypothesis 的基于属性的模糊测试。
## 参考资料
- [OWASP 密码存储备忘单 — Argon2id](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html) — KDF 基线声明的依据
- [NIST SP 800-38D — GCM 模式建议](https://csrc.nist.gov/publications/detail/sp/800-38d/final) — AES-GCM 规范和 12 字节 IV 标准
- [RFC 7516 — JSON Web Encryption (JWE)](https://www.rfc-editor.org/rfc/rfc7516) — 本设计所遵循的成熟信封加密模式
- [cryptography 库文档](https://cryptography.io/en/latest/) — AES-GCM 和 Argon2id 的底层实现
标签:AES-256-GCM, Argon2id, GCM模式, KDF, meg, nonce, ProjectDiscovery, PyPI, 信封加密, 信息安全, 内存硬函数, 密码学, 密钥派生, 密钥派生函数, 对称加密, 手动系统调用, 数据保护, 数据加密, 盐值, 离线暴力破解防护, 自动化审计, 认证加密, 逆向工具, 静态加密