第2章 密码学基础速览:对称加密、非对称加密、哈希函数、数字签名与MAC
说实话,很多搞网络协议的朋友,一上来就啃TLS握手细节,结果被密钥交换、证书链这些东西搞得一头雾水。归根结底,是密码学底子不够扎实。我不是说要你去啃数论或椭圆曲线,但核心的几个密码学原语——对称加密、非对称加密、哈希、数字签名、消息认证码——必须得搞明白它们各自解决什么问题、有什么坑。
我个人习惯,把TLS握手的本质看成一个「三步走」:身份验证、密钥协商、安全传输。每一步都依赖不同的密码学工具。本章我们就先把这些工具过一遍,后面讲到握手流程时,你自然就知道它们用在哪了。
2.1 对称加密:速度快,但密钥怎么给?
对称加密,说白了就是加密和解密用同一把钥匙。你拿钥匙锁门,别人拿同一把钥匙开门。这个“钥匙”在密码学里叫密钥(Secret Key)。
常见的对称加密算法有:
- AES(高级加密标准):当今最主流的分组密码,密钥长度128/192/256位。TLS 1.2/1.3都在用。
- ChaCha20:流密码,在移动设备上性能特别好,Google 和 Cloudflare 都在推。
- DES/3DES:老古董了,现在已被禁用。我几年前做项目迁移时,还在遗留系统里见过3DES,赶紧建议对方换掉了。
对称加密最大的优势是快。硬件加速后,AES加解密能做到几GB/s。但它有个致命问题——密钥分发。假如你和我通信,咱们得事先共享同一个密钥。那这个密钥怎么安全地传给对方?通过电话?快递U盘?都不现实。
我在项目中遇到过团队直接用对称加密做API鉴权,结果密钥硬编码在App里,反编译一下就全泄露了。嗯,这其实不是算法的问题,是没搞懂「密钥如何安全协商」。
2.2 非对称加密:公钥加密,私钥解密
非对称加密的概念改变了很多人的认知。它使用一对密钥:一个叫公钥,可以公开给全世界;另一个叫私钥,必须自己藏好,谁也不能给。
它有两个核心用法:
- 加密:别人用你的公钥加密数据,只有你能用私钥解密——这解决了对称加密的密钥分发问题。
- 签名:你用私钥签名一段数据,别人用你的公钥验证签名是否有效——这解决了身份认证问题。
常见的非对称算法:
- RSA:最经典,支持加密和签名。位数越长越安全,现在推荐至少2048位。但RSA签名速度慢,且密钥对生成很耗时。
- ECC(椭圆曲线密码学):同样安全强度下,密钥长度比RSA短得多。比如256位ECC ≈ 3072位RSA。TLS 1.3基本都在推ECC。
- DH/DHE:严格来说它不是加密算法,而是密钥交换协议。后面章节我们会详细讲。
| 特性 | 对称加密 | 非对称加密 |
|---|---|---|
| 密钥数量 | 1个(共享密钥) | 2个(公钥+私钥) |
| 速度 | 极快(硬件加速可达GB/s) | 慢(比对称加密慢100-1000倍) |
| 密钥分发 | 困难,需安全通道 | 公钥可公开,私钥本地保存 |
| 典型用途 | 大量数据加密 | 密钥交换、数字签名 |
举个例子:我在配置TLS时,证书里的公钥就是非对称的。握手时,客户端用这个公钥加密一个随机数发给服务器,服务器用私钥解密,从而安全地建立共享密钥。你想想看,如果没有非对称加密,这个随机数在网络上裸奔,整个会话瞬间就废了。
2.3 哈希函数:数据指纹的“摘要器”
哈希函数(Hash Function)是一个非常有意思的工具。它能把任意长度的输入,变成固定长度的输出(比如256位)。这个输出叫哈希值或摘要。而且,它有几个重要特性:
- 单向性:从哈希值无法反推出原始数据。
- 抗碰撞性:很难找到两个不同的输入产生同样的哈希值。
- 雪崩效应:输入哪怕改一个比特,哈希值几乎会完全变化。
常见的哈希算法:SHA-2(SHA-256/384/512)是TLS的主流选择。SHA-1已经不安全了,2017年后主流浏览器基本都拒绝SHA-1证书。我经历过一次因为使用SHA-1证书导致的浏览器兼容性事故,那时候真是手忙脚乱。
哈希在TLS里至少有四个重要用途:
- 证书指纹:验证证书是否被篡改。
- 消息完整性:配合MAC使用,确保数据在传输中没被修改。
- 密钥派生:通过PRF(伪随机函数)混合输入,生成会话密钥。
- 数字签名的基础:先对数据进行哈希,再对哈希值签名,而不是直接签名原始数据。
2.4 数字签名:让公钥变成“可信的”
光有非对称加密还不行。你想,中间人也可以生成一对密钥,把公钥发给你,然后你用它加密的数据全被中间人解密了。你怎么知道这个公钥真的是服务器的?数字签名(Digital Signature)就是解决这个问题的。
数字签名的流程很清晰:
- 发送方对数据(或其哈希值)用私钥进行签名运算,生成签名值。
- 接收方用发送方的公钥验证签名是否有效。
- 如果验证通过,说明数据确实来自私钥持有者,且未被篡改。
我在一次安全审计时发现,某个系统为了让伪造的请求通过验证,直接硬编码了服务器的公钥。这其实就绕过了签名的意义——公钥必须是可信的、经过证书链验证的。TLS里通过数字证书来绑定公钥和身份(比如域名)。证书是由CA(证书颁发机构)签名的。你浏览器里预置了根证书,顺着证书链一层层验证,最终确认服务器的公钥是真的。
常见的签名算法:RSA签名和ECDSA(椭圆曲线数字签名算法)。ECDSA签名更短,性能更好,在移动端和物联网场景优势明显。
2.5 MAC与HMAC:防篡改的“封装锁”
最后一个原语是消息认证码(MAC)。它和哈希有点像,但多了一个共享密钥的输入。
MAC的核心能力:
- 发送方用共享密钥对消息计算MAC值,随消息一起发送。
- 接收方用同样的密钥和收到的消息重新计算MAC,比对是否一致。
- 如果一致,说明消息未被篡改,且确实来自持有共享密钥的一方。
MAC和哈希的区别:哈希只有输入数据一个参数;MAC有两个参数(数据和密钥)。简单来说,MAC保证了在不知道密钥的情况下,攻击者无法伪造合法消息。TLS里最常用的MAC是HMAC(基于哈希的MAC)。比如HMAC-SHA256就是先用SHA-256加密钥处理消息。
2.6 它们是如何协同工作的?
我们把上面几个概念串起来,看看在TLS握手里它们实际怎么配合:
- 身份认证:服务器发送证书(含公钥),CA用数字签名保证证书可信。客户端验证签名通过。
- 密钥协商:客户端用服务器公钥加密一个随机数,或使用DH/ECDH密钥交换,双方各自计算出相同的预主密钥(Pre-Master Secret)。然后用PRF派生出一堆会话密钥(包括对称加密密钥和HMAC密钥)。
- 安全传输:之后的数据用对称加密(如AES)加密,同时附加HMAC保证完整性。接收方解密并验证HMAC,确保数据在传输中没被篡改。
你看,每个密码学工具各司其职。非对称加密和签名搞定握手阶段,对称加密和HMAC搞定数据传输阶段,哈希函数则是众多安全机制的基础砖石。
下面这张图梳理了本章的核心知识体系:
这张图把五个原语和TLS三个阶段的关系画得很清楚。你可以看到,哈希函数横跨三个阶段,它在证书指纹、密钥派生、PRF里都有出现。
2.7 避坑小集
最后,我整理几个自己踩过的坑,以及经常被问到的误区:
- 千万别用SHA-1:我曾经维护一个老旧系统,发现证书还是SHA-1,结果被安全扫描工具报高风险,赶紧走流程更换。现在主流浏览器都禁了SHA-1证书。
- 对称加密要注意模式:比如AES-ECB模式不安全,同样的明文块会得到同样的密文块。TLS里用的是GCM或CBC(配合HMAC)。分不清模式的人写代码会出大问题。
- 密钥不能硬编码:我见过太多项目把对称密钥或私钥写在配置文件里提交到Git仓库。一旦泄露,整个系统就废了。正确的做法是用密钥管理服务(KMS)或硬件安全模块(HSM)。
- 不要自己拼算法:你用AES加密数据,自己设计一个MAC方案?别闹了。TLS有标准化的记录层协议,所有细节都定好了。用开源库才是正解。