4. 证书申请与签发:CSR生成、签发策略与吊销机制
证书申请与签发,是整个PKI体系里最核心的环节。说白了,就是你怎么向CA证明“我是我”,然后CA怎么给你发一张可信的身份证。我这些年处理过不少证书相关的故障,有一半以上都出在这个环节——要么是CSR格式不对,要么是签发策略没配好,导致证书用不了。
今天咱们就把这块彻底讲透。从CSR怎么生成,到CA怎么签发,再到证书出问题了怎么吊销,一条线捋清楚。
4.1 CSR生成流程——你的“身份申请书”
CSR,全称Certificate Signing Request,证书签名请求。你可以把它理解成一张申请表:你把你的公钥和一些身份信息填进去,然后用自己的私钥签个名,交给CA。CA验证通过后,就给你签发证书。
核心要点:CSR里包含的是你的公钥,不是私钥。私钥永远不要离开你本地。我在项目中见过有人把私钥一起发给CA,这是严重的安全事故。
4.1.1 生成密钥对
第一步,先得有一对密钥。我习惯用OpenSSL来操作,它几乎是业界标准。下面是一个生成RSA 2048位私钥的例子:
# 生成RSA私钥,2048位
openssl genrsa -out server.key 2048
# 查看私钥信息(可选)
openssl rsa -in server.key -text -noout
这里要注意几点:
- 密钥长度:2048位是当前最低标准,我个人建议用4096位。虽然生成慢一点,但安全性高很多。
- 密钥保护:生产环境一定要给私钥设置密码保护,用
-aes256参数。我曾经遇到过服务器被入侵,私钥没加密,直接被拖走,那叫一个惨。 - 密钥存储:私钥文件权限要设置为600或400,只允许root用户读取。
4.1.2 生成CSR文件
有了私钥,就可以生成CSR了。你需要提供一些身份信息,也就是证书的Subject字段:
# 生成CSR,交互式输入信息
openssl req -new -key server.key -out server.csr
# 或者用配置文件批量生成(推荐)
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=www.example.com"
Subject字段的各个部分含义如下:
| 字段 | 含义 | 示例 | 是否必填 |
|---|---|---|---|
| C | 国家代码 | CN(中国) | 是 |
| ST | 省份/州 | Beijing | 推荐 |
| L | 城市 | Beijing | 推荐 |
| O | 组织名称 | MyCompany | 是 |
| OU | 部门名称 | IT | 可选 |
| CN | 通用名称(域名) | www.example.com | 是 |
小技巧:CN字段一定要和实际使用的域名完全一致。比如你证书里写的是www.example.com,但用户访问的是example.com,浏览器就会报证书错误。我建议在CSR里同时申请SAN(Subject Alternative Name),把多个域名都列进去。
4.1.3 查看CSR内容
生成之后,最好检查一下CSR内容是否正确:
# 查看CSR的明文内容
openssl req -in server.csr -text -noout
你会看到类似这样的输出:
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = CN, ST = Beijing, O = MyCompany, CN = www.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Attributes:
a0:00
Signature Algorithm: sha256WithRSAEncryption
Signature Value: [一堆十六进制数据]
嗯,这里要注意:CSR里的签名是用你的私钥生成的,CA会用CSR里的公钥去验证这个签名。如果验证通过,说明你确实持有对应的私钥。这就是“证明你是你”的过程。
4.2 证书签发策略——CA怎么决定发不发
CA收到CSR后,不会直接签发。它有一套完整的签发策略,说白了就是一套规则:什么情况下可以发,什么情况下拒绝,发多长时间的证书,能不能续期等等。
4.2.1 签发策略的核心要素
我整理了一个表格,把常见的策略项列出来:
| 策略项 | 说明 | 典型值 |
|---|---|---|
| 证书有效期 | 证书从签发到过期的时间 | 1年(内部CA可设3-5年) |
| 密钥用途 | 证书可以用来做什么 | digitalSignature, keyEncipherment |
| 扩展密钥用途 | 更细粒度的用途限制 | serverAuth, clientAuth |
| 域名验证 | 是否验证申请者对域名的所有权 | 必须验证 |
| 组织验证 | 是否验证企业资质 | OV/EV证书必须验证 |
| 吊销检查 | 签发前是否检查申请者历史 | 建议开启 |
你想想看,如果CA什么策略都不设,随便谁都能申请到任意域名的证书,那整个互联网就乱套了。所以策略的核心目的就是:确保只有合法主体才能获得对应身份的证书。
4.2.2 用OpenSSL配置签发策略
如果你自己搭建CA,签发策略是通过配置文件来定义的。下面是一个典型的策略配置片段:
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
这里match表示CSR里的字段必须和CA证书里的对应字段一致,supplied表示必须提供但不能为空,optional表示可有可无。我个人习惯用policy_match来签发服务器证书,用policy_anything来签发测试证书。
注意:签发策略不是摆设。我曾经接手过一个项目,CA的签发策略配成了policy_anything,结果内部有人给自己签了一张CN为“*”的通配符证书,理论上可以冒充任何内部系统。后来我们紧急吊销了那张证书,并收紧了策略。
4.2.3 签发证书的实际操作
策略配好之后,签发证书就很简单了:
# 用CA私钥签发证书
openssl ca -in server.csr -out server.crt \
-config openssl.cnf \
-extensions server_cert \
-days 365
这里-extensions server_cert指定了证书扩展,比如SAN、密钥用途等。这些扩展会直接写入最终证书,影响证书的使用范围。
4.3 证书吊销——证书的“死亡宣告”
证书不是发了就万事大吉。私钥泄露、域名变更、员工离职……这些情况都需要把证书“作废”。吊销机制就是干这个的。
目前主流的有两种方式:CRL和OCSP。我分别讲一下。
4.3.1 证书吊销列表(CRL)
CRL,Certificate Revocation List,说白了就是一张“黑名单”。CA定期发布一个列表,里面是所有被吊销的证书序列号。客户端拿到证书后,去下载这个列表,看看自己的证书在不在里面。
生成CRL的命令:
# 生成CRL
openssl ca -gencrl -out ca.crl -config openssl.cnf
# 查看CRL内容
openssl crl -in ca.crl -text -noout
CRL有个明显的缺点:实时性差。CA可能一天才更新一次CRL,如果证书刚被吊销,客户端拿到的还是旧列表,就会认为证书有效。我遇到过客户被钓鱼网站骗了,就是因为钓鱼证书虽然被吊销了,但CRL还没更新,浏览器没检测出来。
4.3.2 在线证书状态协议(OCSP)
OCSP,Online Certificate Status Protocol,是CRL的升级版。它不再依赖客户端下载整个列表,而是让客户端直接向OCSP服务器查询某个证书的状态。实时性更好,效率也更高。
OCSP的查询过程:
- 客户端拿到服务器证书后,提取证书序列号和颁发者信息。
- 客户端向OCSP服务器发送查询请求。
- OCSP服务器返回证书状态:good(有效)、revoked(已吊销)或unknown(未知)。
- 客户端根据返回结果决定是否继续连接。
关键区别:CRL是“拉模式”,客户端主动去拉列表;OCSP是“查模式”,客户端逐个查询。OCSP的实时性更好,但OCSP服务器本身可能成为性能瓶颈或单点故障。
4.3.3 OCSP Stapling——解决OCSP的性能问题
OCSP虽然好,但有个问题:每次客户端连接都要去查OCSP服务器,如果网站访问量大,OCSP服务器扛不住。而且客户端查OCSP的过程是明文的,会泄露用户访问了哪些网站。
解决方案就是OCSP Stapling。说白了,就是服务器自己定期去OCSP服务器查询自己的证书状态,然后把结果“钉”在TLS握手过程中发给客户端。客户端就不用再去查了。
Nginx配置OCSP Stapling的示例:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
# 开启OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/ca-chain.crt;
# 指定OCSP服务器地址
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
}
我个人强烈建议生产环境开启OCSP Stapling。它既解决了OCSP的性能问题,又保护了用户隐私,一举两得。
4.4 本章小结——一张图看懂证书生命周期
好了,咱们把CSR生成、证书签发、吊销机制都过了一遍。下面这张图可以帮你理清整个流程:
从这张图可以看出来,证书的生命周期是一个闭环:生成密钥→生成CSR→提交CA→签发证书→部署使用→(必要时)吊销。每一步都有安全风险,每一步都需要相应的防护措施。
我的建议:如果你在管理一个内部CA,一定要把签发策略和吊销机制都自动化。手动操作容易出错,而且效率低。我曾经见过一个团队,吊销证书全靠手动更新CRL,结果有一次忘了更新,被吊销的证书继续用了三个月,直到安全审计才发现。