OpenSSL 常见问题

FreeGuideOnline 最新 2026-07-15

bash

PEM 转 DER(证书)

openssl x509 -in cert.pem -outform der -out cert.der

DER 转 PEM(证书)

openssl x509 -in cert.der -inform der -outform pem -out cert.pem

私钥转换同理,使用 rsa 或 ec 子命令


## 生成与检查密钥

### 如何生成 RSA 私钥?

```bash
# 生成 2048 位 RSA 私钥,并使用 AES256 加密保护
openssl genrsa -aes256 -out private.key 2048

# 生成无密码保护的私钥(不推荐)
openssl genrsa -out private.key 2048

生产环境推荐使用 2048 或 4096 位。若要去除已有私钥的密码:

openssl rsa -in encrypted.key -out decrypted.key

如何使用更现代的 ECDSA 密钥?

# 列出系统支持的椭圆曲线
openssl ecparam -list_curves

# 使用 prime256v1 (即 P-256) 生成私钥
openssl ecparam -genkey -name prime256v1 -out ecdsa.key

ECDSA 在同等安全强度下密钥更小、计算更快,推荐用于现代系统。

如何检查私钥信息?

# 查看私钥的算法、位数和公钥
openssl rsa -in private.key -text -noout
openssl ec -in ecdsa.key -text -noout

如果私钥有密码保护,会提示输入密码。

创建证书签名请求 (CSR) 与自签名证书

如何生成一个 CSR?

推荐使用配置文件方式(避免交互输入),或通过一条命令自动填写:

# 交互式生成 CSR(会询问国家、域名等)
openssl req -new -key private.key -out request.csr

# 一行命令非交互式生成(常用于脚本)
openssl req -new -key private.key -out request.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=www.example.com"

CN(Common Name)对于单域名证书就是完全合格的域名;使用 SAN(主题备用名)更加现代,见下一个问题。

如何生成带有 SAN 的 CSR?

自 Chrome 58 起,浏览器不再信任缺少 SAN 的 SSL 证书。你需要为 CSR 指定 SAN 扩展。首先创建一个配置文件 san.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=MyOrg
CN=www.example.com

[req_ext]
subjectAltName = @alt_names

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

然后执行:

openssl req -new -key private.key -out request.csr -config san.cnf

如何快速生成自签名证书?

自签名证书仅用于内部测试,浏览器会显示“不安全”。

# 生成有效期为 365 天的自签名证书(无 SAN)
openssl req -x509 -newkey rsa:2048 -keyout selfsigned.key -out selfsigned.crt -days 365 -nodes -subj "/CN=localhost"

# 生成带 SAN 的自签名证书(推荐),同样使用配置文件
openssl req -x509 -newkey rsa:2048 -keyout selfsigned.key -out selfsigned.crt -days 365 -nodes -config san.cnf -extensions req_ext

参数说明:

  • -x509 表示直接输出证书而非 CSR。
  • -nodes 表示不加密私钥(no DES)。
  • -days 指定有效期。

证书查看与验证

如何查看证书的详细信息?

# 查看 PEM 格式证书的全部内容(包括有效期、颁发者、SAN)
openssl x509 -in certificate.crt -text -noout

# 查看证书的特定字段
openssl x509 -in certificate.crt -subject -issuer -dates -noout

如何从证书中提取公钥?

openssl x509 -in certificate.crt -pubkey -noout > pubkey.pem

如何验证证书是否匹配私钥?

比较公钥的哈希值:

# 私钥的公钥哈希
openssl rsa -in private.key -modulus -noout | openssl sha256
# 证书的公钥哈希
openssl x509 -in certificate.crt -modulus -noout | openssl sha256

若两个哈希完全相同,则密钥对匹配。

如何验证证书链是否完整?

# 验证由 CA 签发的证书,需要提供中间证书包
openssl verify -CAfile ca-bundle.crt certificate.crt

# 如果是自签名证书或信任锚
openssl verify -CAfile root-ca.crt -untrusted intermediate.crt server.crt

在日常部署中,如果中间证书缺失,浏览器可能无法构建信任链,报 SSL证书不受信任 错误。

格式转换与实用操作

如何将 CRT 和 KEY 合并为 PFX/PKCS#12?

Windows IIS 常用 PFX 格式,包含了证书和私钥。

# 将证书链(yourcert.crt + intermediates.crt)与私钥合并为 pfx
openssl pkcs12 -export -out certificate.pfx -inkey private.key -in yourcert.crt -certfile ca-bundle.crt

如何从 PFX 中提取证书和私钥?

# 提取私钥(需输入原 PFX 密码,之后设置新密码或留空)
openssl pkcs12 -in certificate.pfx -nocerts -out private.key -nodes
# 提取所有证书(包括叶子证书和 CA)
openssl pkcs12 -in certificate.pfx -nokeys -out fullchain.crt

证书文件里包含多段 BEGIN/END ,如何拆分?

一个文件包含服务器证书、中间证书、根证书时,可以手动或使用命令拆分:

# 使用 awk 拆分第一个证书
awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/' fullchain.pem | head -n $(( $(grep -c "CERTIFICATE" fullchain.pem)/2 )) > server.crt

更可靠的方法是使用工具 csplitopenssl 分行读取:

csplit -f cert- fullchain.pem '/-----BEGIN CERTIFICATE-----/' '{*}'

然后删除空文件,按需重命名。

如何在不解密私钥的情况下移除密码?(其实就是“解密”)

openssl rsa -in encrypted.key -out decrypted.key
# ECDSA 私钥
openssl ec -in encrypted_ec.key -out decrypted_ec.key

注意这会生成一份无密码保护的私钥文件,权限应设置为 600。

连接与调试

如何使用 OpenSSL 测试远程服务器的 SSL/TLS 支持?

# 测试基本连接并显示证书链
openssl s_client -connect example.com:443 -showcerts

# 指定使用的 TLS 版本,如测试 TLS 1.2
openssl s_client -connect example.com:443 -tls1_2

# 使用 SNI 指定域名(某些服务器需要)
openssl s_client -connect 1.2.3.4:443 -servername example.com

如何检查证书是否即将过期?

# 获取远程证书过期时间
echo | openssl s_client -servername www.example.com -connect www.example.com:443 2>/dev/null | openssl x509 -noout -dates

# 本地证书过期时间
openssl x509 -in certificate.crt -noout -enddate

常见的 unable to get local issuer certificate 错误怎么解决?

该错误表示 OpenSSL 在验证链时找不到颁发者证书(中间 CA)。解决方式:

  1. 确保你拥有完整的中间证书(通常 CA 会提供 bundle)。
  2. 在命令中使用 -CAfile 指向包含根证书和中间证书的 bundle 文件。
  3. 如果是自签名证书,需要在客户端信任该根证书。

杂项与批量处理

如何生成随机密码或随机数据?

# 生成 32 位随机十六进制字符串
openssl rand -hex 32

# 生成 base64 编码的 48 字节随机数
openssl rand -base64 48

如何批量转换某个目录下所有 CER 为 PEM?

for f in *.cer; do
    openssl x509 -in "$f" -inform der -out "${f%.cer}.pem" -outform pem
done