4. PKI核心操作:证书签发、吊销、验证流程
证书的整个生命周期,说白了就三个动作:发出去、用起来、收回来。我在多个项目里跟这三个步骤打交道,每个步骤都有不少坑。今天咱们把这套流程拆开揉碎,一个个讲清楚。
4.1 证书签发——从请求到证书
签发证书,我习惯分三步走:生成密钥对、构造CSR、CA盖章。每一步都不简单。
4.1.1 生成密钥对
用户先在自己的环境里生成一对密钥。私钥必须自己保管好,公钥要随CSR发给CA。生成方式有很多,比如OpenSSL的genpkey、Java的KeyPairGenerator。我个人习惯用RSA 2048或者ECC P-256,兼顾安全和性能。
4.1.2 构造CSR
CSR(证书签名请求)就是申请人把公钥和自己的身份信息打包,用私钥签个名,发给CA。格式是PKCS#10。里面包含:
- 主体DN:比如CN、O、C这些字段。注意DN的唯一性,我曾经遇到两个设备DN相同,导致证书验证冲突。
- 公钥:刚刚生成的那个。
- 扩展:比如SAN(主题备用名称)、Key Usage、Extended Key Usage。这些很关键,少写了证书可能无法用于TLS。
CA收到CSR后,先验证签名的合法性,然后才开始签发流程。
4.1.3 CA签发流程
CA一般会做这些事:
- 验签CSR,确保确属申请人发起。
- 构造证书主体信息,加上序列号、有效期、签发者信息。
- 添加扩展属性,比如基本约束(CA标志)、密钥用法。
- 用CA私钥对证书的TBSCertificate部分签名,生成数字签名。
- 把签名后的数据封装成X.509 v3格式。
签发出来的证书本身不加密,谁都能打开看。它的安全性靠CA的数字签名保证。
4.2 证书验证——信任链与签名完整性
拿到证书后,怎么确定它可靠?验证过程比签发还复杂。我通常按下面几步走:
4.2.1 构建证书链
验证者先从目标证书开始,找它的签发者证书,再找签发者的签发者,直到受信任的根证书。这个过程叫链构建。如果中间证书不全,就会失败。我之前在嵌入式系统里遇到过根证书和中间证书分开存放,应用没配置中间证书,导致链构建不完整。
4.2.2 签名验证
链建好后,逐级验证签名:用上一级证书的公钥验证下一级证书的签名。最后根证书是自签名的,它的公钥需要提前信任,比如预置在系统根证书库里。
4.2.3 有效期检查
每个证书都有notBefore和notAfter字段。验证者要确认当前时间在有效期之内。注意时间同步问题——我在一个项目里因为设备系统时间被篡改,证书刚刚签发就显示过期,后来加了NTP同步才解决。
4.2.4 关键扩展检查
根据证书用途检查扩展:
- Basic Constraints:如果CA标志为False,就不能用于签发下级证书。
- Key Usage:比如数字签名扩展不能用于密钥加密。
- Extended Key Usage:服务器证书的EKU里必须有serverAuth,否则TLS握手会失败。
4.3 证书吊销——把信任收回
证书还没到期就可能需要作废。比如私钥泄露、人员离职、域名变更。这时候就要吊销。主要用两种机制:CRL和OCSP。
4.3.1 CRL(证书吊销列表)
CA定期发布一个列表,里面是所有已被吊销证书的序列号。验证者下载这个列表,检查目标证书的序列号是否在列。CRL分完整CRL和增量CRL。完整CRL每次都包含全部吊销项,增量CRL只包含增量变化。我在项目中更倾向用增量CRL,能减少网络开销。
4.3.2 OCSP(在线证书状态协议)
OCSP实时查询,验证者向CA的OCSP响应器发送请求,返回证书状态(良好、吊销、未知)。OCSP支持stapling,即服务器把OCSP响应附带在TLS握手里,减少客户端访问。另外,OCSP响应可以包含nonce防止重放攻击。
实际项目中,我遇到过OCSP服务器响应缓慢导致TLS握手超时的场景。后来改用stapling,并增加缓存机制,问题解决了。
4.3.3 CRL vs OCSP 对比
| 维度 | CRL | OCSP |
|---|---|---|
| 实时性 | 依赖于更新周期(如每日一更) | 接近实时 |
| 负载 | 列表可能很大,带宽消耗高 | 每次查询小请求,但并发大 |
| 隐私 | 下载列表无特定证书暴露 | OCSP请求暴露了正在查询的证书 |
| 实现复杂度 | 相对简单,只需解析列表 | 需要支持HTTP/GET,响应签名验证 |
| 典型场景 | 离线环境、嵌入式设备 | Web PKI、需要即时响应 |
4.4 流程全景图
下面这张图把签发、验证、吊销放在一起,方便理解整体关系。
- 证书签发包括密钥生成、CSR构造、CA签名三步,每一步都有安全要求。
- 验证的核心是链构建、签名验证、有效期检查和扩展检查,漏一步就可能出问题。
- 吊销机制有CRL和OCSP两种,选择时考虑实时性、负载和隐私。
好了,这套流程搞定了基本逻辑。实际开发中每个环节都有SDK接口需要对接,后面章节咱们会深入到代码层面。记住今天的核心:签发要严谨、验证要完整、吊销要及时。三者缺一,信任体系就崩了。