第3章 公钥加密基础与RSA归纳总结
说实话,在密文检索场景中做密钥边界约束,绕不开公钥加密。我刚开始接触这个领域时,总觉得对称加密够用了——快、简单。但后来发现,要让多个用户各自持有不同查询权限,又不暴露底层密钥,公钥体系几乎是唯一解。RSA作为最经典的公钥方案,背后那套数学原理,咱们得先吃透。
3.1 非对称加密的核心逻辑
公钥加密,说白了就是“一把锁配两把钥匙”。一把公开,大家都能用它上锁;另一把私藏,只有自己能开锁。这和传统锁具完全不同——你想想,谁会把自己家门钥匙到处送人?
- 公钥(Public Key):用于加密,可公开分发,谁都可以拿它加密消息
- 私钥(Private Key):用于解密,必须保密,只有持有者才能解密
- 单向陷门函数:加密容易,反向计算极难,除非你知道“陷门”(私钥)
我个人习惯把公钥类比成“信箱号码”——任何人都能往你信箱里投信(加密),但只有你才有信箱钥匙(私钥)取出信件。这个比喻在培训新同事时特别管用。
3.2 RSA:大整数分解的魔法
RSA是1977年由Rivest、Shamir、Adleman三人提出的,至今仍是应用最广泛的公钥算法。它的安全性基于一个大数难题:大整数分解。两个大素数相乘容易,但从乘积反推出这两个素数极其困难。
来,咱们看看密钥生成流程。我把它拆成几步,你对照着理解:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 随机选择大素数 p 和 q | 一般要求 512 位以上,商用场景推荐 2048 位 |
| 2 | 计算 n = p × q | n 的位数就是密钥长度,比如 2048 位 RSA 的 n 有 2048 位 |
| 3 | 计算 φ(n) = (p-1)(q-1) | 欧拉函数值 |
| 4 | 选择公钥指数 e | 通常取 65537(0x10001),兼顾安全与效率 |
| 5 | 计算私钥 d ≡ e⁻¹ mod φ(n) | 扩展欧几里得算法求模逆 |
密钥对就这样产生了:公钥 (n, e),私钥 (n, d)。注意,p、q、φ(n) 必须销毁或妥善保护——我在项目中见过有人把 p、q 留在注释里,结果被内部审计扫描出来,差点翻车。
3.3 加密与解密操作
加密和解密其实就是模幂运算,数学上非常对称:
加密:c = m^e mod n
解密:m = c^d mod n
其中 m 是明文整数(需要先编码成小于 n 的整数),c 是密文。这里有个关键约束:明文必须严格小于 n。如果大于 n,RSA 直接失效,解密会得到错误结果。嗯,这引出了咱们这门课的核心——密钥边界约束。
边界约束第一定理(我的叫法):在 RSA 加密中,有效明文空间是 [0, n-1] 的整数集合。超出这个边界的任何数据,都无法正确加密/解密。密文检索系统必须保证查询参数和加密数据都落在这个边界内。
3.4 RSA 安全性边界
光知道公式还不够。RSA 的安全边界受几个因素约束,我整理成清单,你对照检查:
- 密钥长度:小于 1024 位的 RSA 已被认为不安全,NIST 推荐 2048 位以上
- p、q 差值:二者不能太接近,否则 Fermat 分解法可以快速攻破。我习惯说“p 和 q 最好差几个比特位”
- e 的选取:e 太小(如 3)可能遭受 Coppersmith 攻击;太大又影响加密性能
- 填充方案:直接对消息 m 加密是危险的——需要 OAEP 等填充方案来抵抗选择密文攻击
- 随机数质量:生成素数时若随机数生成器有弱点,可能导致密钥被预测。我曾经遇到过嵌入式设备上熵池不足,生成的 RSA 密钥重复率极高
踩坑回忆:去年帮客户审计一套密文检索系统,他们用 RSA-OAEP 加密索引关键词,但部署时误将 p 值写进了配置文件(debug 遗留)。攻击者拿到 p 直接算出私钥,整个加密索引形同虚设。所以,边界约束不仅包括数学边界,还包括信息边界——私钥参数不得出现在任何可访问存储中。
3.5 RSA 在密文检索中的角色定位
很多人误以为 RSA 可以直接加密大块数据。错。RSA 速度慢,通常只用来加密对称密钥或短查询令牌。在密文检索场景中,我建议这样用:
- 用 RSA 加密会话密钥(比如 AES 密钥),AES 再去加密文档
- 用 RSA 加密查询 trapdoor(陷门),保证查询条件不泄露
- 用 RSA 签名来验证数据来源完整性
下面这张图总结了 RSA 在密钥边界约束方案中的核心结构:公钥在外围公开,私钥被安全容器保护,消息必须通过“明文空间边界检查”才能进入加密通道。
3.6 RSA 的局限性在边界约束中的体现
没有银弹。RSA 在密文检索中有几处明显的边界短板,我直接列出来,你在设计系统时务必考虑:
- 密钥长度与性能的权衡:2048 位 RSA 单次加密约 1ms(现代 CPU),若检索索引有 10 万条,光加密就卡死。所以通常只加密“查询令牌”而非全量数据
- 密文膨胀:RSA 密文长度等于 n 的字节数(如 256 字节),即使明文只有 1 字节,密文也是 256 字节。这会给存储和带宽带来压力
- 无前向安全性:一旦私钥泄露,所有历史密文都可解密。在需要长期保存密文的检索系统中,建议配合 ephemeral Diffie-Hellman 进行会话密钥协商
- 选择密文攻击:没有 OAEP 填充的 RSA 是可 malleable 的——攻击者可以篡改密文导致解密出意外结果。密文检索中如果使用 RSA 加密查询条件,必须确保填充+签名
我做个项目时踩过一个坑:用 RSA 加密用户查询关键词后直接存入数据库,没有做任何完整性校验。结果网络中间人翻转了密文的某几个比特,解密后得到完全不同的关键词——系统返回了错误文档。后来我强制要求:任何 RSA 密文都附带 HMAC 或 RSA 签名,这才杜绝了这个问题。
3.7 小结:RSA 在密钥边界约束中的位置
RSA 不是万能的,但它在公钥加密领域的地位不可撼动。对于密文检索场景,我给你的建议是:
- 用 RSA-OAEP 加密 短查询令牌(< 245 字节 for 2048-bit RSA)
- 用 RSA 加密 AES 会话密钥,再用 AES 加密文档内容
- 严格检查 m < n,必要时做分段加密或混合加密
- 私钥必须存储在 HSM、TEE 或密钥管理服务中,绝不允许出现在代码或配置里
记住,边界约束不是一句空话,它是从数学到工程的全链路设计。下一层的 ECC 和 Diffie-Hellman 会进一步优化这里的效率问题,但 RSA 的基本功咱们先站稳。你手里有了这套思路,遇到实际系统时,至少知道从哪里开始抠细节。