3. 证书申请(CSR):生成密钥对、创建证书签名请求

证书申请这一步,说白了就是向CA证明“我是谁,我想要什么”。你想想看,CA不可能凭空给你发证书,你得先提交一份正式的申请材料。这份材料就是CSR——证书签名请求。

我刚开始做PKI的时候,觉得CSR不就是个文件嘛,随便生成一下就行。后来在项目中吃过亏,才发现这里面门道不少。密钥对生成得不对,CSR字段填错了,提交上去被CA打回来,一来一回耽误好几天。嗯,咱们今天就把这块彻底讲透。

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

证书的核心是公私钥对。私钥你死死守住,公钥放进CSR里交给CA。CA签名后,公钥就和你的身份绑定了。

我个人习惯用OpenSSL来生成密钥对。为什么?因为它跨平台、标准、可控。你当然也可以用Java的keytool、Windows的certreq,或者各种云平台的管理工具,但底层逻辑都一样。

3.1.1 密钥类型与算法选择

目前主流的选择就三种:RSA、ECC(ECDSA)、Ed25519。我列个表,你一看就明白。

算法 推荐位数/曲线 安全强度 性能特点 适用场景
RSA 2048 / 4096 高 签名慢,验证快 兼容性最好,旧系统首选
ECC (ECDSA) P-256 / P-384 高(同等强度密钥更短) 签名快,密钥小 移动端、IoT、高性能场景
Ed25519 固定255位 极高 极快,抗侧信道 新兴系统、现代协议
我的建议: 如果系统兼容性要求高,选RSA 2048。如果是新项目,直接上ECC P-256。Ed25519虽然好,但有些CA和旧设备还不支持,你得先确认。

3.1.2 生成RSA密钥对

这是最常用的方式。命令很简单,但有几个参数你得注意。

# 生成RSA私钥,2048位,带加密保护
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 \
  -aes-256-cbc -pass pass:YourStrongPassword \
  -out server.key

# 或者用传统方式(我个人更推荐genpkey)
openssl genrsa -aes256 -out server.key 2048

这里有个关键点:私钥一定要加密。我见过有人直接生成不加密的私钥,然后不小心传到代码仓库里……后果你懂的。用-aes-256-cbc或者-aes256,设置一个强密码。

警告: 私钥密码丢了,服务器重启时证书加载失败,服务直接挂掉。我曾经帮一个客户排查过这个问题——他们运维把密码存在Excel里,Excel丢了……后来我们不得不重新签发所有证书。密码要妥善保管,建议用密码管理器或HSM。

3.1.3 生成ECC密钥对

ECC的密钥生成更简洁,因为曲线是固定的。

# 生成ECC私钥,使用P-256曲线(也叫prime256v1)
openssl ecparam -genkey -name prime256v1 -out ecdsa.key

# 或者用genpkey统一风格
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 \
  -out ecdsa.key

常用的曲线就几个:prime256v1(P-256)、secp384r1(P-384)、secp521r1(P-521)。我个人建议P-256就够了,P-384性能开销大不少,安全增益却有限。

3.2 创建CSR:把你的身份写进文件

密钥对生成好了,下一步就是创建CSR。CSR里包含你的公钥和身份信息,然后用私钥签名——证明你确实拥有对应的私钥。

3.2.1 CSR包含的关键字段

CSR的核心是DN(Distinguished Name,专有名称)。DN由一系列字段组成,我列个表说明。

字段缩写 全称 含义 必填? 示例
C Country 国家代码,两位字母 通常必填 CN
ST State/Province 省/州 推荐 Beijing
L Locality 城市 推荐 Beijing
O Organization 组织名称 通常必填 Example Inc.
OU Organizational Unit 部门 可选 IT Security
CN Common Name 通用名称,通常是域名 必填 www.example.com
重点: CN字段是CSR里最重要的。对于SSL/TLS证书,CN必须是你想要保护的域名。对于客户端证书,CN通常是用户名或邮箱。填错了,CA签出来的证书就没法用。

除了DN,CSR还包含:

  • 公钥:你刚生成的密钥对里的公钥部分
  • 签名算法:比如sha256WithRSAEncryption
  • 属性:可以附加额外信息,比如SAN(Subject Alternative Name,主题备用名称)

3.2.2 生成CSR的命令

有了私钥,生成CSR就一行命令的事。

# 从RSA私钥生成CSR
openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Example Inc./OU=IT/CN=www.example.com"

# 交互式输入(适合手动操作)
openssl req -new -key server.key -out server.csr

我习惯用-subj参数一次性指定所有字段,这样脚本化部署很方便。交互式输入容易出错,而且没法自动化。

