密码学基础回顾:哈希函数、密钥交换与证书签名
这一章,咱们来点硬核的。做TLS网关,很多坑其实都出在密码学基础上。说白了,你不理解这些原语,配置就是瞎调。
我记得刚接触HTTPS卸载那会儿,总觉得“证书签名”就是个加密过程。后来被一个问题卡了三天,才搞清楚——签名和加密根本不是一回事。好了,咱们一个个来过。
哈希函数:数字指纹
哈希函数,你可以把它想象成一个“碎纸机+混泥土搅拌机”。输入任意大小的数据,输出固定长度的摘要。而且,这个摘要几乎无法反推原始数据。
核心特性:
- 单向性:给摘要找原像,目前只能暴力猜。
- 抗碰撞:找到两个不同输入产生相同输出,很难。
- 雪崩效应:改一个比特,输出一半以上比特翻转。
TLS 1.3里用了SHA-256、SHA-384。我建议你至少用SHA-256,MD5和SHA-1已经彻底被攻破了。嗯,这里要注意:有些老旧客户端还在用SHA-1证书,你如果做兼容性处理,记得把客户端支持的签名算法列表限制一下,别把服务器也拉到坑里。
实战小技巧: 可以用OpenSSL快速计算文件哈希:openssl dgst -sha256 yourfile.bin。调试证书时很管用,用来验证两边拿到的是不是同一份数据。
密钥交换算法:DH与ECDH
TLS握手最刺激的一步就是密钥交换。没有它,客户端和服务端永远没法安全地通话。我们来看看DH和ECDH。
传统DH(Diffie-Hellman)
我说个简化版:双方各自选个私密数字,然后生成一个公开值交换。最后用彼此的公开值和自己私密数字一算,得到同一个共享密钥。第三方就算截获了所有公开值,也推不出私密数字,更算不出共享密钥。
我曾在项目中遇到一个问题:DH参数体积极大(2048位),握手时CPU负载飙升到70%以上。后来切换到ECDH,负载直接降到10%以下。所以实战中,我几乎不用传统DH。
避坑指南: 我曾经配置过“强DH参数”却忽略了对端支持的椭圆曲线。结果好多老手机连不上。记得把客户端支持的曲线列表用openssl s_client -connect host:port -curves检验一下。
ECDH(椭圆曲线Diffie-Hellman)
ECDH的数学基础是椭圆曲线上的离散对数难题。它用更短的密钥长度提供同等级别的安全强度。比如,256位的ECC等价于3072位的RSA。
实际TLS 1.3里,密钥交换就是基于ECDHE(Ephemeral ECDH)。临时密钥每次握手都生成,完美前向安全性(PFS)就靠它。你想想看,如果某个私钥泄露了,以前会话的流量依然安全——这个特性对边界网关来说太重要了。
| 算法 | 密钥长度(位) | 安全强度(位) | 计算开销 | TLS支持 |
|---|---|---|---|---|
| DH | 2048 | 112 | 中等 | TLS 1.0+ |
| ECDH(P-256) | 256 | 128 | 很低 | TLS 1.2+ |
| ECDH(X25519) | 256 | 128 | 极低 | TLS 1.3 |
| ECDH(P-384) | 384 | 192 | 低 | TLS 1.2+ |
我的实践建议: 网关层优先启用X25519,回退到P-256。X25519是Curve25519的变种,设计上更防侧信道攻击。
证书签名原理
证书签名的核心是“非对称加密的逆用”——私钥签名,公钥验签。但是很多人混淆了两个概念:加密 和 签名。
- 加密:用公钥把数据锁住,只有私钥能解开。目的是保密。
- 签名:用私钥给数据打上“印章”,大家用公钥来验证。目的是防篡改和认证。
我举个例子。CA签发证书时,会先计算服务器公钥+其他字段的哈希,然后用CA私钥对哈希值进行签名。客户端拿到证书后,用CA公钥解密签名得到哈希值,再自己算一遍证书内容的哈希——对比一致就说明这个证书是CA签发的,没人改过。
关键点: 签名不包括私密信息。签名算法(如RSA-PSS、ECDSA)输出的只是数字签名值,原始数据仍然可读。
记得有一次排查TLS握手失败,发现客户端报“certificate signature verification failed”。检查证书链,结果中间证书的签名算法是SHA-1,但根证书已经不支持SHA-1了。我花了大半天才定位到这个低级问题——所以,现在我做证书管理,一定先跑一遍openssl verify -CAfile ca.crt cert.pem。
避坑指南: 证书链里别混用不同签名算法。比如根是RSA-SHA256,中间是ECDSA-SHA384,很容易触发兼容性bug。我建议统一下,至少所有中间证书都用SHA-256以上。
整体知识图谱
下面这张图概括了本章的核心逻辑——从哈希到密钥交换到证书签名,它们如何支撑TLS握手。
简单回顾一下:哈希负责完整性,密钥交换负责协商临时密钥,证书签名负责身份认证和防篡改。这三层叠在一起,TLS握手的加密通道才牢靠。
思考题: 如果哈希函数被攻破(比如找到碰撞),对TLS协议攻击面有多大?答案会涉及签名伪造、中间人攻击等多个层面。我建议你结合TLS 1.3的握手流程自己推演一遍。