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的查询过程:

  1. 客户端拿到服务器证书后,提取证书序列号和颁发者信息。
  2. 客户端向OCSP服务器发送查询请求。
  3. OCSP服务器返回证书状态:good(有效)、revoked(已吊销)或unknown(未知)。
  4. 客户端根据返回结果决定是否继续连接。

关键区别: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生成、证书签发、吊销机制都过了一遍。下面这张图可以帮你理清整个流程:

证书申请、签发与吊销流程 1. 生成密钥对 私钥本地保存 2. 生成CSR 包含公钥+身份信息 3. 提交CSR给CA 验证身份 4. CA签发证书 按策略签发 5. 部署证书 配置到服务器 6. 证书吊销 CRL / OCSP 关键说明 • 私钥永远不离开本地 • CSR用私钥签名证明持有 • CA按策略验证后签发 • 吊销后需立即更新CRL/OCSP

从这张图可以看出来,证书的生命周期是一个闭环:生成密钥→生成CSR→提交CA→签发证书→部署使用→(必要时)吊销。每一步都有安全风险,每一步都需要相应的防护措施。

我的建议:如果你在管理一个内部CA,一定要把签发策略和吊销机制都自动化。手动操作容易出错,而且效率低。我曾经见过一个团队,吊销证书全靠手动更新CRL,结果有一次忘了更新,被吊销的证书继续用了三个月,直到安全审计才发现。