AgariusMeredius/ml-pki
GitHub: AgariusMeredius/ml-pki
一个基于 ML-DSA 与 CBOR 的后量子 PKI 库,提供密钥生成、证书签发与吊销的原生支持。
Stars: 0 | Forks: 0
# mlpki
Python 的后量子公钥基础设施库。
`mlpki` 使用
**ML-DSA**(FIPS 204 / CRYSTALS-Dilithium)通过
[liboqs](https://github.com/open-quantum-safe/liboqs) 实现证书管理和数字签名。
所有数据结构均以 **CBOR** 格式序列化,使用整数密钥 —— 无 ASN.1、无 TLS、无密钥交换。该库涵盖完整的 PKI 生命周期:密钥生成、证书签发、CSR 工作流、链验证和吊销。
## 功能特性
- **ML-DSA-44 / 65 / 87** — 全部三种 NIST 后量子安全等级
- **CBOR 序列化**,使用整数密钥和 Unix 时间戳
- **双层证书格式** — TBS 字节单独签名,外层结构携带 `tbs_bytes + sig_alg + signature`
- **证书签名请求(CSR)**,带自签名以证明密钥拥有权
- **完整链验证** — 签名、有效期窗口、CA 标志、
`KEY_CERT_SIGN`、`path_len` 约束、权威密钥标识符匹配、
吊销状态
- **证书吊销列表(CRL)** — 仅追加不可变、CBOR 序列化、
ML-DSA 签名
- **加密密钥存储** — Argon2id 密钥派生 + AES-256-GCM,
CBOR 文件格式
- **类似 PEM 的导出** 用于证书和 CSR(`-----BEGIN ML-CERTIFICATE-----`)
## 要求
- Python ≥ 3.11
- [liboqs](https://github.com/open-quantum-safe/liboqs) 共享库(≥ 0.14)
- `liboqs-python`、`cbor2`、`argon2-cffi`、`cryptography`
## 安装
```
# 1. Build and install liboqs (shared library)
git clone --depth 1 --branch 0.14.0 https://github.com/open-quantum-safe/liboqs.git
cmake -S liboqs -B liboqs/build -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DOQS_BUILD_ONLY_LIB=ON
cmake --build liboqs/build
sudo cmake --install liboqs/build
# 2. Install Python dependencies
pip install liboqs-python cbor2 argon2-cffi "cryptography>=42"
# 3. Install mlpki (editable)
pip install -e .
```
## 快速开始
### 1 — 创建根 CA
```
from mlpki import create_root_ca, Name, ALG_ML_DSA_65, save_secret_key
root_cert, root_sec = create_root_ca(
subject=Name(cn="My Root CA", org="My Organisation"),
validity_days=3650,
alg=ALG_ML_DSA_65,
)
save_secret_key("root_ca.mlkey", root_sec, ALG_ML_DSA_65, b"strong-password")
with open("root_ca.pem", "w") as f:
f.write(root_cert.to_pem())
```
### 2 — 签发证书
```
from mlpki import (
Certificate, generate_keypair, issue_certificate,
load_secret_key, verify_chain, KEY_USAGE_DIGITAL_SIGNATURE,
)
root_cert = Certificate.from_pem(open("root_ca.pem").read())
root_sec, root_alg = load_secret_key("root_ca.mlkey", b"strong-password")
ee_pub, ee_sec = generate_keypair(root_alg)
ee_cert = issue_certificate(
subject=Name(cn="service.example.com", org="My Organisation"),
subject_pub=ee_pub,
issuer_cert=root_cert,
issuer_sec=root_sec,
validity_days=365,
key_usage=KEY_USAGE_DIGITAL_SIGNATURE,
)
verify_chain([ee_cert], trusted_root=root_cert) # raises on failure
```
### 3 — CSR 工作流
```
from mlpki import (
CertificateSigningRequest, generate_keypair,
issue_from_csr, verify_chain, Name, ALG_ML_DSA_44,
)
# --- Applicant ---
pub, sec = generate_keypair(ALG_ML_DSA_44)
csr = CertificateSigningRequest.create(
subject=Name(cn="applicant.example.com", org="Applicant Org"),
pub=pub, sec=sec, alg=ALG_ML_DSA_44,
)
csr_pem = csr.to_pem() # transmit to CA
# --- CA ---
csr = CertificateSigningRequest.from_pem(csr_pem)
assert csr.verify_self_signature()
cert = issue_from_csr(csr, issuer_cert=root_cert, issuer_sec=root_sec)
```
### 4 — 吊销
```
from mlpki import RevocationList
crl = RevocationList.create(root_cert, root_sec, next_update_days=30)
crl = crl.add_serial(ee_cert.tbs.serial, root_cert, root_sec)
from mlpki.verify import VerificationError
try:
verify_chain([ee_cert], trusted_root=root_cert, crl=crl)
except VerificationError as e:
print(e.code) # VerificationCode.REVOKED
```
### 5 — 签名与验证数据
```
from mlpki import generate_keypair, sign, ALG_ML_DSA_65
from mlpki.keys import verify
pub, sec = generate_keypair(ALG_ML_DSA_65)
sig = sign(b"my message", sec, ALG_ML_DSA_65)
ok = verify(b"my message", sig, pub, ALG_ML_DSA_65)
```
## 项目结构
```
mlpki/
├── __init__.py Public API re-exports
├── constants.py Field numbers, algorithm IDs, key-usage flags
├── certificate.py Name, PublicKeyInfo, TBSCertificate, Certificate
├── keys.py Key generation, sign, verify, encrypted storage
├── csr.py CertificateSigningRequest
├── ca.py CA operations (create_root_ca, issue_certificate …)
├── revocation.py RevocationList (CRL)
└── verify.py verify_chain, verify_signature, VerificationError
tests/ pytest suite — 144 tests, no network required
examples/ Runnable end-to-end scripts
docs/ Architecture, API reference, format spec, security
```
## 运行测试
```
pytest tests/ -q
```
## 文档
详细文档位于 [`docs/`](docs/):
| 文件 | 内容 |
|---|---|
| [`architecture.md`](docs/architecture.md) | 模块概览、数据流、设计决策 |
| [`api-reference.md`](docs/api-reference.md) | 每个公共函数的完整 API 参考 |
| [`formats.md`](docs/formats.md) | CBOR 序列化格式规范 |
| [`security.md`](docs/security.md) | 安全注意事项与威胁模型 |
## 使用警告与安全注意事项
### 算法选择
| 变体 | NIST 等级 | 推荐用途 |
|---|---|---|
| `ALG_ML_DSA_44` | 2(128 位经典) | **仅限开发与测试** |
| `ALG_ML_DSA_65` | 3(192 位经典) | 通用生产使用 |
| `ALG_ML_DSA_87` | 5(256 位经典) | 高安全或长寿命证书(> 10 年) |
**不要在生产环境中使用 `ALG_ML_DSA_44`。** 其 128 位经典安全等级是 NIST 接受的最低级别,仅为测试和受限设备提供速度优势。
### 密钥管理
- 使用 `save_secret_key()` 并搭配 **强随机生成的密码**(≥ 32 字节,来自 `secrets.token_bytes()`)。人类可记忆的密码短语不足以保护根 CA 密钥。
- 限制密钥文件权限:`chmod 600 root_ca.mlkey`
- 在不进行签名时,将根 CA 密钥文件存储在 **离线或硬件安全介质** 上。
- 密钥字节为纯 Python `bytes` 对象 —— Python 在垃圾回收时不会清零内存。请将密钥保持在局部作用域;不要将其缓存在全局状态中。
### CRL 新鲜性
`verify_chain()` 现在 **强制** 要求提供的 CRL 的 `next_update` 时间戳在未来。旧的 CRL 将引发 `VerificationError`,错误代码为 `CRL_EXPIRED`。应用程序必须在过期前刷新 CRL:
```
# Refresh before next_update; never let CRLs go stale.
crl = RevocationList.create(issuer_cert, issuer_sec, next_update_days=7)
```
### 链深度
`verify_chain()` 拒绝超过 `max_depth`(默认:10)的链。为扁平 PKI 层次结构设置更严格的限制以减少攻击面:
```
verify_chain([ee_cert], trusted_root=root_cert, max_depth=2)
```
### CSR 处理
`issue_from_csr()` 会自动验证 CSR 自签名。但 CA 仍必须独立应用其自身的 **签发策略** —— 例如,是否接受 CSR 的 `is_ca=True` 请求。该库将 CSR 主题中的请求扩展传输到签发者约束;它不会强制命名策略或组织验证。
### `mlpki` 不提供的内容
- **无密钥交换或机密性** — ML-DSA 仅是签名方案;无 KEM、无 TLS、无加密通道
- **无 OCSP** — 仅通过批处理 CRL 吊销;无实时吊销状态
- **无 X.509 / TLS 兼容性** — 证书使用自定义 CBOR 格式,与现有 X.509 基础设施不兼容
- **无名称约束** — CA 无法限制子 CA 的主题命名空间
- **无时钟偏差容忍** — 有效期检查使用精确整数比较;即使 1 秒的 NTP 漂移也可能导致新签发证书出现 `NOT_YET_VALID`
### 安全审计
于 2026-04-13 完成了完整的安全与功能审计。
请参阅 [`AUDIT.md`](AUDIT.md) 获取所有发现、已应用的修复以及剩余可接受的风险。
## 免责声明
`mlpki` 是一个**实验性研究库**,实现了基于 ML-DSA(FIPS 204)的后量子 PKI 原语。
本库以教育目的、原型设计和后量子证书基础设施评估为目的提供。
**本项目由 Claude Sonnet 4.6 与 Claude Code(Sonnet 4.6)开发、调试和审计。** 完整的代码库(包括设计、实现、测试套件和安全审计)均通过 AI 辅助开发完成。尚未经过合格密码学家的独立人工同行评审。
**本软件不是经过认证的密码学产品,也未经过正式第三方安全评估。**
以下限制适用:
- **不提供任何形式的担保**,明示或暗示,包括对特定用途的适用性或生产环境中的安全性。
- 基于 CBOR 的证书格式 **与 X.509、TLS 或任何标准 PKI 基础设施不兼容**。这是该库独有的自定义格式。
- 后量子密码标准是**近期标准化**的(FIPS 204:2024 年 8 月)。尽管 ML-DSA 被认为能抵抗已知的量子与经典攻击,但更广泛的生态系统(实现、工具链和操作指南)仍在成熟中。
- 正确的安全结果取决于调用者遵循 [`docs/security.md`](docs/security.md) 与 [`AUDIT.md`](AUDIT.md) 中的指导。错误使用 API —— 如跳过链验证、使用过期 CRL 或以不安全方式处理密钥 —— 无法被库阻止。
- 底层 `liboqs` C 库必须独立保持更新。`liboqs` 的安全修复不会通过更新此包自动应用。
**在生产环境或安全敏感环境中部署 `mlpki` 或其衍生作品前,请获得独立密码学家的安全审查。**
## 出口管制
本项目以开源形式发布,不受美国出口管制法规约束,属于公共领域豁免(EAR § 740.17(b)(1))。所使用的密码算法(ML-DSA / FIPS 204、AES-256-GCM)已由 NIST 公开标准化,且其实现在全球范围内均可自由获取。
## 许可证
MIT
标签:AES-256-GCM, Argon2id, Authority Key ID, CBOR, CRL, CSR, CVE, Dilithium, FIPS 204, liboqs, ML-DSA, NIST PQC, PEM, Python, Python 3.11, XML 请求, 公钥基础设施, 吊销, 后量子密码, 安全开发, 安全规则引擎, 密码库, 密钥存储, 密钥对生成, 密钥用途标识, 序列化, 数字签名, 整数键, 无后门, 时间戳, 证书签发, 证书管理, 证书验证, 路径约束, 逆向工具, 量子安全, 链验证