数字证书原理与实践
数字证书原理与实践
一、数字证书介绍
数字证书是保障互联网通信安全与信任的基石,它如同网络世界的“身份证”。
1.1 核心信任链
根证书 → 中间 CA 证书 → 业务证书(二级域名 / 泛域名 / 多域名)。
当浏览器验证一个网站的证书时,会沿 业务证书 → 中间证书 → 根证 的路径逐级验证签名,只要根证书是可信的,且链条完整,浏览器就会认为该网站是安全的。
1.2 根证书(根 CA 证书)
- 作用:作为整个信任体系的最终信任锚点、 HTTPS 的信任锚点。
- 特点:自己给自己发证,没人比它更高。
- 有效期:极长:10~20 年。
- 安装位置:预先安装在操作系统和浏览器中。
- 权限:可以签发中间 CA证书、下级根。
- 私钥绝对离线:常年锁在机房保险柜,绝不直接给网站发证。
- 示例:当在浏览器中访问
https://www.example.com时,浏览器会检查该网站的证书。验证的最终一步,就是确认签发该证书的机构是否能追溯到浏览器内置的一个受信任的根证书(例如DigiCert Global Root G2)。如果能成功追溯,浏览器就会显示“安全”的锁形图标。
1.3 中间证书
-
是什么:中间证书是由根证书签发的,它扮演着“代理人”的角色。
-
特点:
- 由根证书签发,不是自签。
- 不预装在浏览器,网站部署时要一起配上去。
- 权限:可以签发网站证书、下级中间 CA。
- 给谁签发:给所有域名、服务器、设备签发 HTTPS 证书。
- 有效期:3~5 年,比根短、比网站证书长。
- 作用:
- 保护根证书:即使中间证书的私钥不慎泄露,也只需吊销该中间证书,而不会危及整个根证书体系的信任,影响范围有限。
- 提高签发效率:根证书离线保存,而中间证书在线处理海量的证书签发请求,实现了安全与效率的平衡。
1.4 业务证书
业务 SSL 证书根据其保护的域名范围和方式,主要分为以下几种类型:
1.4.1 单域名证书
-
也可以叫
二级域名证书,是给单个固定二级域名用的终端业务证书。 -
一张证书仅能保护一个完整的域名(例如
example.com或www.example.com),不支持任何其他子域名。 -
特点:
- 由中间 CA签发。
- 只能绑定 1 个域名。
- 只能给对应网站做 HTTPS,不能再签发任何子证书。
- 有效期:现在主流 1 年。
- 可以免费申请(Let’s Encrypt)。
-
适合场景:适合只有一个官方网站或博客的场景。
1.4.2 多域名证书
- 也称为
SAN 证书或 UCC 证书。 - 一张证书可以同时保护多个完全不同的域名。例如,一张证书可以同时保护
abc.com、kfc.cn和ccc.net。 - 适合场景:非常适合拥有多个独立品牌、不同业务线或跨区域网站的企业集团。
- 由中间CA签发。
1.4.3 泛域名证书
-
泛域名证书通过使用通配符
*来保护一个主域名下的所有同级(二级)子域名- 例如,一张
*.abc.com的证书,可以保护www.abc.com、shop.abc.com、api.abc.com等任意数量的二级子域名。
- 例如,一张
-
主要优势是无限扩展和管理便捷,新增子域名时无需重新申请或部署证书。
-
但需注意,它通常只能保护一层子域名,无法覆盖
a.b.abc.com这样的三级域名。 -
特点:
- 中间 CA 签发的终端证书。
- 适合子域名多、业务系统多的企业。
- 免费证书也能申请泛域名。
- 风险:只要证书泄露,所有子域名都有风险。
1.4.4 自签名证书
-
一个使用 OpenSSL 自己给自己签发的证书,没有权威的根、中间 CA参与。
-
特点:
- 没有权威 CA 背书。
- 浏览器、系统默认不信任,访问必报警告。
- iBMC、路由器、内网设备默认都是自签名证书。
- 只能内网测试、设备管理用,不能公网正式建站。
-
解决办法:把自签根证书导入电脑「受信任根证书」,就不告警了。
二、模拟证书签发流程
使用 OpenSSL 工具生成各种证书,模拟 根 CA→中间 CA→网站域名证书 完整三级签发链条,以此熟悉根证书、中间证书、业务证书的上下级关系。
注:颁发期限时,根证书 > 中间证书 > 实体证书。
2.1 创建存放目录
mkdir -p /usr/local/CAcd /usr/local/CA2.2 自建根证书
创建本地根证书,模拟官方全球根 CA。
作用:整个信任链的最高源头,自签名、离线保存,只用来签发下级中间证书。
2.2.1 创建根证书配置文件
cat > rootca.cnf << 'EOF'[ req ]distinguished_name = req_distinguished_namex509_extensions = v3_reqprompt = no
[ req_distinguished_name ]C = CNST = BeijingL = BeijingO = My OrganizationOU = Root CACN = My Root CA
[ v3_req ]keyUsage = critical, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSignextendedKeyUsage = serverAuth, clientAuthbasicConstraints = critical, CA:TRUEsubjectKeyIdentifier = hashEOF
[ req_distinguished_name ]配置参数说明:
C:国家;O:组织机构;OU:单位部门;CN:通用名,有时候是一个域名,如xxx.com;L:地区;ST:省市;STREET:街道;POSTALCODE:邮编;SERIALNUMBER:序列号。
[ v3_ca ]配置参数说明:
subjectAltName:证书使用者可选名称;nsCaRevocationUrl:Netscape证书颁发机构吊销 URL;nsBaseUrl:Netscape 证书基URLL;nsRevocationUrl:Netscape 证书吊销 URLL;nsRenewalUrl:Netscape 证书续订 URLL;nsCaPolicyUrl: Netscape 证书颁发机构策略 URLL;nsSslServerName:Netscape 证书 SSL 服务器名称L。
2.2.2 生成私钥和请求文件
使用 rootca.cnf 根证书配置文件,生成 rootca.csr 请求文件,同时生成 rootca.key 根私钥文件:
openssl req -config rootca.cnf -new -newkey rsa:4096 -keyout rootca.key -out rootca.csr -nodes2.2.3 生成根证书
使用根证书的配置文件、私钥、请求文件,生成 rootca.crt 根证书,期限为 10 年:
openssl x509 -req -extfile rootca.cnf -extensions v3_req -days 3650 -sha256 -signkey rootca.key -in rootca.csr -out rootca.crt2.2.4 查看根证书信息
openssl x509 -in rootca.crt -noout -text2.3 自建中间证书
作用:根证书授权签发的二级机构,日常专门用来签发网站业务证书,真实环境不会用根证书直接给网站发证。
2.3.1 创建中间证书配置文件
cat > midca.cnf << 'EOF'[ req ]distinguished_name = req_distinguished_namex509_extensions = v3_reqprompt = no
[ req_distinguished_name ]C = CNST = BeijingL = BeijingO = My OrganizationOU = Intermediate CACN = My Intermediate CA
[ v3_req ]keyUsage = critical, keyCertSign, cRLSignbasicConstraints = critical, CA:TRUE, pathlen:0subjectKeyIdentifier = hashauthorityKeyIdentifier = keyidEOF2.3.2 生成私钥和请求文件
使用 midca.cnf 中间证书配置文件,生成 midca.csr 请求文件,同时生成 midca.key 私钥文件:
openssl req -config midca.cnf -new -newkey rsa:4096 -keyout midca.key -out midca.csr -nodes2.3.3 生成中间证书
使用中间证书的配置文件、私钥、请求文件,以及根证书和私钥文件,一起生成 midca.crt 中间证书,期限为 5 年:
openssl x509 -req -extfile midca.cnf -extensions v3_req -days 1825 -sha256 -CA rootca.crt -CAkey rootca.key -CAcreateserial -CAserial serial -in midca.csr -out midca.crt2.3.4 验证中间证书
使用 rootca.crt 根证书,来验证 midca.crt 中间证书是否正确,显示 ok ,则表示证书没有问题:
openssl verify -CAfile rootca.crt midca.crt2.3.5 查看中间证书信息
openssl x509 -in midca.crt -noout -text2.4 签发业务证书
2.4.1 创建业务证书配置文件
cat > server.cnf << 'EOF'[ req ]distinguished_name = req_distinguished_namex509_extensions = v3_reqprompt = no
[ req_distinguished_name ]C = CNST = BeijingL = BeijingO = My OrganizationOU = server caCN = my server ca
[ v3_req ]keyUsage = critical, digitalSignature, keyEncipherment, dataEncipherment, keyAgreementextendedKeyUsage = serverAuth, clientAuthsubjectKeyIdentifier = hashauthorityKeyIdentifier = keyidbasicConstraints = critical, CA:FALSEsubjectAltName = @alternate_names
[ alternate_names ]DNS.1 = localhostDNS.2 = test.cnIP.1 = 127.0.0.1IP.2 = 10.22.51.76EOF注:
[ alternate_names ]块中的DNS和IP分别用来指定哪些 域名 和 IP 可以使用此证书,为此可以分出多种证书类型。
- 单域名 / IP 证书:
Terminal window # 单域名证书[ alternate_names ]DNS.1 = www.test.cn# 单 IP 证书[ alternate_names ]IP.1 = 10.22.51.76
- 多域名 / IP 证书:
Terminal window [ alternate_names ]DNS.1 = hututu.netDNS.2 = jenkins.loveDNS.3 = test.xyz.comIP.1 = 10.2.51.44IP.2 = 10.22.51.76IP.3 = 10.33.21.54
- 泛域名证书:
Terminal window [alt_names]DNS.1 = *.abc.comDNS.2 = *.hututu.net
2.4.2 生成私钥和请求文件
使用 server.cnf 业务证书配置文件,生成 server.csr 请求文件,同时生成 server.key 私钥文件:
openssl req -config server.cnf -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes2.4.3 生成业务证书
使用业务证书的配置文件、私钥、请求文件,以及中间证书和私钥文件,一起生成 midca.crt 根证书,期限为 1 年:
openssl x509 -req -extfile server.cnf -extensions v3_req -days 365 -sha256 -CA midca.crt -CAkey midca.key -CAcreateserial -in server.csr -out server.crt2.4.4 查看业务证书信息
openssl x509 -in server.crt -noout -text2.4.5 验证业务证书
使用 2.5.1 生成的 mid-root-ca_chain.crt 复合证书,来验证 server.crt 业务证书是否正确,显示 ok ,则表示证书没有问题:
openssl verify -CAfile mid-root-ca_chain.crt server.crt2.4.6 验证完整证书链
使用根证书、中间证书、业务证书,验证完整的证书链,显示ok,则表示从域名证书 → 中间证书 → 根证书的完整信任链验证通过:
openssl verify -CAfile rootca.crt -untrusted midca.crt server.crt2.5 生成复合证书
将生成的证书合并,生成复合证书。
拼接顺序:上游证书放后面,下游放前面。
2.5.1 生成 CA 链证书
CA 链证书 也就是中间证书与根证书合并生成的一个复合证书,中间CA证书在前:
cat midca.crt rootca.crt > mid-root-ca_chain.crt适用场景:
- 电脑 / 服务器 / 设备 导入私有信任库。
- 内网自建 CA,让整机信任所有由这个中间 CA 签发的业务证书。
- 签发证书时,作为 OpenSSL 的可信 CA 池。
2.5.2 生成全链证书
全链证书 也就是业务证书与中间证书合并生成的一个复合证书,业务证书在前:
cat server.crt midca.crt > server-mid_chain.crt适用场景:公网网站、普通内网 HTTPS、Nginx / 反向代理、常规服务器。
2.5.3 生成含根全链证书
含根全链证书 也就是业务证书与中间证书与根证书三个证书合并生成,也叫完整证书链、全包证书链:
cat server.crt midca.crt rootca.crt > server-mid-root_chain.crt适用场景:
-
嵌入式老旧设备 / BMC / 工控机 / 打印机:
设备自身没有内置可信根证书库,不认公共根,必须整条链全给它。
-
完全内网隔离环境,自建私有 CA:
员工电脑没导入私有根,又不想每台机器手动装根证书,只能服务端下发含根全链,让客户端直接整条链校验通过。
三、验证测试
3.1 前言
整体流程分为三步:
- 将证书部署到 Nginx
- 客户端导入根证书
- 浏览器访问验证
将 rootca.crt 根证书导入电脑受信任的根证书库后,再访问 Nginx 搭载的全链证书 server-mid_chain.crt 站点,浏览器即显示安全锁,不会弹出告警。
3.2 客户端导入
3.2.1 浏览器导入
以谷歌浏览器为例,访问 chrome://certificate-manager/(或者打开【设置】——【隐私与安全】——【安全】——【管理证书】)进入证书管理器,点击左侧【您的证书】——【管理从 Windows 导入的证书】:

