实现原理:CRL 生成与编码
对应代码:
pkg/crlgen.go· 入口GenerateCRL(req)
CRL 是 CA 签名的"已吊销证书清单",规范在 RFC 5280 §5.3.1。本页讲 reason code 编码、serial 双试解析与一个容易被忽略的省略惯例。
reason code 映射
严格按 RFC 5280 §5.3.1:
| 原因名 | 码 | 备注 |
|---|---|---|
unspecified | 0 | 默认 |
key-compromise | 1 | 私钥泄露 |
ca-compromise | 2 | CA 私钥泄露 |
affiliation-changed | 3 | |
superseded | 4 | |
cessation-of-operation | 5 | |
certificate-hold | 6 | 暂时挂起 |
| — | 7 | RFC 5280 未分配,缺省 |
remove-from-crl | 8 | |
privilege-withdrawn | 9 | |
aa-compromise | 10 |
码 7 是空的
RFC 5280 没分配值 7,cert-skills 的 revocationReasons 映射表里也没有 7。反向映射 reasonCodeToString 遇未知码返回 "unknown (%d)"。
关键惯例:unspecified 时省略扩展
if reasonCode > 0 {
rle.ReasonCode = reasonCode // 仅 >0 时设置
}为什么省略? RFC 5280 规定 unspecified 是默认值,"SHOULD NOT" 显式携带——写了 0 反而不合规。cert-skills 遵守这条惯例。
reasonCode 来源:优先 entry.ReasonCode;若为 0 且 entry.Reason != "" 才查 revocationReasons map。
序列号双试解析
每条 RevokedEntry 的 serial 用 big.Int.SetString 双试(L139-145):
这样 --serials 123456(十进制)和 --serials 0x1E240(十六进制)都能解析。
revocationTime 默认
entry.RevocationTime.IsZero() 时用 time.Now().UTC()(L155-158)。
CRL 模板与签名
Number 类型是 *big.Int。ThisUpdate 默认 time.Now().UTC(),NextUpdate = ThisUpdate + NextUpdate天。
默认值
| 参数 | 默认值 | 位置 |
|---|---|---|
NextUpdate | 30 天 | L62-64 |
Number | 1 | L65-67 |
OutputPath | "crl.pem" | L68-70 |
| PEM block type | "X509 CRL" | L114 |
CRLGenerateRequest 字段
type CRLGenerateRequest struct {
CACertPath string
CAKeyPath string
RevokedCerts []RevokedEntry
NextUpdate int // 天
Number int64
OutputPath string
}
type RevokedEntry struct {
SerialNumber string
RevocationTime time.Time
Reason string // 字符串原因名
ReasonCode int // 数字码(优先)
}keyMatchesCert 三算法支持
loadCertAndSigner(caissuer.go L354-377)按 cert.PublicKey.(type) 分发:
switch pub := cert.PublicKey.(type) {
case *rsa.PublicKey:
sp := priv.(*rsa.PrivateKey).PublicKey
return pub.N.Cmp(sp.N) == 0 && pub.E == sp.E
case *ecdsa.PublicKey:
sp := priv.(*ecdsa.PrivateKey).PublicKey
return pub.X.Cmp(sp.X) == 0 && pub.Y.Cmp(sp.Y) == 0
case ed25519.PublicKey:
sp := priv.(ed25519.PrivateKey).Public().(ed25519.PublicKey)
return pub.Equal(sp)
default:
return false
}配套能力
ParseCRL(L177-202):先尝试 PEM(block type 必须为"X509 CRL"),否则按 DER;x509.ParseRevocationList;CRLInfo.Number =crl.Number.String()VerifyCRLSignature:crl.CheckSignatureFrom(caCert)CheckCertRevokedByCRL(L327-369):按cert.SerialNumber.String()与每个crlInfo.RevokedCerts[i].SerialNumber字符串相等比较
前置条件回顾
生成 CA 时 --is-ca 会自动带上 CRLSign,所以用 cert-skills 自建的 CA 直接能签 CRL。
下一步
- CRL 用法 → CRL 吊销列表
- 在线吊销查询 → 吊销与 HSTS
- PKI 全流程 → 多层 PKI 工作流