3.2.3 添加SAN扩展

现在的浏览器已经不再信任只带CN的证书了。SAN是必须的。你需要在生成CSR时通过配置文件来添加SAN。

# 创建一个配置文件 san.cnf
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

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

[v3_req]
keyUsage = keyEncipherment, digitalSignature
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

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

然后用这个配置文件生成CSR:

openssl req -new -key server.key -out server.csr -config san.cnf
避坑指南: 我曾经遇到一个案例,运维人员生成CSR时忘了加SAN,CA那边也没提醒,直接签发了证书。结果部署到Nginx上,Chrome访问直接报“NET::ERR_CERT_COMMON_NAME_INVALID”。最后只能重新生成CSR、重新提交、重新签发,白白浪费了两天。所以,生成CSR时一定要确认SAN包含所有需要的域名。

3.3 CSR验证:提交前先自查

CSR生成后,别急着提交。先验证一下,确保内容正确。我一般用下面几个命令来检查。

3.3.1 查看CSR内容

# 以可读文本形式查看CSR
openssl req -in server.csr -noout -text

# 只看主题字段
openssl req -in server.csr -noout -subject

# 查看公钥信息
openssl req -in server.csr -noout -pubkey

输出里你会看到:

  • Subject:确认DN字段是否正确
  • Subject Public Key Info:确认算法和密钥长度
  • X509v3 extensions:确认SAN、Key Usage等扩展
  • Signature Algorithm:确认签名算法

3.3.2 验证私钥与CSR的匹配

这个步骤很多人会跳过,但我觉得非常必要。确保CSR里的公钥确实来自你手里的私钥。

# 从私钥提取公钥
openssl pkey -in server.key -pubout -out pub_from_key.pem

# 从CSR提取公钥
openssl req -in server.csr -noout -pubkey -out pub_from_csr.pem

# 比较两个公钥是否一致
diff pub_from_key.pem pub_from_csr.pem

如果diff没有输出,说明匹配。如果有差异,那就是私钥和CSR对不上——这种情况我遇到过,通常是搞混了多个密钥文件。

注意: 验证CSR时,确保私钥文件没有被意外修改。我习惯在生成CSR后立即做这个校验,避免后续排查时浪费时间。

3.4 CSR提交:把申请递到CA手上

CSR验证通过后,就可以提交给CA了。提交方式取决于你的CA类型。

3.4.1 企业CA(内部PKI)

如果你用的是企业内部CA(比如Microsoft AD CS、EJBCA、OpenCA),通常通过Web界面或API提交。

  • Web界面:上传CSR文件,选择证书模板,提交申请
  • API:用REST/SOAP接口发送CSR内容,自动审批或等待管理员审核

3.4.2 公共CA(如DigiCert、Let's Encrypt)

  • 传统方式:在CA门户上传CSR,填写验证信息,等待人工或自动验证
  • ACME协议:Let's Encrypt等现代CA支持ACME,自动完成CSR提交和证书签发。我个人非常推荐这种方式,省时省力

3.4.3 提交时的注意事项

  • CSR格式:大部分CA接受PEM格式(以-----BEGIN CERTIFICATE REQUEST-----开头)
  • 域名验证:公共CA会要求你证明域名所有权,通常通过DNS TXT记录或HTTP文件验证
  • 组织验证:OV/EV证书需要提交企业资质文件,审核周期较长

3.5 本章核心流程总结

我把整个证书申请流程画了张图,方便你理解整体脉络。

证书申请(CSR)核心流程 1. 生成密钥对 RSA 2048 / ECC P-256 2. 创建CSR 填写DN + SAN扩展 3. 验证CSR 检查字段 + 密钥匹配 4. 提交CSR Web / API / ACME 5. CA验证 域名 / 组织验证 6. 签发证书 CA签名,生成证书 关键说明: • 密钥对生成后,私钥必须加密存储,公钥放入CSR • CSR中的CN和SAN是CA签名的核心依据,务必准确 • 提交前一定要验证CSR内容,特别是公钥与私钥的匹配 • 公共CA的域名验证通常需要DNS或HTTP方式,提前准备好 • 整个流程中,私钥始终不应离开你的控制范围

你看,整个流程其实不复杂。但每个环节都有坑。密钥生成时算法选错、CSR字段填错、SAN遗漏、提交前不验证——这些我都踩过。嗯,现在你知道了这些,应该能少走不少弯路。

证书申请是PKI生命周期里的第一步,也是决定后续所有环节能否顺利进行的关键。把这一步做扎实了,后面的证书部署、续期、吊销都会顺畅很多。