打开【证书】窗口,点击【导入】,在【证书导入向导】中,选择下载好的 rootca.crt 根证书:

在下一步【证书存储】中,将其放到 受信任的根证书颁发机构 中,完成导入:

弹出窗口,选择【是】,安装证书:

安装完成后,进入【受信任的根证书颁发机构】栏,可查看到导入后的证书:

3.2.2 本地计算机导入
双击 rootca.crt 根证书,点击【安装证书】,选择【证书存储】为 受信任的根证书颁发机构 :

安装导入后,打开【运行】窗口,输入 mmc 进入【控制台根节点】,点击【文件】——【添加/删除管理单元】中的【证书】,双击打开【受信任的根证书颁发机构】中的【证书】,可看到自己已导入好的证书,双击可查看相应的信息内容:

3.3 配置 Nginx 证书部署
将生成的
server-mid_chain.crt全链证书与业务证书的server.key私钥文件部署到 Nginx,配置 HTTPS 服务供客户端访问。
3.3.1 部署证书文件
# 创建证书存放目录mkdir -p /usr/local/nginx/conf/certs
# 复制私钥与全链证书cp /usr/local/CA/server.key /usr/local/CA/server-mid_chain.crt /usr/local/nginx/conf/certs
# 重命名全链证书mv /usr/local/nginx/conf/certs/server-mid_chain.crt /usr/local/nginx/conf/certs/server.crt
# 设置私钥权限(必须为 600)chmod 600 /usr/local/nginx/conf/certs/server.key3.3.2 创建站点配置文件
在 /usr/local/nginx/conf/conf.d 目录下,创建名为 ssl-test.conf 站点配置文件,用于测试 HTTPS 访问,添加以下内容:
cat > /usr/local/nginx/conf/conf.d/ssl-test.conf << 'EOF'server { listen 80; server_name test.cn localhost; return 301 https://$host$request_uri;}
server { # listen 443 ssl http2; # Nginx 1.25 以下版本写法 listen 443 ssl; http2 on; server_name test.cn localhost;
ssl_certificate /usr/local/nginx/conf/certs/server.crt; ssl_certificate_key /usr/local/nginx/conf/certs/server.key;
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;
location / { root html; index ssl-test.html; }}EOF关键参数说明:
ssl_certificate:指向全链证书,包含业务证书 + 中间证书。ssl_certificate_key:指向业务证书的私钥。ssl_protocols:仅启用 TLSv1.2 / TLSv1.3,禁用老旧协议。return 301:HTTP 自动跳转 HTTPS。
3.3.3 创建静态文件
在 /usr/local/nginx/html 目录下,创建名为 ssl-test.html 的静态文件,添加以下内容:
cat > /usr/local/nginx/html/ssl-test.html <<'EOF'<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HTTPS 测试页面</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background-color: #f0f2f5; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } .card { background: white; padding: 40px; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); text-align: center; max-width: 400px; } h1 { color: #2c3e50; margin-bottom: 10px; } p { color: #7f8c8d; font-size: 16px; } .status { display: inline-block; margin-top: 20px; padding: 8px 16px; background-color: #e8f5e9; color: #2e7d32; border-radius: 20px; font-weight: bold; border: 1px solid #2e7d32; } .icon { font-size: 48px; margin-bottom: 20px; } </style></head><body>
<div class="card"> <div class="icon">🔒</div> <h1>HTTPS 部署成功!</h1> <p>当前连接是安全的。</p> <p>服务器时间: <span id="time"></span></p> <div class="status">SSL 证书工作正常</div> </div>
<script> // 简单的脚本显示当前时间,证明页面是动态加载的 document.getElementById('time').innerText = new Date().toLocaleString(); </script>
</body></html>EOF3.3.4 重载 Nginx 配置
nginx -tnginx -s reload3.4 浏览器安全验证
客户端导入根证书后,通过浏览器访问 Nginx 搭载的 HTTPS 站点,验证证书链完整性与浏览器安全提示是否正常。
3.4.1 修改本地 hosts 解析
以管理员身份编辑 C:\Windows\System32\drivers\etc\hosts 文件,添加以下内容:
10.22.51.76 test.cn3.4.2 浏览器访问验证
打开浏览器访问 https://test.cn ,点击地址栏旁边的锁图标按钮,可以看到显示 连接是安全的 :

点击进入【证书有效】,可以查看证书详细信息,切换到【详细信息】标签页,可看到三层证书:My Root CA → My Intermediate CA → my server ca ,逐层点击可查看每级证书的详细信息(签发者、有效期、指纹等):

若证书链完整且根证书已导入受信任库,浏览器不会弹出安全告警,页面正常加载,即证明整套自建 CA 证书体系可正常用于内网 HTTPS 环境。
常见问题排查:
现象 原因 解决 浏览器报 NET::ERR_CERT_AUTHORITY_INVALID根证书未导入受信任库 重新导入 rootca.crt到「受信任的根证书颁发机构」报 NET::ERR_CERT_COMMON_NAME_INVALID访问域名不在证书 SAN 列表中 检查 server.cnf的[alternate_names]是否包含该域名报 NET::ERR_CERT_DATE_INVALID证书已过期 重新签发业务证书 报 SSL_ERROR_BAD_CERT_DOMAIN(Firefox)域名与证书不匹配 确认 hosts 中 IP 与证书 SAN 中的 IP/域名一致
3.5 证书链验证原理
- 为什么只导入根证书而不导入中间证书,浏览器也认?
TLS 握手时,Nginx 通过 ssl_certificate 将 全链证书 server-mid_chain.crt(业务证书 + 中间证书)完整发送给浏览器。浏览器拿到后,只需用本地已信任的根证书校验链条顶端签名即可:
服务端在 TLS 握手时发送: server.crt + midca.crt客户端本地持有: rootca.crt(已导入受信任库) ↓ rootca 签名验证 midca → midca 签名验证 server → ✅ 信任链完整因此 中间证书无需客户端单独导入——它由服务端在握手阶段自动下发补全。客户端只需拥有根证书这一个信任锚点。
- 为什么双击
server.crt提示「无法找到该证书的颁发者」?
server.crt 是 单独的业务证书,内部不包含 midca.crt。双击打开时,系统依次在以下位置查找其签发者:
| 查找位置 | 是否有 midca.crt | 说明 |
|---|---|---|
当前 .crt 文件内部 | ❌ 不包含 | server.crt 只有自身信息 |
| Windows 证书存储(中间证书颁发机构) | ❌ 未导入 | 只导入了根证书 |
| 操作系统内置公共 CA 库 | ❌ 不认自建 CA | 自建 CA 不在公共信任列表中 |
三个位置都找不到签发者,系统自然提示”无法找到该证书的颁发者”,这属于正常现象,并非证书有问题。需要再导入中间证书后,才会显示可信任。
自行验证:双击 server-mid_chain.crt 全链证书,切换到「证书路径」标签页,即可看到完整三层链:My Root CA → My Intermediate CA → my server ca 。
总结:单看
server.crt就像只看身份证却找不到发证机关是谁;全链证书server-mid_chain.crt则附上了发证机关的完整授权链,系统自然能追溯验证。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
赣公网安备36072602000131号