证书管理¶
入库与去重¶
证书入库(cert.store 步骤或 POST /api/certificates 手动上传)按域名
集合去重:同一域名集合再次入库是更新已有记录而非新增,续期重跑不会产生
重复记录。证书链 PEM 与私钥 PEM 落盘到数据目录(见
数据库与数据目录),库中存相对路径与元数据(指纹、签发者、
起止时间、签发账号凭据标识)。
指纹 = 整个叶子证书 DER 的 SHA-256 小写 hex,作为文件目录名与幂等依据。
域名取自 SAN(保序、含 *.);SAN 缺失时回退 Subject CN。
到期状态¶
三态,全局唯一实现(store 实体也委托同一函数,不会两处漂移):
| 状态 | 判定 |
|---|---|
healthy |
not_after > now + 阈值 |
expiring_soon |
not_after <= now + 阈值(恰好等于阈值也算临期;now == not_after 瞬间按临期而非过期) |
expired |
now > not_after |
阈值默认 30 天(续期扫描同一阈值)。判定比较时间点而非天数—— 「剩余 0 天」可能实际已过期 23 小时。
下载格式¶
GET /api/certificates/{id}/download?format=...&password=...:
| format | 别名 | Content-Type | 说明 |
|---|---|---|---|
pem(默认) |
crt |
application/x-pem-file |
证书链 PEM |
der |
— | application/pkix-cert |
叶子证书 DER |
pfx |
p12 |
application/x-pkcs12 |
PKCS#12,默认 AES-256 加密(PBES2 + HMAC-SHA256);口令默认 changeit,alias acmecast |
jks |
— | application/x-java-keystore |
JKS,口令最短 6 位(Java 自身约束);alias 统一转小写 |
p7b |
— | application/pkcs7-mime |
PKCS#7 certs-only |
转换全部在内存中完成(纯 Rust,无 OpenSSL 依赖),不改持久化的 PEM。
下载文件名取首个域名(仅保留字母数字与 .、-、_)。
吊销¶
POST /api/certificates/{id}/revoke,可选 reason(RFC 5280 原因码 0–10,
如 1=keyCompromise、4=superseded):
- 先用签发时记录的 ACME 账号向 CA 吊销;
- CA 报「已吊销」→ 只同步本地状态(
revoked_now=false); - 本地标记吊销时间,并把证书文件归档到
certs/revoked/<指纹>/(只换目录不改名;源文件缺失时保持库中路径不变)。
已吊销的记录重复吊销幂等直接返回;手动上传(无签发账号)的记录返回
422 missing_account——请去对应 CA 的管理渠道吊销。
私钥校验¶
入库/上传时校验私钥与证书匹配:比较私钥推导的公钥与证书 SPKI 的
subjectPublicKey 字节。私钥仅支持 PKCS#8(BEGIN PRIVATE KEY);
PKCS#1(BEGIN RSA PRIVATE KEY)会报错提示先转换:
支持的算法:RSA、ECDSA P-256/P-384、Ed25519。