OpenSSL 是最强大的证书管理工具之一。本文聚焦日常证书管理中最常用的操作:生成、签名、转换和验证。

生成私钥

生成 RSA 私钥

1
2
3
4
5
6
7
8
# 生成 2048 位 RSA 私钥
openssl genrsa -out private.key 2048

# 生成 4096 位 RSA 私钥(更安全)
openssl genrsa -out private.key 4096

# 生成带密码保护的私钥
openssl genrsa -aes256 -out private-encrypted.key 2048

生成 EC 私钥

1
2
3
4
5
# 生成 EC 私钥(P-256 曲线)
openssl ecparam -name prime256v1 -genkey -noout -out ec-private.key

# 生成 EC 私钥(P-384 曲线)
openssl ecparam -name secp384r1 -genkey -noout -out ec-private-384.key

验证私钥:

1
2
3
4
5
# 检查 RSA 私钥
openssl rsa -in private.key -check -noout

# 查看私钥详细信息
openssl rsa -in private.key -text -noout

生成证书签名请求(CSR)

为域名生成 CSR

1
2
3
4
5
6
7
8
9
# 交互式生成 CSR
openssl req -new -key private.key -out domain.csr

# 非交互式生成 CSR(适合脚本)
openssl req -new -key private.key -out domain.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=example.com"

# 查看 CSR 内容
openssl req -in domain.csr -text -noout

多域名 CSR(SAN)

创建配置文件 san.cnf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext

[dn]
C = CN
ST = Beijing
L = Beijing
O = MyCompany
CN = example.com

[req_ext]
subjectAltName = @alt_names

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

使用配置生成 CSR:

1
openssl req -new -key private.key -out multi-domain.csr -config san.cnf

创建自签名证书

快速生成自签名证书

1
2
3
4
5
6
7
8
9
# 单域名自签名证书(有效期 365 天)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
  -days 365 -nodes -subj "/CN=localhost"

# 使用现有私钥生成自签名证书
openssl req -x509 -key private.key -in domain.csr -out cert.pem -days 365

# 查看证书详情
openssl x509 -in cert.pem -text -noout

证书格式转换

OpenSSL 支持多种证书格式转换:

PEM 转 DER

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

DER 转 PEM

1
openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM

PEM 转 PKCS#12(PFX)

1
2
3
4
5
6
7
# 将证书和私钥打包为 PFX
openssl pkcs12 -export -out certificate.pfx \
  -inkey private.key -in cert.pem

# 带证书链的 PFX
openssl pkcs12 -export -out certificate.pfx \
  -inkey private.key -in cert.pem -certfile chain.pem

PKCS#12 转 PEM

1
2
3
4
5
# 提取证书
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out cert.pem

# 提取私钥
openssl pkcs12 -in certificate.pfx -nocerts -out private.key

验证证书链

验证证书有效性

1
2
3
4
5
6
7
8
9
# 验证证书是否过期
openssl x509 -in cert.pem -noout -dates

# 验证证书与私钥是否匹配
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in private.key | openssl md5

# 验证证书链
openssl verify -CAfile ca-bundle.crt cert.pem

测试服务器证书

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 获取服务器证书
openssl s_client -connect example.com:443 -showcerts

# 获取服务器证书并保存
openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null | \
  openssl x509 -outform PEM > server-cert.pem

# 检查证书过期时间
openssl s_client -connect example.com:443 2>/dev/null | \
  openssl x509 -noout -dates

证书信息提取

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 提取证书主题
openssl x509 -in cert.pem -noout -subject

# 提取证书颁发者
openssl x509 -in cert.pem -noout -issuer

# 提取证书序列号
openssl x509 -in cert.pem -noout -serial

# 提取 SAN(Subject Alternative Names)
openssl x509 -in cert.pem -noout -ext subjectAltName

# 提取证书公钥
openssl x509 -in cert.pem -noout -pubkey

实用脚本:证书过期检查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# check-cert-expiry.sh - 检查证书是否即将过期

CERT_FILE=$1
DAYS_WARNING=30

if [ -z "$CERT_FILE" ]; then
    echo "Usage: $0 <certificate-file>"
    exit 1
fi

EXPIRY_DATE=$(openssl x509 -in "$CERT_FILE" -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - CURRENT_EPOCH) / 86400 ))

echo "Certificate expires: $EXPIRY_DATE"
echo "Days left: $DAYS_LEFT"

if [ $DAYS_LEFT -lt $DAYS_WARNING ]; then
    echo "WARNING: Certificate will expire in $DAYS_LEFT days!"
    exit 1
fi

使用方法:

1
2
chmod +x check-cert-expiry.sh
./check-cert-expiry.sh /path/to/cert.pem

参考来源