3. 密码学基础(下):数字签名、数字证书、CA 信任链、公钥基础设施(PKI)概念
上一节我们把对称加密、非对称加密和哈希聊透了。这一节,咱们聊聊怎么把这些技术串起来,解决一个核心问题:你拿到的公钥,到底是不是对方的?
我在早期做安全方案时,就踩过这个坑。当时自己写了个加密通信工具,用 RSA 交换公钥。结果中间人攻击一来,我的公钥被换了,我还浑然不知。嗯,从那以后我才真正理解——没有身份验证的加密,等于没加密。
3.1 数字签名:谁说公钥不能“签名”?
先问个问题:私钥加密,公钥解密,这能叫签名吗?
严格来说,不是。真正的数字签名,是对消息的哈希值做加密,而不是对消息本身。为什么?
- 性能:非对称加密很慢。对整条消息加密,太奢侈了。
- 语义安全:直接加密消息,会暴露消息长度等信息。
所以,标准做法是:
- 对消息做哈希,得到摘要(digest)。
- 用私钥加密这个摘要,得到签名。
- 把签名和原始消息一起发出去。
验证方收到后,用公钥解密签名,得到摘要 A;再对消息做哈希,得到摘要 B。如果 A == B,说明消息没被改过,而且确实是私钥持有者签的。
核心结论:数字签名 = 哈希 + 非对称加密。它提供了完整性和不可否认性,但不提供机密性。
我在项目中见过有人把签名和加密搞混。签名是证明“谁写的”,加密是保证“谁看的”。两码事。
3.2 数字证书:把公钥和身份绑在一起
好,现在我有签名了。但我怎么知道这个公钥属于张三,而不是李四冒充的?
答案就是数字证书。说白了,证书就是一张“身份证”,里面写着:
- 持有者的身份信息(域名、组织名等)
- 持有者的公钥
- 证书的有效期
- 签发者的签名
你想想看,如果我自己给自己签一张证书,说“我是百度”,你信吗?当然不信。所以,证书必须由大家都信任的第三方来签发。这个第三方,就是 CA(Certificate Authority,证书颁发机构)。
一个典型的 X.509 证书结构长这样:
| 字段 | 说明 |
|---|---|
| 版本号 | 通常是 v3 |
| 序列号 | CA 分配的唯一编号 |
| 签名算法 | 如 SHA256-RSA |
| 颁发者 | 签发该证书的 CA 名称 |
| 有效期 | 开始和结束时间 |
| 主体 | 证书持有者的信息 |
| 公钥 | 持有者的公钥 |
| 扩展 | 用途、约束等 |
| CA 签名 | CA 用私钥对上述内容的签名 |
个人习惯:我每次部署 TLS 时,都会用 openssl x509 -text -in cert.pem 看一眼证书的扩展字段。特别是 Subject Alternative Name (SAN),很多证书问题都出在这里。
3.3 CA 信任链:信任是怎么传递的?
CA 给网站签了证书,那 CA 自己的证书谁来签?
答案是:根 CA 自己签自己(自签名)。根 CA 的证书预装在操作系统或浏览器里。这就是信任的起点。
但根 CA 不能直接给所有网站签证书,那样风险太大。所以有了中间 CA:
- 根 CA 给中间 CA 签证书
- 中间 CA 给网站签证书
这就形成了一条信任链:
根证书 → 中间证书 → 服务器证书
验证时,浏览器从服务器证书开始,逐级向上验证签名,直到找到系统里信任的根证书。只要链条完整,就信任。
我曾经踩过的坑:有一次部署 HTTPS,只配了服务器证书,没配中间证书。结果 Chrome 报错,但 Safari 能打开。为什么?因为 Safari 自己缓存了中间证书,Chrome 没有。从那以后,我每次都会用 openssl verify -CAfile ca-bundle.crt server.pem 验证完整链。
3.4 PKI:让这一切运转起来的体系
数字签名、数字证书、CA 信任链,这些都不是孤立的技术。它们共同构成了公钥基础设施(PKI)。
PKI 不是某个具体的算法或协议,而是一整套策略、流程、硬件、软件的组合。它的核心职责是:
- 注册:验证申请者的身份
- 颁发:生成并签发证书
- 撤销:通过 CRL 或 OCSP 吊销证书
- 更新:证书到期前续期
- 归档:保存历史证书和日志
我参与过企业内部 PKI 的建设。说实话,技术本身不复杂,复杂的是运营流程。比如:谁有权申请证书?证书丢了怎么紧急吊销?这些都得提前想清楚。
下面这张图,把 PKI 的核心流程串起来了:
3.5 证书撤销:证书过期了怎么办?
证书有有效期,一般是 1-2 年。但有时候,证书还没到期就得作废。比如私钥泄露、域名变更、员工离职。
这时候就需要证书撤销。两种主流方式:
- CRL(证书撤销列表):CA 定期发布一个黑名单,列出所有被撤销的证书序列号。缺点是列表会越来越大。
- OCSP(在线证书状态协议):实时查询某个证书是否被撤销。更灵活,但需要 CA 提供在线服务。
我建议:生产环境优先用 OCSP Stapling。服务器自己缓存 OCSP 响应,每次握手时发给客户端,省去客户端单独查询的延迟。Nginx 配置里加一行 ssl_stapling on; 就行。
3.6 小结:你该记住什么?
这一节内容不少,但核心就几条:
- 数字签名 = 哈希 + 私钥加密,保证完整性和不可否认性。
- 数字证书 = 公钥 + 身份信息 + CA 签名,解决公钥归属问题。
- 信任链 = 根 CA → 中间 CA → 服务器证书,逐级验证。
- PKI = 让这一切能落地运营的体系。