4. 证书签名请求(CSR):从生成到提交的完整指南

证书签名请求,也就是我们常说的 CSR,是整个证书生命周期里第一个真正由你动手的环节。说白了,它就是一份「自我介绍」——你告诉 CA 你是谁,你的公钥是什么,然后请 CA 帮你签个名,变成一张正式的证书。

我在项目中见过太多因为 CSR 格式不对、字段填错导致证书无法使用的案例。所以这一章,我会把 CSR 的生成流程、字段细节、验证方法,以及提交时的注意事项,一次性讲清楚。

4.1 CSR 的生成流程

生成 CSR 的过程,其实就三步:

  1. 生成密钥对 —— 先创建私钥和公钥
  2. 组装请求信息 —— 把身份信息 + 公钥打包
  3. 签名请求 —— 用私钥对上述内容签名,证明你拥有对应的私钥

嗯,这里要注意:签名用的是你自己的私钥,而不是 CA 的。CA 的签名是在签发证书时才做的。

我习惯用 OpenSSL 来生成 CSR,它是最通用的工具。下面是一个典型流程:

# 第一步:生成 RSA 私钥(2048 位)
openssl genrsa -out mykey.pem 2048

# 第二步:从私钥生成 CSR
openssl req -new -key mykey.pem -out mycsr.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=www.example.com"

# 第三步:查看 CSR 内容
openssl req -text -noout -verify -in mycsr.csr

你看,就这么几行命令。但实际项目中,我遇到过有人把私钥权限设成 777,结果被同事误删了。所以我建议:私钥文件权限一定要设为 600,并且做好备份。

核心要点: CSR 的本质是「用私钥签名的自我介绍信」。CA 通过验证 CSR 上的签名,确认你确实拥有对应的私钥,然后才会签发证书。

4.2 CSR 字段详解

CSR 里包含的字段,大部分都来自 X.509 标准。我把它拆成两部分:必填字段和扩展字段。

4.2.1 必填字段(DN 部分)

字段缩写 全称 含义 示例
C Country 国家代码,两位字母 CN
ST State/Province 省或州 Beijing
L Locality 城市 Beijing
O Organization 组织名称 MyCompany
OU Organizational Unit 部门 IT
CN Common Name 通用名称(域名或主体名) www.example.com

这里有个坑:CN 字段对于 SSL/TLS 证书来说,必须是你想要保护的域名。我曾经见过有人把 CN 填成公司全称,结果浏览器报域名不匹配。现在虽然 SAN(主题备用名称)更常用,但 CN 仍然是必填项。

4.2.2 扩展字段

除了 DN 之外,CSR 还可以包含扩展属性。最常见的几个:

  • SubjectAltName (SAN) —— 指定多个域名或 IP,现在浏览器更依赖这个字段
  • Key Usage —— 说明密钥用途(数字签名、密钥加密等)
  • Extended Key Usage —— 更细化的用途(服务器认证、客户端认证等)

我个人习惯在生成 CSR 时,通过配置文件来指定这些扩展字段,而不是用命令行参数。因为配置文件更清晰,也方便团队复用。

# 示例:openssl.cnf 配置文件片段
[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions      = req_ext

[ req_distinguished_name ]
countryName                 = CN
stateOrProvinceName         = Beijing
localityName                = Beijing
organizationName            = MyCompany
organizationalUnitName      = IT
commonName                  = www.example.com

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = www.example.com
DNS.2 = example.com
DNS.3 = api.example.com

小技巧: 如果你需要为多个域名申请证书,一定要在 CSR 里包含 SAN 字段。否则证书签发后,再想加域名就只能重新申请了。

4.3 CSR 的验证

生成 CSR 之后,别急着提交。先验证一下内容是否正确。我一般会检查这几项:

  1. 签名验证 —— 确认 CSR 没有被篡改
  2. 公钥匹配 —— 确认 CSR 里的公钥和你的私钥是一对
  3. 字段完整性 —— 确认 DN 字段没有拼写错误
  4. SAN 字段 —— 确认所有需要的域名都在里面

用 OpenSSL 验证签名很简单:

# 验证 CSR 签名
openssl req -verify -in mycsr.csr -noout

# 如果输出 "verify OK",说明签名有效

我曾经遇到过一个案例:某同事生成的 CSR 签名验证通过了,但提交给 CA 后一直报错。后来发现是他在生成 CSR 时用了不同的私钥文件。所以,我建议你验证完签名后,再确认一下公钥指纹:

# 查看 CSR 里的公钥指纹
openssl req -in mycsr.csr -noout -pubkey | openssl sha256

# 查看私钥对应的公钥指纹
openssl pkey -in mykey.pem -pubout | openssl sha256

# 两个指纹应该完全一致

警告: 永远不要用生产环境的私钥去生成测试用的 CSR。我见过有人把测试 CSR 提交到生产 CA,结果证书绑定了测试域名,生产环境无法使用。建议为不同环境准备不同的密钥对。

4.4 CSR 的提交

CSR 验证通过后,就可以提交给 CA 了。提交方式主要有三种:

提交方式 适用场景 注意事项
Web 门户上传 小型组织、个人 注意 CSR 文件格式(通常要求 PEM 格式)
API 接口提交 自动化部署、大规模管理 需要处理 API 认证和重试机制
邮件提交 传统 CA、审核流程 确保 CSR 内容不被邮件网关截断

提交时,CA 会验证你的 CSR 签名,然后根据你提供的域名或组织信息进行审核。审核通过后,CA 会用它的私钥对你的公钥进行签名,生成最终的证书。

嗯,这里有个细节:CA 在签发证书时,会把 CSR 里的公钥、DN 信息、以及 CA 自己的签名打包成 X.509 证书。所以,CSR 里填的信息,最终会出现在你的证书里。填错了,证书也就错了。

4.5 CSR 生成与提交流程图

下面这张图,把整个流程串起来了。你可以看到从密钥生成到证书签发的完整路径:

CSR 生成与提交流程图 CSR 生成与提交流程 1. 生成密钥对 2. 组装身份信息 + 公钥 3. 私钥签名 CSR 4. 验证 CSR 内容 5. 提交给 CA 签发 关键点 私钥永远不要泄露 CSR 可公开传输 常见错误 CN 与域名不匹配 忘记加 SAN 字段

你看,整个流程其实不复杂。但每个环节都有容易踩坑的地方。我总结了几条经验:

  • 私钥安全第一 —— 生成 CSR 时,私钥不要放在共享目录里
  • CSR 可公开 —— CSR 本身不包含私钥,可以放心传给 CA
  • 保留原始 CSR —— 证书签发后,保留 CSR 文件方便后续排查问题
  • 自动化生成 —— 如果管理大量证书,建议用脚本或工具自动生成 CSR,减少人工错误

总结一下: CSR 是证书生命周期的起点。生成时要确保密钥对正确、字段完整;提交前要验证签名和内容;提交后保留好原始文件。做到这几点,后面的证书签发流程就会顺利很多。