OpenSSL 证书链验证详解

证书链验证是 SSL/TLS 安全的核心机制。本文将详细介绍如何使用 OpenSSL 工具进行证书链验证,确保连接的安全性。

什么是证书链?

证书链(Certificate Chain)是一系列证书的有序集合,用于验证终端实体证书的有效性。典型的证书链包含:

  1. 终端实体证书:最终服务的证书
  2. 中间证书:由 CA 签发的证书
  3. 根证书:受信任的根 CA 证书

OpenSSL 验证命令

基本验证

1
2
3
# 验证证书和私钥匹配
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5

证书链验证

1
2
# 验证证书链
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt

实战案例:完整证书链验证

场景描述

验证包含终端证书、中间证书和根证书的完整证书链。

1. 准备证书文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 创建测试目录
mkdir -p /tmp/cert-test
cd /tmp/cert-test

# 生成根证书
openssl genrsa -out root.key 4096
openssl req -x509 -new -nodes -key root.key -sha256 -days 3650 \
  -out root.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=Test Root CA/CN=Test Root CA"

# 生成中间证书
openssl genrsa -out intermediate.key 2048
openssl req -new -key intermediate.key -out intermediate.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Test Intermediate CA/CN=Test Intermediate CA"
openssl x509 -req -in intermediate.csr -CA root.crt -CAkey root.key \
  -CAcreateserial -out intermediate.crt -days 365 -sha256

# 生成终端证书
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Test Server/CN=test.example.com"
openssl x509 -req -in server.csr -CA intermediate.crt -CAkey intermediate.key \
  -CAcreateserial -out server.crt -days 365 -sha256

2. 验证证书链

1
2
3
4
5
# 验证终端证书
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt

# 详细验证过程
openssl verify -verbose -CAfile root.crt -untrusted intermediate.crt server.crt

高级验证选项

1. 检查证书有效期

1
2
3
4
5
# 检查证书有效期
openssl x509 -in server.crt -text -noout | grep "notBefore\|notAfter"

# 验证证书是否过期
openssl x509 -checkend 0 -in server.crt

2. 验证证书用途

1
2
3
4
5
# 检查证书扩展字段
openssl x509 -in server.crt -text -noout | grep "Extended Key Usage"

# 验证证书是否支持服务器认证
openssl x509 -in server.crt -purpose sslserver

3. 验证主机名匹配

1
2
3
4
5
# 验证证书中的主机名
openssl x509 -in server.crt -text -noout | grep "DNS"

# 使用 OpenSSL 验证主机名匹配
openssl s_client -connect test.example.com:443 -servername test.example.com | openssl x509 -noout -text

常见验证问题及解决方案

1. 证书链不完整

1
2
3
4
5
# 错误示例:缺少中间证书
openssl verify -CAfile root.crt server.crt

# 解决方案:提供完整的证书链
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt

2. 证书过期

1
2
3
4
5
6
# 检查证书过期时间
openssl x509 -in server.crt -enddate -noout

# 创建即将过期的证书进行测试
openssl x509 -req -in server.csr -CA intermediate.crt -CAkey intermediate.key \
  -CAcreateserial -out server.crt -days 1 -sha256

3. 主机名不匹配

1
2
3
4
5
# 检查证书中的主机名
openssl x509 -in server.crt -text -noout | grep "Subject: CN"

# 验证主机名匹配
openssl s_client -connect wrong.example.com:443 -servername test.example.com

实用脚本:证书验证自动化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash

# 证书验证脚本
verify_certificate_chain() {
    local server_cert="$1"
    local intermediate_cert="$2"
    local root_cert="$3"
    
    echo "验证证书链..."
    
    # 检查证书文件是否存在
    if [ ! -f "$server_cert" ] || [ ! -f "$intermediate_cert" ] || [ ! -f "$root_cert" ]; then
        echo "错误:证书文件不存在"
        return 1
    fi
    
    # 验证证书链
    if openssl verify -CAfile "$root_cert" -untrusted "$intermediate_cert" "$server_cert"; then
        echo "✓ 证书链验证成功"
        return 0
    else
        echo "✗ 证书链验证失败"
        return 1
    fi
}

# 使用示例
verify_certificate_chain "server.crt" "intermediate.crt" "root.crt"

验证命令测试

让我们验证 OpenSSL 证书验证命令是否正常工作:

1
2
3
4
5
6
7
8
9
# 创建测试证书
openssl req -x509 -newkey rsa:2048 -nodes -keyout test.key \
  -out test.crt -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"

# 验证自签名证书
openssl verify -CAfile test.crt test.crt

# 检查证书详情
openssl x509 -in test.crt -text -noout

总结

证书链验证是确保 SSL/TLS 连接安全的关键步骤。通过 OpenSSL 工具,我们可以:

  • 验证证书链的完整性
  • 检查证书的有效期和用途
  • 确保主机名匹配
  • 自动化证书验证流程

定期验证证书链有助于及时发现和解决证书相关问题,确保服务的安全性。

参考来源