3. 证书颁发与签发:CA 签发流程、证书签名算法、证书颁发策略

证书颁发,说白了就是 CA 给申请者「盖个章」。但这个章怎么盖、用什么笔盖、盖之前要检查什么,里面门道不少。我见过不少团队,证书申请流程跑通了,结果签名算法选错,或者策略配置有漏洞,最后被审计追着改。今天咱们就把这三个环节拆开聊透。

3.1 CA 签发流程:从 CSR 到证书

一个证书从申请到落地,大致走五步。我习惯把这五步画成一张图,团队里新人也容易看懂。

CA 证书签发流程 1. 生成密钥对 2. 创建 CSR 3. 身份验证 4. 签发证书 5. 分发/安装 关键说明 • 步骤 1-2 由申请者(终端实体)完成,步骤 3-4 由 CA 完成 • 步骤 3 是安全核心:CA 必须验证申请者对私钥的控制权 • 步骤 4 包含签名算法选择、有效期设定、扩展项填充

第一步,申请者自己生成密钥对。私钥绝对不能离开申请者环境,这是铁律。第二步,用私钥签名生成 CSR(证书签名请求),里面包含公钥和身份信息。第三步,CA 验证申请者身份——这一步最容易被忽视,我后面会细说。第四步,CA 用自己私钥签发证书。第五步,把证书发回给申请者安装。

小提示:CSR 里的 CN(Common Name)字段,在 TLS 场景下必须与域名完全匹配。我曾经遇到一个案例,CN 写成了 IP 地址,结果浏览器直接报安全警告。现在主流浏览器更倾向 SAN(Subject Alternative Name),建议把域名都放 SAN 里。

3.2 证书签名算法:选错了就是坑

签名算法决定了证书的「防伪能力」。目前主流就两种:RSA 和 ECDSA。我个人的建议是:新项目优先选 ECDSA,兼容性要求高的场景保留 RSA。

算法 密钥长度 签名速度 安全强度 典型场景
RSA 2048 / 4096 位 较慢 高(2048 位以上) 企业 CA、兼容旧设备
ECDSA 256 / 384 位 快 高(P-256 以上) IoT、移动端、高性能场景
Ed25519 256 位 极快 极高 新兴系统、内部 CA

为什么 RSA 还在用?说白了就是兼容性。很多老设备、老浏览器只认 RSA。但 RSA 4096 位的签名计算量很大,高并发场景下 CA 服务器容易扛不住。ECDSA 用 P-256 曲线,安全强度相当于 RSA 3072 位,但签名速度快一个数量级。

避坑指南:我曾经接手过一个项目,CA 用了 SHA-1 签名算法。2017 年以后主流浏览器已经拒绝 SHA-1 证书了。检查一下你的 CA 配置,签名哈希算法至少要用 SHA-256。另外,ECDSA 曲线不要选 secp256k1(比特币用的那条),选 NIST P-256 或者 Curve25519 更通用。

签名算法在签发时怎么配?以 OpenSSL 为例:

# 使用 RSA 2048 + SHA-256 签发
openssl ca -in server.csr -out server.crt \
  -keyfile ca.key -cert ca.crt \
  -md sha256 -days 365

# 使用 ECDSA P-256 + SHA-256 签发
openssl ca -in server.csr -out server.crt \
  -keyfile ca.key -cert ca.crt \
  -md sha256 -days 365 \
  -sigopt ec_paramgen_curve:prime256v1

注意看,-md 指定的是摘要算法,不是签名算法本身。签名算法是 CA 私钥类型决定的。RSA 私钥自然签出 RSA 签名,EC 私钥签出 ECDSA 签名。这个细节很多人搞混。

3.3 证书颁发策略:谁可以拿什么证书

颁发策略就是一套规则:什么身份的人能申请什么类型的证书,需要经过几级审批。没有策略的 CA,就像没有门禁的大楼——谁都能进。

我一般把策略分成三个维度:

  • 身份验证级别:DV(域名验证)、OV(组织验证)、EV(扩展验证)。DV 只要证明你控制域名就行,OV 需要提交营业执照,EV 更严格,要律师函或第三方数据库确认。
  • 证书类型限制:服务器证书、客户端证书、代码签名证书、邮件证书。每种证书的用途不同,CA 应该在配置里限制扩展项。
  • 审批流程:自动签发、单人审批、双人审批。内部 CA 常用自动签发,但生产环境建议至少单人审批。

实际案例:我帮一家金融公司搭内部 CA 时,策略是这样定的:开发环境证书自动签发,有效期 30 天;测试环境需要组长审批,有效期 90 天;生产环境需要安全团队+运维总监双签,有效期 365 天。策略配置在 CA 的 openssl.cnf 里,通过 policy 段和 usr_cert 段控制。

策略配置示例:

[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

policy_match 要求 CSR 里的国家、省份、组织必须与 CA 证书一致,适合企业内严格管控。policy_loose 只要求 CN 必填,其他可选,适合公共 CA 或测试环境。

我的习惯:生产环境用 policy_match,但把 organizationalUnitName 设为 optional。因为不同部门可能用不同 OU,但根组织必须统一。另外,建议在 usr_cert 段里加上 basicConstraints=CA:FALSE,防止终端证书被拿去签其他证书——这个坑我踩过。

3.4 签发中的常见陷阱

最后聊几个我实际遇到过的坑,你碰到了可以少走弯路。

  • 有效期过长:CA/B 基线要求公开 CA 证书最长 825 天,内部 CA 建议不超过 2 年。我见过有人设 10 年,结果密钥泄露后吊销都来不及。
  • 序列号重复:CA 必须保证每个证书序列号唯一。用 OpenSSL 默认配置没问题,但如果你自己写签发脚本,记得用随机数或时间戳。
  • 扩展项缺失:服务器证书必须包含 keyUsage=digitalSignature, keyEncipherment 和 extendedKeyUsage=serverAuth。缺了浏览器不认。
  • CRL/OCSP 配置遗漏:签发时就要指定 CRL 分发点和 OCSP 响应器地址。事后补很麻烦,需要重新签发。

我曾经遇到一个生产事故:运维同事用脚本批量签发 500 个证书,结果忘记设置 -extensions 参数,所有证书都没有 subjectAltName。部署上去后,Chrome 全部报错。最后只能连夜重新签发。所以,签发前一定要用 openssl x509 -text -in cert.crt 检查一遍扩展项。

证书签发不是「点一下按钮就完事」的活。流程、算法、策略,三个环节环环相扣。你把这套东西理清楚了,CA 跑起来才稳当。