1976年,Whitfield Diffie和Martin Hellman发表了一篇划时代的论文,提出了公钥密码学的概念。在此之前,任何想要秘密通信的双方都必须预先共享密钥——这是一个困扰密码学家数千年的难题。然而,公钥密码学在解决密钥分发问题的同时,也带来了一个新的困境:它太慢了。
有多慢?在同等安全强度下,RSA的加密速度比AES慢约1000倍,而解密速度差距更是达到3000倍以上。这个性能鸿沟并非工程实现的缺陷,而是数学原理的必然结果。理解这一点,是理解现代密码学架构的关键。
对称加密的效率密码:比特操作的优雅
AES(Advanced Encryption Standard)的设计哲学可以概括为:用简单的操作,反复叠加。
一次AES加密操作的核心是什么?是XOR、查表、字节移位。这些操作在现代CPU上几乎都可以在单个时钟周期内完成。AES-128执行10轮变换,每轮包含四个步骤:SubBytes(S盒替换)、ShiftRows(行移位)、MixColumns(列混淆)和AddRoundKey(轮密钥加)。

图片来源: upload.wikimedia.org
SubBytes是唯一的非线性操作,通过一个固定的256字节查找表(S-box)将每个字节映射为另一个字节。ShiftRows简单地将状态矩阵的行循环移位。MixColumns在有限域GF(2^8)上进行矩阵乘法,实现列内字节的混合。AddRoundKey则是对状态和轮密钥进行XOR。
这些操作的共同特点是:它们都是常数时间操作,且与现代CPU的字长完美匹配。
BearSSL的基准测试数据清晰地展示了AES的性能优势。在使用AES-NI硬件加速的x86-64平台上,AES-128 CTR模式的吞吐量达到2426 MB/s。即使在没有硬件加速的纯软件实现中,使用查表法的AES-128 CBC加密也能达到约163 MB/s。
更重要的是,AES加密的数据量与密钥长度完全解耦。无论你要加密1KB还是1GB的数据,使用的都是同一个128位(或192/256位)密钥。加密一个字节只需要几次简单的查表和XOR操作。
非对称加密的计算代价:大数运算的重担
RSA的数学基础看似简单:选择两个大素数p和q,计算n = p×q和φ(n) = (p-1)(q-1),选择公钥指数e,计算私钥d = e^(-1) mod φ(n)。加密:c = m^e mod n;解密:m = c^d mod n。
问题在于那个不起眼的"^e"和"^d"。
RSA-2048的操作对象是2048位的大整数。这不是CPU原生支持的数据类型——现代CPU的寄存器最多64位。一次模幂运算需要进行数千次大整数乘法和模约减。
大整数乘法的复杂度是多少?朴素算法是O(n²),对于2048位的数,这意味着需要进行约400万次单字乘法。Karatsuba算法可以将其降低到O(n^1.585),但实际实现中,由于常数因子的影响,只有在非常大的数上才能体现优势。
更关键的是,RSA的私钥指数d通常是一个接近n的2048位数。这意味着解密操作需要进行大约2048次模平方和数百次模乘法(取决于d的汉明重量)。
BearSSL的基准数据给出了残酷的现实:在Intel Xeon E3-1220 V2(3.10 GHz)上,RSA-2048的私钥操作速度约为355次/秒(使用i62优化实现)。相比之下,AES-128 CTR模式在这个平台上可以处理约2.4 GB/s的数据——大约是1500万次/秒的128位块加密。
简单换算:AES比RSA快约40000倍。
这就是为什么RSA被限制在加密小量数据上。一个2048位的RSA密钥最多只能加密245字节的数据(使用PKCS#1 v1.5填充后)。如果要加密更大的数据,唯一的可行方案是:用RSA加密一个随机的对称密钥,然后用这个对称密钥加密数据——这就是混合加密。
椭圆曲线:在更小的数字上做更难的问题
ECC(Elliptic Curve Cryptography)的出现,部分缓解了非对称加密的性能困境。
椭圆曲线密码学的安全性基于椭圆曲线离散对数问题(ECDLP):给定椭圆曲线上的基点G和点P = kG,找出整数k是困难的。与RSA的大整数分解问题相比,ECDLP在同等安全强度下可以使用更小的密钥。
根据NIST的建议,256位的椭圆曲线密钥提供的安全强度约等于3072位的RSA密钥,也约等于128位的对称密钥。这意味着ECC操作涉及的是256位整数,而不是2048位或3072位。
BearSSL的Curve25519基准数据:在相同平台上,Curve25519的点乘法可以达到约5700次/秒(使用c25519_m31实现)。这比RSA-2048的私钥操作快约16倍,但仍然比AES慢约2500倍。
性能差距依然存在,但已经大大缩小。这就是为什么TLS 1.3完全移除了RSA密钥交换,转而强制使用ECDHE(Elliptic Curve Diffie-Hellman Ephemeral)。
混合加密:工程上的最优解
现代密码学系统的设计几乎是统一的:用非对称密码学解决密钥分发问题,用对称密码学解决数据加密问题。
TLS握手是这一原则的典型体现:
-
密钥交换阶段:客户端和服务器通过ECDHE协商出一个预主密钥(pre-master secret)。这个过程涉及椭圆曲线点乘法,计算开销大,但只需执行一次。
-
密钥派生阶段:预主密钥通过伪随机函数(PRF)派生出对称加密所需的会话密钥。
-
数据传输阶段:所有后续通信都使用AES-GCM或ChaCha20-Poly1305进行对称加密。这个阶段可以处理GB级别的数据,性能开销极小。
sequenceDiagram
participant C as 客户端
participant S as 服务器
Note over C,S: TLS 1.3 握手 (1-RTT)
C->>S: ClientHello + KeyShare(ECDHE公钥)
S->>C: ServerHello + KeyShare(ECDHE公钥) + Certificate + Finished
Note over C,S: 双方计算共享密钥
C->>S: Finished (已加密)
Note over C,S: 后续通信使用对称加密
这种设计的精髓在于:将昂贵的非对称操作限制在握手阶段(每连接一次),将高效的对称操作用于数据传输(每连接数百万次)。
前向安全性:为什么RSA密钥交换被废弃
TLS 1.3最重要的变化之一是彻底移除了RSA密钥交换。这不是因为RSA不安全,而是因为RSA密钥交换无法提供前向安全性(Forward Secrecy)。
在RSA密钥交换中,客户端生成一个随机的预主密钥,用服务器的RSA公钥加密后发送。如果攻击者记录了这次通信,并在日后获取了服务器的私钥,就可以解密所有历史通信。
ECDHE的解决方案是:每次握手都生成临时的密钥对。即使服务器的长期私钥泄露,攻击者也无法解密历史通信,因为每次握手使用的临时密钥对早已销毁。
这带来了一定的性能代价:每次握手都需要执行椭圆曲线点乘法。但如前所述,Curve25519的点乘法在现代CPU上只需要约0.2毫秒,对于TLS握手的总体延迟(通常在数十到数百毫秒)来说,这个开销是可以接受的。
硬件加速:AES-NI的影响
2008年,Intel宣布将在其CPU中引入AES-NI指令集。这是一组专门为AES设计的硬件指令,将SubBytes、ShiftRows、MixColumns等操作编码为CPU原生指令。
AES-NI的影响是巨大的。根据Intel的官方数据,AES-NI可以将AES的性能提升3-10倍。BearSSL的基准数据更具体:在支持AES-NI的平台上,AES-128 CTR模式的吞吐量从纯软件实现的约93 MB/s跃升到2426 MB/s——提升超过25倍。
这引出了一个有趣的对比:在没有AES-NI的平台上(如ARM移动设备),ChaCha20-Poly1305往往比AES-GCM更快。ChaCha20的设计天生对软件实现友好,不需要依赖查表,也不受缓存时序攻击的影响。
这就是为什么TLS 1.3同时支持AES-GCM和ChaCha20-Poly1305。现代TLS库会根据平台能力自动选择最快的密码套件。
密钥长度的安全等价性
理解对称和非对称加密的性能差异,还需要理解它们密钥长度的含义完全不同。
对称密钥的长度直接对应暴力破解的难度:破解一个128位的AES密钥平均需要2^127次尝试。这是天文数字——即使使用全人类所有的计算资源,直到宇宙热寂也无法完成。
非对称密钥的长度则取决于底层数学问题的难度。RSA的安全性基于大整数分解问题的难度,而分解一个n位整数的最快已知算法(通用数域筛,GNFS)的复杂度约为exp((ln n)^(1/3) (ln ln n)^(2/3))。这意味着RSA密钥的增长是对数级别的安全提升。
| 安全级别(比特) | 对称密钥 | RSA密钥 | ECC密钥 |
|---|---|---|---|
| 80 | 80 | 1024 | 160 |
| 112 | 112 | 2048 | 224 |
| 128 | 128 | 3072 | 256 |
| 192 | 192 | 7680 | 384 |
| 256 | 256 | 15360 | 521 |
这个表格揭示了一个关键洞察:ECC在密钥长度上更接近对称密码的效率,但计算复杂度仍然高出数个数量级。
填充的必要性:RSA不是直接加密
RSA不能直接加密原始数据。原因有两个:数学限制和安全需求。
数学上,被加密的消息m必须满足0 < m < n(n是模数)。如果直接加密一个接近n的数,经过模幂运算后可能无法唯一还原。更关键的是,如果m很小而e也很小(比如e=3),m^e可能小于n,这时开立方根就能直接破解。
安全上,RSA的原始形式(教科书RSA)具有严重的密码学弱点。最著名的是Bleichenbacher在1998年提出的攻击:如果服务器对PKCS#1 v1.5填充格式的正确性给出不同的响应,攻击者可以通过数百万次的适应性查询,逐步恢复出明文。这个攻击在2018年的ROBOT攻击中被证明仍然影响着许多现代系统。
解决方案是OAEP(Optimal Asymmetric Encryption Padding),它在RSA加密前对明文进行复杂的填充变换,引入随机性使得同一明文每次加密产生不同的密文。
graph LR
M[明文消息] --> OAEP[OAEP填充]
OAEP --> |加入随机种子| P[填充后消息]
P --> RSA[RSA加密]
RSA --> C[密文]
填充机制进一步压缩了RSA可以加密的数据量。RSA-2048使用OAEP填充后,最多只能加密约190字节的数据。
从数学到工程的权衡
密码学原语的性能差异不是缺陷,而是特性。它们各自服务于不同的目的:
- 对称密码学(AES、ChaCha20)用于保密性,高效处理大量数据。
- 非对称密码学(RSA、ECC)用于密钥协商和身份认证,解决密钥分发难题。
- 哈希函数(SHA-256、BLAKE3)用于完整性,提供数据的唯一指纹。
- 消息认证码(HMAC、Poly1305)用于真实性,验证消息来源。
现代密码系统是这些原语的精心组合。TLS是混合加密的典范。Signal协议在混合加密的基础上增加了棘轮机制,每次消息都更新密钥。WireGuard使用Curve25519进行初始握手,然后切换到ChaCha20-Poly1305进行数据传输。
理解这些性能差异,才能在设计安全系统时做出正确的选择。当你需要加密数据库中的敏感字段时,使用AES,不要用RSA。当你需要安全地交换密钥时,使用ECDHE,不要用固定密钥。当你需要签名验证时,优先考虑Ed25519而不是RSA-PSS。
密码学的安全性建立在数学难题的困难性上,而困难性本身就意味着计算开销。我们无法同时拥有最高的安全性和最快的速度——这是计算复杂性理论的铁律。混合加密的价值在于,它让我们在正确的地方使用了正确强度的工具。
参考资料
- Daemen, J., & Rijmen, V. (2001). AES Proposal: Rijndael. NIST.
- Rivest, R. L., Shamir, A., & Adleman, L. (1978). A Method for Obtaining Digital Signatures and Public-Key Cryptosystems. Communications of the ACM.
- Diffie, W., & Hellman, M. (1976). New Directions in Cryptography. IEEE Transactions on Information Theory.
- Bernstein, D. J. (2006). Curve25519: New Diffie-Hellman Speed Records. PKC 2006.
- Rescorla, E. (2018). The Transport Layer Security (TLS) Protocol Version 1.3. RFC 8446.
- BearSSL Speed Benchmarks. https://www.bearssl.org/speed.html
- Intel Corporation. Intel Advanced Encryption Standard Instructions (AES-NI).
- Bleichenbacher, D. (1998). Chosen Ciphertext Attacks Against Protocols Based on the RSA Encryption Standard PKCS #1. CRYPTO ‘98.
- NIST SP 800-57 Part 1 Rev. 5. Recommendation for Key Management.
- Wikipedia. Advanced Encryption Standard. https://en.wikipedia.org/wiki/Advanced_Encryption_Standard