4. 证书签名请求(CSR):从生成到提交的完整流程
CSR,说白了就是你去CA那里办证书的「申请书」。你把自己的公钥和身份信息填进去,CA审核通过后签个字,证书就到手了。这个环节看似简单,但我见过太多团队在这里栽跟头——密钥没保存好、Common Name写错、扩展字段漏了,最后证书下来用不了,还得重新走一遍流程。
嗯,咱们今天就把CSR的来龙去脉彻底讲清楚。
4.1 CSR到底长什么样?里面塞了哪些信息?
CSR本质上是一个PKCS#10格式的请求体,用ASN.1编码,然后Base64包一层。你拿OpenSSL看一眼就能明白:
openssl req -in my.csr -noout -text
输出里你会看到这么几块核心内容:
| 字段 | 说明 | 我的经验 |
|---|---|---|
| Subject | 证书持有者的DN(Distinguished Name) | CN字段最容易填错,后面细说 |
| Public Key | 你的公钥,算法和长度都在这里 | RSA 2048起步,4096更稳妥 |
| Attributes | 可选扩展,比如SAN、密钥用途 | 现代浏览器强制要求SAN,别漏了 |
| Signature | 用你的私钥对CSR签名,证明你持有私钥 | 这是防抵赖的关键 |
Subject里的DN包含这些组件:
- C (Country) — 两位国家代码,比如CN、US
- ST (State/Province) — 省份或州
- L (Locality) — 城市
- O (Organization) — 公司或组织名称
- OU (Organizational Unit) — 部门,比如IT部
- CN (Common Name) — 最关键,域名或服务器名
⚠️ 注意: 从2017年开始,主流浏览器已经不再信任仅依赖CN字段的证书。你必须把域名放到Subject Alternative Names (SAN)里,否则Chrome、Safari会直接报不安全。
4.2 用OpenSSL生成CSR,手把手来一遍
我个人习惯把密钥和CSR分开生成,这样密钥可以单独备份,CSR丢了重新生成就行,不用动密钥。
第一步:生成私钥
openssl genrsa -out server.key 2048
这里有个坑——私钥文件默认权限是644,意味着其他用户也能读。我建议生成后立刻改权限:
chmod 400 server.key
第二步:生成CSR
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=DevOps/CN=www.example.com"
如果你需要SAN扩展,得用配置文件方式:
openssl req -new -key server.key -out server.csr \
-config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:www.example.com,DNS:api.example.com")) \
-reqexts SAN
我曾经帮一个客户排查证书问题,他们生成的CSR里SAN字段是空的,结果证书下来后所有子域名都报错。折腾了两天,最后发现是OpenSSL版本太老,默认配置没加载SAN扩展。
第三步:验证CSR内容
openssl req -in server.csr -noout -text
检查这几项:
- 公钥长度是不是2048位以上
- CN和SAN里的域名对不对
- 签名算法是不是SHA-256(别用SHA-1,已经不安全了)
💡 小技巧: 我习惯把CSR生成命令写成脚本,每次申请证书直接跑脚本,避免手敲出错。脚本里加上日期戳,方便追溯。
4.3 CSR提交与审核流程
CSR生成后,下一步就是提交给CA。流程大致是这样:
CSR提交流程全景图
CA的审核方式取决于证书类型:
| 证书类型 | 验证方式 | 审核时间 | 我遇到的坑 |
|---|---|---|---|
| DV(域名验证) | 邮箱验证 / DNS TXT记录 / HTTP文件验证 | 几分钟到几小时 | 邮箱没配好,验证邮件收不到 |
| OV(组织验证) | 人工审核企业资质 | 1-3个工作日 | 公司名称和营业执照不一致被驳回 |
| EV(扩展验证) | 严格人工审核,电话回访 | 3-7个工作日 | 电话没接到,流程重新走 |
4.4 避坑指南:我踩过的那些CSR的坑
做这行快十年了,CSR相关的翻车现场我见得太多了。挑几个典型的说说:
🚨 坑一:私钥和CSR不匹配
有人拿A密钥生成CSR,提交后把B密钥当成私钥去配证书。结果证书下来后服务起不来,报错说私钥和证书不匹配。解决办法很简单——生成CSR后立刻把密钥和CSR一起归档,文件名带上同样的标识。
有人拿A密钥生成CSR,提交后把B密钥当成私钥去配证书。结果证书下来后服务起不来,报错说私钥和证书不匹配。解决办法很简单——生成CSR后立刻把密钥和CSR一起归档,文件名带上同样的标识。
🚨 坑二:Common Name写成了IP地址
有些内部系统用IP访问,CSR的CN直接写了IP。但公共CA一般不支持IP证书(除非你额外申请)。我建议内部PKI自己签,或者用DNS名称,别跟公共CA较劲。
有些内部系统用IP访问,CSR的CN直接写了IP。但公共CA一般不支持IP证书(除非你额外申请)。我建议内部PKI自己签,或者用DNS名称,别跟公共CA较劲。
🚨 坑三:SAN字段漏了关键域名
这是最常见的。你申请的是 www.example.com 的证书,但用户访问的是 example.com 或者 m.example.com。没有SAN,这些域名全报错。我每次生成CSR都会列一个域名清单,逐个核对。
这是最常见的。你申请的是 www.example.com 的证书,但用户访问的是 example.com 或者 m.example.com。没有SAN,这些域名全报错。我每次生成CSR都会列一个域名清单,逐个核对。
4.5 自动化CSR生成的最佳实践
手动生成CSR偶尔做一次还行,但如果你管理几十上百个域名,必须上自动化。我推荐的做法是:
- 模板化配置 — 把OpenSSL配置文件和SAN清单做成模板,用变量替换域名
- 密钥分级管理 — 生产环境用HSM或密钥管理服务,开发环境用本地文件
- CSR审计日志 — 每次生成CSR都记录时间、域名、操作人,方便追溯
- 预检脚本 — 提交前自动检查CSR内容,比如公钥长度、SAN完整性
💡 我的习惯: 我会写一个Makefile,里面封装好CSR生成、验证、提交的步骤。团队成员只需要
make csr DOMAIN=example.com,剩下的交给脚本。这样既统一又不容易出错。