4. 证书签名请求(CSR):从生成到提交的完整指南
证书签名请求,也就是我们常说的 CSR,是整个证书生命周期里第一个真正由你动手的环节。说白了,它就是一份「自我介绍」——你告诉 CA 你是谁,你的公钥是什么,然后请 CA 帮你签个名,变成一张正式的证书。
我在项目中见过太多因为 CSR 格式不对、字段填错导致证书无法使用的案例。所以这一章,我会把 CSR 的生成流程、字段细节、验证方法,以及提交时的注意事项,一次性讲清楚。
4.1 CSR 的生成流程
生成 CSR 的过程,其实就三步:
- 生成密钥对 —— 先创建私钥和公钥
- 组装请求信息 —— 把身份信息 + 公钥打包
- 签名请求 —— 用私钥对上述内容签名,证明你拥有对应的私钥
嗯,这里要注意:签名用的是你自己的私钥,而不是 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 之后,别急着提交。先验证一下内容是否正确。我一般会检查这几项:
- 签名验证 —— 确认 CSR 没有被篡改
- 公钥匹配 —— 确认 CSR 里的公钥和你的私钥是一对
- 字段完整性 —— 确认 DN 字段没有拼写错误
- 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 可公开 —— CSR 本身不包含私钥,可以放心传给 CA
- 保留原始 CSR —— 证书签发后,保留 CSR 文件方便后续排查问题
- 自动化生成 —— 如果管理大量证书,建议用脚本或工具自动生成 CSR,减少人工错误
总结一下: CSR 是证书生命周期的起点。生成时要确保密钥对正确、字段完整;提交前要验证签名和内容;提交后保留好原始文件。做到这几点,后面的证书签发流程就会顺利很多。