3、证书申请与CSR:密钥对、签名请求与验证流程

证书申请这件事,说白了就是向CA证明“我是谁,我拥有什么”。而CSR(Certificate Signing Request)就是这个证明的载体。我见过不少运维同学,一把openssl req -new敲下去就完事了,结果证书签发回来发现组织名写错、域名漏了——嗯,这种坑我踩过不止一次。

这一章,我们就把CSR的生成、解析和验证掰开揉碎讲清楚。

3.1 生成密钥对:一切信任的根基

证书的核心是公钥,而公钥必须对应一个私钥。私钥丢了,证书就是一张废纸。所以第一步,先把密钥对生成好。

3.1.1 选择算法与密钥长度

目前主流的选择就两个:

算法 推荐密钥长度 典型场景
RSA 2048 或 4096 位 通用、兼容性最好
ECDSA P-256 或 P-384 性能敏感、IoT、移动端

我个人习惯:服务器证书用 RSA 2048,兼容性无坑;内部系统或新项目优先上 ECDSA P-256,性能更好,密钥也短。

避坑指南: 我曾经遇到一个客户,为了“更安全”选了 RSA 8192,结果TLS握手时CPU飙到100%,客户端频繁超时。密钥太长,不是好事。

3.1.2 生成私钥的命令

RSA私钥生成:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out server.key

ECDSA私钥生成:

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out server.key

生成后,务必检查私钥权限:

chmod 400 server.key

私钥文件权限设为400,只有属主能读。这是底线。

3.2 创建证书签名请求(CSR)

有了私钥,下一步就是生成CSR。CSR里包含你的公钥和身份信息,然后交给CA去签名。

3.2.1 交互式生成CSR

openssl req -new -key server.key -out server.csr

执行后会让你填一堆字段。很多人在这里随便填,结果证书下来发现不能用。我建议你提前准备好配置文件。

3.2.2 使用配置文件生成CSR(推荐)

写一个server.cnf:

[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext

[dn]
C = CN
ST = Beijing
L = Beijing
O = Example Inc.
OU = IT
CN = www.example.com

[req_ext]
subjectAltName = DNS:www.example.com, DNS:example.com

然后一行命令搞定:

openssl req -new -key server.key -out server.csr -config server.cnf

这样生成的CSR,字段统一、不易出错,适合批量操作。

注意: 通用名称(CN)必须与证书使用的主域名一致。SAN(主题备用名称)里要列出所有需要保护的域名。缺少SAN,浏览器会报安全警告。

3.3 CSR字段解析:每一行都有意义

CSR不是纯文本,它是ASN.1编码的。但我们可以用openssl把它解析成可读格式:

openssl req -in server.csr -noout -text

输出大致长这样:

Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = CN, ST = Beijing, O = Example Inc., CN = www.example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub: 
                    04:xx:xx:xx...
        Attributes:
            (none)
        Requested Extensions:
            X509v3 Subject Alternative Name: 
                DNS:www.example.com, DNS:example.com
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:xx:xx:xx...

关键字段说明:

字段 含义 常见错误
Subject 证书持有者的身份信息 组织名(O)与营业执照不一致
Public Key 你的公钥,CA会签入证书 算法或长度不符合CA要求
Subject Alternative Name 证书保护的域名/IP列表 遗漏二级域名或IP
Signature 用私钥对CSR的签名,证明你拥有私钥 签名算法过弱(如SHA1)

这里有个细节:CSR里的签名,是用你的私钥对CSR自身做的签名。CA收到CSR后,会用CSR里的公钥验这个签名。验不过?说明你根本不拥有对应的私钥,CA直接拒绝。

3.4 CSR验证流程:别等CA退回来才后悔

CSR提交给CA之前,自己先验一遍。我习惯三步走:

3.4.1 验证CSR格式与完整性

openssl req -in server.csr -noout -verify

输出verify OK才算通过。如果报错,检查文件是否损坏或编码格式是否正确。

3.4.2 核对CSR内容

用-text查看字段,逐项确认:

  • 国家代码(C)是不是两位大写字母?
  • 组织名(O)有没有拼写错误?
  • 通用名称(CN)是不是主域名?
  • SAN里有没有遗漏?

我曾经帮一个客户排查问题,折腾了两天,最后发现CSR里组织名多了一个空格。CA系统严格匹配,一个空格就导致审核失败。

3.4.3 验证公钥与私钥是否匹配

这一步很多人忽略。先提取CSR里的公钥:

openssl req -in server.csr -noout -pubkey > csr_pub.pem

再提取私钥对应的公钥:

openssl pkey -in server.key -pubout > key_pub.pem

然后比对:

diff csr_pub.pem key_pub.pem

没有输出,说明匹配。有差异?那你可能拿错了私钥,或者CSR是用别的密钥生成的。

核心原则: CSR验证不是可选项,是必选项。每次生成CSR后,花30秒跑一遍验证流程,能省下后面几天的麻烦。

3.5 知识体系:CSR生命周期全景

下面这张图,把CSR从生成到提交的完整流程串起来了。

CSR 生成与验证流程 1. 生成密钥对 2. 创建CSR 3. 验证CSR ✅ 验证通过 → 提交CA ❌ 验证失败 → 重新生成 💡 说明: 验证CSR时,重点检查:格式完整性、字段准确性、公钥与私钥匹配。 这三步都过了,CSR才能放心提交给CA。

这张图把CSR的生成、创建、验证和提交决策串成了一个闭环。你想想看,如果每次生成CSR都按这个流程走一遍,还会出那些低级错误吗?

3.6 本章小结

CSR是证书申请的第一步,也是最重要的一步。密钥对生成要选对算法和长度,CSR字段要填对,提交前一定要自己验一遍。我见过太多因为CSR问题导致证书签发失败或安全告警的案例,说白了,都是细节没到位。