一、前言
在当今数字化时代,安全性和信任是任何在线交易和通信的基石。无论是访问一个安全的网站、发送一封加密邮件,还是下载一个可信的软件,数字证书都在背后默默地发挥着至关重要的作用。数字证书作为公钥基础设施(PKI
)的核心组件,通过验证身份和加密数据,确保了互联网和其他网络环境中的安全性和完整性。
数字证书不仅仅是一个简单的加密工具,它们代表了一种信任机制,是确保数据传输和身份验证的关键。随着网络威胁的不断演变和复杂化,理解和正确使用数字证书变得比以往任何时候都更加重要。
二、数字证书标准:X.509
ITU(International Telecommunication Union):负责信息和通信技术(ICT)领域的国际标准化和协调,包括无线电通信、电信网络、互联网技术和多媒体技术。 (ITU-T G.992.1:ADSL 标准、 ITU-R BT.2020:超高清电视(UHDTV)标准、ITU-T H.264:视频压缩标准、ITU-T G.711:音频压缩标准)
ISO(International Organization for Standardization):负责制定和发布广泛领域的国际标准,包括质量管理、环境管理、信息安全等。
IEC(International Electrotechnical Commission):负责制定和发布电工电子技术领域的国际标准,包括电气设备、电子元件、可再生能源等。
除了 ISO、IEC 和 ITU 这三个国际标准化组织外,IETF、IEEE、W3C 和 ANSI 也是重要的国际标准化组织。
数字证书和X.509
之间的关系可以总结为:X.509
是ITU-T
制定的证书标准,它定义了数字证书的格式和内容。大多数现代数字证书都是基于X.509
标准的。X.509
证书已应用在包括TLS/SSL
在内的众多网络协议里,同时它也用在很多非在线应用场景里,比如电子签名服务。X.509
证书里含有公钥、身份信息(比如网络主机名,组织的名称或个体名称等)和签名信息(可以是证书签发机构CA
的签名,也可以是自签名)。
X.509
还附带了证书吊销列表和用于从最终对证书进行签名的证书签发机构直到最终可信点为止的证书合法性验证算法。X.509
是ITU-T
标准化部门基于他们之前的ASN.1
定义的一套证书标准。
2.1、X.509 证书内容
证书信息主要分为三类:
- 被颁发者信息:颁发的域名、关联子域以及所颁给的个人、企业、组织信息等等
- 证书机构信息:证书颁发机构名称、数字签名等等
- 证书信息:证书的版本号、序列号、签名算法、签发日期、到期日期、公钥等等
2.1.1、主要字段
版本号(Version):指定证书的版本,当前常用的是版本
3
。序列号(Serial Number):由证书颁发机构分配的唯一编号,用于唯一标识证书。
签名算法标识符(Signature Algorithm Identifier):指定用于签名证书的算法,如
SHA-256 with RSA
。发行者(Issuer):证书颁发机构的名称,通常包括组织名、国家等信息。
有效期(Validity Period):包含证书的起始日期(
Not Before
)和终止日期(Not After
)。主体(Subject):证书持有者的名称,通常包括个人或组织名、部门、国家等信息。
主体公钥信息(Subject Public Key Info):包含主体的公钥及其算法信息。
扩展字段(Extensions):版本
3
证书中引入的可选字段,用于添加额外的信息,如密钥使用、证书策略等。签名值(Signature Value):证书颁发机构对证书内容的数字签名,用于验证证书的完整性和真实性。
证书的结构示例:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
01:23:45:67:89:ab:cd:ef
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Example CA, O=Example Organization, C=US
Validity
Not Before: Jan 1 00:00:00 2023 GMT
Not After : Jan 1 00:00:00 2024 GMT
Subject: CN=www.example.com, O=Example Organization, C=US
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:ab:cd:ef:...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Digital Signature, Key Encipherment
X509v3 Basic Constraints:
CA:FALSE
Signature Algorithm: sha256WithRSAEncryption
ab:cd:ef:...
2.1.2、证书撤销列表
证书撤销列表(Certificate Revocation List, CRL
)是由证书颁发机构(CA
)发布的一个列表,包含所有已被撤销的证书的序列号。CRL
用于检查证书的吊销状态,确保证书的有效性。
CRL 的主要字段:
版本号(Version):指定
CRL
的版本,当前常用的是版本2
。签名算法标识符(Signature Algorithm Identifier):指定用于签名
CRL
的算法,如SHA-256 with RSA
。发行者(Issuer): 证书颁发机构的名称。
这个更新(This Update):
CRL
发布的时间。下次更新(Next Update):下次发布
CRL
的预期时间。已撤销证书列表(Revoked Certificates):包含所有被撤销证书的序列号和撤销时间。
扩展字段(Extensions):可选字段,用于添加额外的信息。
签名值(Signature Value):证书颁发机构对
CRL
内容的数字签名。
CRL 的结构示例:
Certificate Revocation List (CRL):
Data:
Version: 2 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Example CA, O=Example Organization, C=US
This Update: Jan 1 00:00:00 2023 GMT
Next Update: Jan 1 00:00:00 2024 GMT
Revoked Certificates:
Serial Number: 01:23:45:67:89:ab:cd:ef
Revocation Date: Jan 1 00:00:00 2023 GMT
Serial Number: 10:20:30:40:50:60:70:80
Revocation Date: Feb 1 00:00:00 2023 GMT
Signature Algorithm: sha256WithRSAEncryption
ab:cd:ef:...
2.1.3、认证框架
X.509
还定义了一个认证框架(Authentication Framework
),用于在公钥基础设施(PKI
)中实现实体身份的认证和信任管理。这个框架包括:
证书颁发机构(CA):负责签发和管理证书,确保证书的真实性和完整性。
注册机构(RA):负责验证申请者的身份,并向
CA
提交签名请求。证书持有者(Certificate Holder):持有
X.509
证书的实体,使用证书进行身份验证和加密通信。依赖方(Relying Party):依赖证书进行身份验证和加密通信的实体。
2.1.4、如何读取证书内容
openssl
读取证书内容
openssl x509 -in baidu.com.pem -text -noout
openssl x509 -inform der -in baidu.com.der -text -noout
查看证书的特定部分:
openssl x509 -in baidu.com.pem -noout -subject
openssl x509 -in baidu.com.pem -noout -issuer
openssl x509 -in baidu.com.pem -noout -fingerprint
查看 PEM 格式的 CRL:
openssl crl -in baidu.com.pem -text -noout
查看私钥内容:
openssl rsa -in privatekey.pem -check -noout
Golang
读取证书信息Demo
:
import (
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"fmt"
"io/ioutil"
"log"
)
func main() {
// 读取PEM格式的证书文件
certPEM, err := ioutil.ReadFile("./baidu.com.pem")
if err != nil {
log.Fatalf("无法读取文件: %v\n", err)
}
// 解码PEM块
block, _ := pem.Decode(certPEM)
if block == nil {
log.Fatalf("无法解码PEM块\n")
}
// 解析X.509证书
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
log.Fatalf("无法解析证书: %v\n", err)
}
// 打印证书详细信息
fmt.Printf("证书颁发者:\n\t组织: %v\n\t组织单位: %v\n\t国家: %v\n\t省份: %v\n\t城市: %v\n\t通用名称: %s\n",
cert.Issuer.Organization, cert.Issuer.OrganizationalUnit, cert.Issuer.Country, cert.Issuer.Province, cert.Issuer.Locality, cert.Issuer.CommonName)
fmt.Printf("证书主题:\n\t组织: %v\n\t组织单位: %v\n\t国家: %v\n\t省份: %v\n\t城市: %v\n\t通用名称: %s\n",
cert.Subject.Organization, cert.Subject.OrganizationalUnit, cert.Subject.Country, cert.Subject.Province, cert.Subject.Locality, cert.Subject.CommonName)
fmt.Printf("有效期自: %s\n", cert.NotBefore)
fmt.Printf("有效期至: %s\n", cert.NotAfter)
fmt.Printf("序列号: %s\n", cert.SerialNumber.String())
fmt.Printf("公钥算法: %s\n", cert.PublicKeyAlgorithm.String())
fmt.Printf("签名算法: %s\n", cert.SignatureAlgorithm.String())
fmt.Printf("签名: %s\n", base64.StdEncoding.EncodeToString(cert.Signature))
fmt.Printf("版本: %d\n", cert.Version)
// 打印扩展信息
fmt.Println("扩展信息:")
for _, ext := range cert.Extensions {
fmt.Printf("\tID: %s\n\t关键扩展: %v\n\t值 (hex): %x\n", ext.Id.String(), ext.Critical, ext.Value)
}
// 打印公钥信息
switch pub := cert.PublicKey.(type) {
case *rsa.PublicKey:
fmt.Printf("RSA公钥位数: %d\n", pub.Size()*8)
fmt.Printf("RSA指数: %d\n", pub.E)
fmt.Printf("RSA模数: %x\n", pub.N)
case *ecdsa.PublicKey:
fmt.Printf("ECDSA曲线: %s\n", pub.Curve.Params().Name)
fmt.Printf("ECDSA公钥 X: %x\n", pub.X)
fmt.Printf("ECDSA公钥 Y: %x\n", pub.Y)
default:
fmt.Println("未知公钥算法")
}
// 打印证书使用
fmt.Println("扩展密钥用途:")
for _, ku := range cert.ExtKeyUsage {
fmt.Printf("\t%v\n", ku)
}
fmt.Println("基本约束:")
fmt.Printf("\t是否CA: %v\n", cert.IsCA)
fmt.Printf("\t最大路径长度: %d\n", cert.MaxPathLen)
}
三、数字证书:文件格式
证书有多种格式的原因主要与不同应用场景、系统兼容性、存储和传输需求有关。每种格式都有其特定的用途和优点,以下是一些关键因素,解释为什么需要这么多不同的证书格式:
系统兼容性
不同的操作系统和应用程序对证书格式的支持不同。例如:
- PEM 格式广泛用于
Unix/Linux
系统和开源软件,如Apache
、Nginx
和OpenSSL
。 - DER 格式通常用于
Windows
系统,因为它是二进制编码格式,更适合Windows
的文件处理方式。 - JKS 格式专用于
Java
应用程序,因为它是Java KeyStore
的标准格式。
数据类型和用途
不同的证书格式可以包含不同类型的数据,如公钥、私钥、证书链等。例如:
- PEM 和 DER 格式可以存储公钥、私钥和证书链。
- PKCS#12 格式可以存储证书、公钥和私钥,适合导出和导入完整的证书链和密钥对。
- PKCS#7 格式主要用于存储证书链,不包含私钥,适合传输多个证书。
安全性和效率
不同的编码方式和文件结构在安全性和效率上有所不同。例如:
- DER 格式是二进制编码,更紧凑,适合高效存储和传输,但不易阅读。
- PEM 格式是
Base64
编码,易于阅读和编辑,适合手动配置和调试。
标准和协议要求
不同的标准和协议对证书格式有特定要求。例如:
- SSL/TLS 协议广泛使用
PEM
和DER
格式的证书。 - S/MIME 协议用于电子邮件加密和签名,通常使用
PKCS#7
格式。 - Java 应用程序 使用
JKS
格式的密钥库来管理证书和密钥。
应用场景
不同的应用场景对证书格式有不同的需求。例如:
- Web 服务器 需要使用
PEM
或DER
格式的证书来配置SSL/TLS
。 - 电子邮件客户端 需要使用
PKCS#7
格式的证书来加密和签名电子邮件。 - SSH 客户端 需要使用
PPK
格式的私钥来进行无密码登录。
3.1、证书格式的详细信息
以下是常见证书格式的详细信息,包括扩展名、描述和特点:
文件格式 | 扩展名 | 描述 | 特点 |
---|---|---|---|
PEM (Privacy-Enhanced Mail) | .pem , .crt , .cer , .key |
基于 Base64 编码的格式,用于存储 X.509 证书、公钥、私钥和证书链 | - Base64 编码 - 以“—–BEGIN CERTIFICATE—–”和“—–END CERTIFICATE—–”包围 - 易于阅读和编辑 |
DER (Distinguished Encoding Rules) | .der , .cer |
二进制编码格式,用于存储 X.509 证书 | - 二进制编码 - 更紧凑,不易阅读 |
PKCS#7 / P7B (Public Key Cryptography Standards #7) | .p7b , .p7c |
用于描述加密和签名数据的格式,可以包含多个证书和证书链 | - Base64 编码或二进制编码 - 以“—–BEGIN PKCS7—–”和“—–END PKCS7—–”包围(Base64 编码) - 不包含私钥 |
PKCS#12 / PFX (Public Key Cryptography Standards #12) | .p12 , .pfx |
用于存储证书、公钥和私钥的格式,通常用于导出和导入证书 | - 二进制编码 - 包含证书、公钥和私钥 |
JKS (Java KeyStore) | .jks |
Java 应用程序使用的密钥库格式,用于存储证书和私钥 | - 二进制编码 - 专用于 Java 应用程序 - 包含证书和私钥 |
PPK (PuTTY Private Key) | .ppk |
PuTTY SSH 客户端使用的私钥文件格式 | - Base64 编码 - 专用于 PuTTY SSH 客户端 - 包含私钥 |
SPC (Software Publisher Certificate) | .spc |
用于代码签名的证书文件 | - 二进制编码 - 包含证书 - 常用于 Windows 系统的代码签名 |
P7M (PKCS#7 MIME Message) | .p7m |
用于存储签名和加密的电子邮件消息 | - Base64 编码或二进制编码 - 以“—–BEGIN PKCS7—–”和“—–END PKCS7—–”包围(Base64 编码) - 包含签名和加密消息 |
CSR (Certificate Signing Request) | .csr |
包含公钥和身份信息的证书签名请求文件 | - Base64 编码 - 以“—–BEGIN CERTIFICATE REQUEST—–”和“—–END CERTIFICATE REQUEST—–”包围 - 用于请求证书签名 |
CRT (Certificate) | .crt , .cer |
用于存储证书,可以是 PEM 或 DER 编码 | - Base64 编码或二进制编码 - 以“—–BEGIN CERTIFICATE—–”和“—–END CERTIFICATE—–”包围(Base64 编码) - 用于存储证书 |
KEY (Private Key) | .key |
用于存储私钥,可以是 PEM 或 DER 编码 | - Base64 编码或二进制编码 - 以“—–BEGIN PRIVATE KEY—–”和“—–END PRIVATE KEY—–”包围(Base64 编码) - 用于存储私钥 |
3.2、格式转换
// 将 DER 格式的证书转换为 PEM 格式:
openssl x509 -inform der -in certificate.der -out certificate.pem
// 将 PEM 格式的证书转换为 DER 格式:
openssl x509 -outform der -in certificate.pem -out certificate.der
// PKCS#12 (PFX) to PEM
openssl pkcs12 -in certificate.pfx -out certificate.pem -nodes
// PEM to PKCS#12 (PFX)
openssl pkcs12 -export -out certificate.pfx -inkey privatekey.pem -in certificate.pem -certfile ca-chain.pem
// 将 CSR (证书签名请求) 从 PEM 转换为 DER
openssl req -outform der -in request.csr -out request.der
// 将 DER 转换为 PEM
openssl req -inform der -in request.der -out request.csr -outform pem
// 将私钥从 PEM 转换为 DER
openssl rsa -in privatekey.pem -outform der -out privatekey.der
// 从 PEM 格式的证书和私钥中生成新的 PEM 格式文件
cat certificate.pem privatekey.pem > combined.pem
// 将 RSA 私钥转换为 PKCS#8 格式
openssl pkcs8 -topk8 -inform PEM -outform PEM -in privatekey.pem -out privatekey-pkcs8.pem -nocrypt
四、数字证书:常用分类
数字证书有多种类别,每种类别都有其特定的用途和应用场景:
证书类别 | 应用场景 | 子类别 | 主要用途和区别 |
---|---|---|---|
SSL/TLS 证书 | 网站安全、电子商务、在线服务 | - 域名验证(DV)证书 - 组织验证(OV)证书 - 扩展验证(EV)证书 |
- DV:仅验证域名所有权,颁发速度快 - OV:验证域名和组织身份 - EV:严格验证,包括法律地位,浏览器地址栏显示绿色 |
代码签名证书 | 软件发布、驱动程序签名 | - 标准代码签名证书 - 驱动程序签名证书 |
- 标准代码签名:用于常规软件 - 驱动程序签名:用于 Windows 驱动程序 |
客户端证书 | 企业内部网络、VPN、安全电子邮件 | - 个人证书 - 设备证书 |
- 个人证书:验证个人用户身份 - 设备证书:验证设备身份 |
S/MIME 证书 | 电子邮件通信、企业通信 | - 个人 S/MIME 证书 - 企业 S/MIME 证书 |
- 个人 S/MIME:用于个人电子邮件 - 企业 S/MIME:用于企业电子邮件 |
根证书和中间证书 | 构建证书链、证书颁发 | - 根证书 - 中间证书 |
- 根证书:顶端证书,用于签发中间证书 - 中间证书:用于签发终端证书,构建信任链 |
自签名证书 | 测试环境、内部应用 | - 测试证书 - 内部应用证书 |
- 测试证书:用于开发和测试 - 内部应用证书:用于内部网络和应用 |
文档签名证书 | 合同签署、报告签署 | - PDF 签名证书 - Microsoft Office 签名证书 |
- PDF 签名:用于签署 PDF 文档 - Office 签名:用于签署 Office 文档 |
时间戳证书 | 法律文件、软件发布 | - 标准时间戳证书 - 合规时间戳证书 |
- 标准时间戳:用于一般时间戳需求 - 合规时间戳:符合法律和行业标准 |
4.1、SSL/TLS 证书分类
域名验证(DV)证书:域名验证(
DV
)证书是最基本的SSL/TLS
证书类型。它们仅验证申请者对域名的所有权,不涉及组织身份的验证。DV
证书一般用于个人网站/测试使用,DV
证书签发速度快、无需人工审核,确保域名验证信息正确的情况下1-15
分钟就能签发。DV
证书无法为特殊域名/公网IP签发证书(例如:edu
、.gov
、.org
、.jp
(国家缩写)等后缀的域名)。DV
证书无法将多个域名合并到一张证书内。- 验证级别:低
- 颁发速度:快,通常几分钟到几小时
- 适用场景:个人网站、小型企业网站
- 成本:通常较低
组织验证(OV)证书:组织验证(
OV
)证书不仅验证域名的所有权,还验证申请者的组织身份。CA
会对申请者的组织信息进行审核。OV
证书是企业SSL
证书的首选,通过企业认证确保代表企业SSL
证书的真实性,拒绝网站风险。OV
证书支持特殊域名的签发,例如gov
、edu
、.gov
、.org
、.jp
(国家缩写)等。OV
证书支持证书合并,多张证书(域名)合并签发。- 验证级别:中
- 颁发速度:中等,通常几天
- 适用场景:中型企业网站、组织网站
- 成本:中等
扩展验证(EV)证书:扩展验证(
EV
)证书是最高级别的SSL/TLS
证书。它们进行严格的验证,包括域名所有权、组织身份和法律地位。浏览器地址栏会显示绿色,并显示公司名称。- 验证级别:高
- 颁发速度:慢,通常几天到几周
- 适用场景:大型企业网站、金融机构、电子商务网站
- 成本:较高
通配符(Wildcard)证书:通配符(
Wildcard
)证书可以保护一个域名及其所有子域名。它们通常用于需要保护多个子域名的网站。- 验证级别:根据是
DV
还是OV/EV
证书而定 - 颁发速度:根据是
DV
还是OV/EV
证书而定 - 适用场景:需要保护多个子域名的网站
- 成本:通常较高
- 验证级别:根据是
多域名(SAN/UCC)证书,多域名证书(也称为
SAN
或UCC
证书)可以保护多个不同的域名。这种证书通常用于需要保护多个域名的网站或服务。- 验证级别:根据是
DV
还是OV/EV
证书而定 - 颁发速度:根据是
DV
还是OV/EV
证书而定 - 适用场景:需要保护多个域名的网站或服务
- 成本:通常较高
- 验证级别:根据是
自签名证书:自签名证书是由组织或个人自己生成和签发的
SSL/TLS
证书,不依赖于外部证书颁发机构(CA)
。它们通常用于内部测试和开发环境。- 验证级别:无外部验证
- 颁发速度:即时
- 适用场景:测试环境、内部应用
- 成本:免费,但不被外部信任
证书类别 | 描述 | 验证级别 | 颁发速度 | 适用场景 | 成本 |
---|---|---|---|---|---|
域名验证(DV)证书 | 仅验证域名所有权,不涉及组织身份验证 | 低 | 快 | 个人网站、小型企业网站 | 低 |
组织验证(OV)证书 | 验证域名所有权和组织身份 | 中 | 中等 | 中型企业网站、组织网站 | 中等 |
扩展验证(EV)证书 | 严格验证域名所有权、组织身份和法律地位,浏览器地址栏显示绿色 | 高 | 慢 | 大型企业网站、金融机构、电子商务网站 | 高 |
通配符(Wildcard)证书 | 保护一个域名及其所有子域名 | 根据验证级别而定 | 根据验证级别而定 | 需要保护多个子域名的网站 | 较高 |
多域名(SAN/UCC)证书 | 保护多个不同的域名 | 根据验证级别而定 | 根据验证级别而定 | 需要保护多个域名的网站或服务 | 较高 |
自签名证书 | 由组织或个人自己生成和签发,不依赖外部 CA | 无外部验证 | 即时 | 测试环境、内部应用 | 免费,但不被外部信任 |
4.2、如何区分 DV、OV、EV
域名验证(DV
)证书:仅验证域名所有权,通常在“主题”字段中只包含域名信息,不包含公司或组织信息。
组织验证(OV
)证书:验证域名所有权和组织身份,在“主题”字段中包含公司或组织信息。
组织验证(EV
)证书:进行严格的验证,包括域名所有权、组织身份和法律地位。在“主题”字段中包含详细的公司或组织信息。
4.3、SSL/TLS 证书域名
在SSL/TLS
证书中,域名信息存储在证书的特定字段中,这些字段包括Common Name (CN)
和Subject Alternative Name (SAN)
。域名信息在证书颁发时由证书颁发机构(CA)
进行验证,并在客户端(如浏览器)访问网站时进行校验。
4.3.1、域名信息存储位置
Common Name (CN)
- 描述:
Common Name
字段通常包含主域名,例如baidu.com
。 - 使用情况:早期的
SSL/TLS
证书主要使用CN
字段存储域名信息,但现代证书更倾向于使用SAN
字段。
- 描述:
Subject Alternative Name (SAN)
- 描述:
Subject Alternative Name
字段可以包含多个域名和子域名,是现代SSL/TLS
证书中存储域名信息的主要位置。 - 使用情况:
SAN
字段允许一个证书保护多个域名和子域名,例如baidu.com
、www.baidu.cn
。
- 描述:
以下是一个包含域名信息的SSL/TLS
证书示例:
➜ Desktop openssl x509 -in baidu.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
4e:40:03:a6:5e:b6:81:f8:7f:4b:d8:eb
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=BE, O=GlobalSign nv-sa, CN=GlobalSign RSA OV SSL CA 2018
Validity
Not Before: Jul 8 01:41:02 2024 GMT
Not After : Aug 9 01:41:01 2025 GMT
Subject: C=CN, ST=beijing, L=beijing, O=Beijing Baidu Netcom Science Technology Co., Ltd, CN=baidu.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
....
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Basic Constraints: critical
CA:FALSE
Authority Information Access:
CA Issuers - URI:http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt
OCSP - URI:http://ocsp.globalsign.com/gsrsaovsslca2018
X509v3 Certificate Policies:
Policy: 1.3.6.1.4.1.4146.1.20
CPS: https://www.globalsign.com/repository/
Policy: 2.23.140.1.2.2
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.globalsign.com/gsrsaovsslca2018.crl
X509v3 Subject Alternative Name:
DNS:baidu.com, DNS:baifubao.com, DNS:www.baidu.cn, DNS:www.baidu.com.cn, DNS:mct.y.nuomi.com, DNS:apollo.auto, DNS:dwz.cn, DNS:*.baidu.com, DNS:*.baifubao.com, DNS:*.baidustatic.com, DNS:*.bdstatic.com, DNS:*.bdimg.com, DNS:*.hao123.com, DNS:*.nuomi.com, DNS:*.chuanke.com, DNS:*.trustgo.com, DNS:*.bce.baidu.com, DNS:*.eyun.baidu.com, DNS:*.map.baidu.com, DNS:*.mbd.baidu.com, DNS:*.fanyi.baidu.com, DNS:*.baidubce.com, DNS:*.mipcdn.com, DNS:*.news.baidu.com, DNS:*.baidupcs.com, DNS:*.aipage.com, DNS:*.aipage.cn, DNS:*.bcehost.com, DNS:*.safe.baidu.com, DNS:*.im.baidu.com, DNS:*.baiducontent.com, DNS:*.dlnel.com, DNS:*.dlnel.org, DNS:*.dueros.baidu.com, DNS:*.su.baidu.com, DNS:*.91.com, DNS:*.hao123.baidu.com, DNS:*.apollo.auto, DNS:*.xueshu.baidu.com, DNS:*.bj.baidubce.com, DNS:*.gz.baidubce.com, DNS:*.smartapps.cn, DNS:*.bdtjrcv.com, DNS:*.hao222.com, DNS:*.haokan.com, DNS:*.pae.baidu.com, DNS:*.vd.bdstatic.com, DNS:*.cloud.baidu.com, DNS:click.hm.baidu.com, DNS:log.hm.baidu.com, DNS:cm.pos.baidu.com, DNS:wn.pos.baidu.com, DNS:update.pan.baidu.com
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Authority Key Identifier:
F8:EF:7F:F2:CD:78:67:A8:DE:6F:8F:24:8D:88:F1:87:03:02:B3:EB
X509v3 Subject Key Identifier:
AD:CA:00:54:CA:D8:E5:94:B6:8F:83:DA:27:80:28:4E:59:24:3B:18
CT Precertificate SCTs:
....
4.3.2、域名信息的校验时机
证书颁发时:证书颁发机构(
CA
)在颁发SSL/TLS
证书之前会进行域名验证,以确保申请者对域名的所有权。验证方法包括:- DNS 验证:
CA
要求申请者在域名的DNS
记录中添加特定的TXT
记录,以证明对域名的控制权。 - 文件验证:
CA
要求申请者在域名对应的网站根目录中上传一个特定文件,以证明对域名的控制权。 - 电子邮件验证:
CA
向域名注册信息中的电子邮件地址发送验证邮件,申请者需要点击邮件中的验证链接。
- DNS 验证:
客户端访问时:当客户端(如浏览器)访问一个使用
SSL/TLS
的网站时,会进行以下校验:- 证书链验证:客户端验证证书链的完整性,确保证书是由受信任的
CA
颁发的。 - 域名匹配验证:客户端检查证书中的域名信息(
CN
和SAN
字段)是否与用户访问的域名匹配。如果不匹配,浏览器会显示安全警告。
- 证书链验证:客户端验证证书链的完整性,确保证书是由受信任的
五、证书签发和验签
5.1、证书签发
5.2、证书链
5.2.1、什么是证书链?
证书链(Certificate Chain
),也称为证书路径,是指一系列相互信任的证书组成的链条,从最终用户的证书(也称为终端证书或叶证书)开始,经过一个或多个中间证书,最终到达根证书(Root Certificate
)。每个证书都由上一级证书颁发机构(CA
)签名,形成一条信任链。
证书链的组成部分:
终端证书(End-Entity Certificate):
- 这是实际用于服务器或客户端的证书,例如网站的
SSL/TLS
证书。 - 由中间证书或根证书签发。
- 这是实际用于服务器或客户端的证书,例如网站的
中间证书(Intermediate Certificate):
- 由根证书或另一个中间证书签发,用于签发终端证书。
- 中间证书可以有多个层级,形成中间证书链。
根证书(Root Certificate):
- 位于证书链的顶端,由受信任的根证书颁发机构(
CA
)签发。 - 根证书是自签名的,并且预先安装在操作系统和浏览器中,作为信任的根源。
- 位于证书链的顶端,由受信任的根证书颁发机构(
5.2.2、证书链的作用
建立信任关系:证书链通过逐级验证,从终端证书到根证书,建立起一个信任关系。客户端(如浏览器)通过验证整个证书链,确保终端证书是由受信任的
CA
签发的。简化证书管理:使用中间证书可以简化证书管理和部署。根证书通常长期有效,而中间证书和终端证书可以更频繁地更新,以提高安全性。
增强安全性:证书链通过多级验证机制,增加了攻击者伪造证书的难度。即使某个中间证书被泄露,也可以通过吊销该证书来保护整个信任链。
便于证书撤销:如果某个中间证书或终端证书被发现存在安全问题,可以通过证书撤销列表(
CRL
)或在线证书状态协议(OCSP
)吊销该证书,确保整个信任链的安全性。
5.2.3、证书链的验证过程
用户访问网站:用户在浏览器中输入网址并访问网站,服务器返回 SSL/TLS 证书和中间证书。
浏览器接收证书链:浏览器接收终端证书和中间证书,并开始验证证书链。
验证证书链:浏览器从终端证书开始,逐级验证每个证书的签名,直到到达根证书。浏览器检查每个证书的有效期、签名和吊销状态。
根证书验证:浏览器检查根证书是否在其预先安装的受信任根证书列表中。如果是,则信任该证书链。
建立安全连接:如果证书链验证通过,浏览器与服务器之间建立安全的
SSL/TLS
连接。
以下是一个典型的证书链示例:
Root Certificate (Root CA)
|
v
Intermediate Certificate (Intermediate CA)
|
v
End-Entity Certificate (www.example.com)
5.3、 交叉证书
交叉证书(Cross-Certificate
)是一种数字证书,它用于建立两个不同证书颁发机构(CA
)之间的信任关系。通常在涉及多个信任域或CA
之间的互操作性时会用到交叉证书。交叉证书使两个不同的PKI
(Public Key Infrastructure
)体系能够互相信任彼此的证书,从而扩展信任链的范围。
交叉证书的应用场景:
- 跨组织信任: 当两个不同的组织或企业希望互相验证对方的用户或设备时,可能会使用交叉证书来建立相互信任的关系。
- 过渡期间的信任延续: 当组织从一个
CA
迁移到另一个CA
时,可以使用交叉证书确保新旧CA
之间的互操作性和信任过渡。 - 多路径验证: 某些大型组织可能会同时依赖多个
CA
进行证书签发,交叉证书可以使不同的CA
信任链互相验证,确保系统兼容性。
交叉证书的工作原理:
准备证书和密钥:
- 确保你有两个
CA
:CA1
和CA2
。 CA1
的私钥和公钥证书。CA2
的私钥和公钥证书。
- 确保你有两个
生成证书签名请求(CSR):
- 使用
CA2
的私钥生成一个证书签名请求(CSR
)。CSR
包含CA2
的公钥和一些身份信息。
- 使用
使用 CA1 签名 CA2 的 CSR:
- 使用
CA1
的私钥对CA2
的CSR
进行签名。这一步骤会生成一个新的证书,该证书由CA1
签发,并包含CA2
的公钥。
- 使用
生成交叉证书:
- 生成的证书即为交叉证书,它表明
CA1
信任CA2
,并将CA2
的公钥包含在其中。
- 生成的证书即为交叉证书,它表明
5.4、证书验证测试
我们用Chrome
浏览器打开baidu.com
,然后如下图:
我们可以分别导出中间证书(GlobalSignRSAOVSSLCA2018.pem
)和网站证书(baidu.com.pem
),同时可以看到根证书(GlobalSign
)的序列号是04:00:00:00:00:01:21:58:53:08:A2
。
打开Mac
系统的KeyChain Access
,找到根证书(GlobalSign.pem
)导出用于代码测试证书:
证书校验验证代码如下:
func main() {
rootCertPath := "./GlobalSign4.pem"
middleCertPath := "./GlobalSignRSAOVSSLCA2018.pem"
certPath := "./baidu.com.pem"
err := verifyCertificate(certPath, middleCertPath, rootCertPath)
if err != nil {
log.Fatalf("Certificate verification failed: %v", err)
}
fmt.Println("Certificate verification succeeded.")
}
func verifyCertificate(certPath, middleCertPath, rootCertPath string) error {
roots, err := loadRootCert(rootCertPath)
if err != nil {
return err
}
intermediates, err := loadRootCert(middleCertPath)
if err != nil {
return err
}
cert, err := loadCertificate(certPath)
if err != nil {
return err
}
opts := x509.VerifyOptions{
Roots: roots, // 根证书
Intermediates: intermediates, // 中间证书
}
chain1, err := cert.Verify(opts)
println(chain1)
return err
}
func loadRootCert(path string) (*x509.CertPool, error) {
rootPEM, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read root CA file: %v", err)
}
roots := x509.NewCertPool()
if !roots.AppendCertsFromPEM(rootPEM) {
return nil, fmt.Errorf("failed to add root CA to pool")
}
return roots, nil
}
func loadCertificate(path string) (*x509.Certificate, error) {
certPEM, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read certificate file: %v", err)
}
block, _ := pem.Decode(certPEM)
if block == nil || block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("failed to decode PEM block containing certificate")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %v", err)
}
return cert, nil
}
六、如何申请数字证书
阿里云证书申请:
acme.sh 免费证书申请:
export Ali_Key="abcd"
export Ali_Secret="xxxxxxxxxx"
# RSA 证书
acme.sh --issue --dns dns_ali -d fanlv.fun -d fanlv.fun -d "*.fanlv.fun" --debug
# 更新证书
$HOME/.acme.sh/acme.sh --renew -d fanlv.fun --force
# 安装证书
$HOME/.acme.sh/acme.sh --install-cert -d fanlv.fun -d "*.fanlv.fun" \
--cert-file $GOPATH/src/xx/cert.pem \
--key-file $GOPATH/src/xx/key.pem