密文检索基础:同态加密与可搜索加密

为什么需要密文检索?

数据加密后,你就没法直接搜、没法直接算了。但业务场景往往要求你在密文上干活——比如云端存着病人的化验单,你不能解密再统计平均值,那会泄露隐私。密文检索就是解决这个矛盾的。

说白了,它让系统在“眼盲”的状态下,还能帮你找到正确的东西。我接触这个领域是几年前做医疗数据共享项目,甲方要求搜索“阳性病例”但不能看到具体姓名。那会儿我第一个想到的就是可搜索加密,后来发现同态加密也能做,但性能天差地别。

同态加密(HE):加密状态下计算

同态加密允许你对密文直接做加法、乘法,解密后得到的结果和明文上做运算一样。举个例子:你手里有加密后的工资数据,你想算平均工资。正常做法是解密→计算→再加密。HE 让你直接在密文上算,算出加密后的平均值,然后解密拿到结果。

关键点:HE 保护的是计算过程的隐私,不是搜索的隐私。它擅长聚合统计、模型推理这类场景。

同态加密有几个级别:

  • 部分同态(PHE):只支持加法或只支持乘法。比如 Paillier 只能做加法同态,RSA 只能做乘法同态。性能还行,实际可用。
  • 浅同态(SHE):支持有限次数的加法和乘法。适合做多项式计算,但不能无限叠加。
  • 全同态(FHE):支持任意次数的加法和乘法,理论上可以跑任何程序。但性能极差,一个简单计算可能慢几千倍。

我记得第一次跑全同态乘法,128 位安全级别下,一次乘法花了 0.3 秒。我当时的内心是崩溃的。嗯,不要指望 FHE 能处理实时流数据。

避坑指南:我曾经带团队评估 FHE 库(SEAL、HElib),发现噪声管理是最大的坑。每次乘法噪声都会膨胀,搞不好就解密失败。务必先用小规模数据压测,否则上线后半夜报警你会很头痛。

可搜索加密(SSE):加密状态下搜索

可搜索加密解决的是另一种需求:我想在加密文档库里搜关键词,但不暴露文档内容,也不暴露搜索词。HE 也能搜,但代价太大。SSE 专为此而生。

SSE 的基本思路:

  1. 为文档集构建加密索引,索引里每个关键词对应一组文档标识符。
  2. 用户用密钥生成一个“陷门”(trapdoor),相当于加密后的搜索词。
  3. 服务器拿着陷门在加密索引上匹配,返回匹配的加密文档标识符。
  4. 用户解密标识符,再按需解密文档。

你想想看,整个过程服务器不知道你搜了什么词,也不知道你搜出了哪些文档。隐私保护到位。

SSE 又分为几种类型:

类型 特点 性能 典型场景
对称 SSE 搜索方和加密方共享同一个密钥 快(O(匹配文档数)) 个人云盘、私有文档搜索
非对称 SSE 公钥加密,私钥搜索;支持多用户写入 慢(通常需要配对运算) 共享数据库、投稿系统
动态 SSE 支持添加/删除文档后更新索引 中等(更新开销较大) 日志审计、实时数据流

我参与过的一个日志审计系统,用的就是动态 SSE。因为每天会新增几百万条日志,静态索引重建一次要 40 分钟,太离谱了。后来换用支持更新操作的方案,每次增量更新几十毫秒搞定。这就引出一个避坑点——

经验之谈:别盲目上动态 SSE 框架。很多里的方案不支持删除或更新效率极低。建议先评估你的数据变更频率,如果几乎不删除,用静态索引定期重建更省事。

同态加密 vs 可搜索加密:怎么选?

很多人搞混这两者。我简单对比一下:

对比维度 同态加密(HE) 可搜索加密(SSE)
核心能力 密文上做任意计算 密文上做关键词搜索
搜索性能 极差(FHE 慢 10^6 倍) 好(通常亚秒级)
计算灵活性 极高(可执行任意函数) 低(仅支持关键词匹配)
数据泄露 几乎无(语义安全) 有(访问模式泄露)
适用场景 数据聚合、模型推理、隐私机器学习 文档搜索、日志审计、关键字过滤
成熟度 FHE 仍偏学术,工程化困难 已有工业级实现(如 CryptDB、Oblivious 方案)
一句话总结:需要做运算选 HE,需要做搜索选 SSE。两件事都想做?可以结合使用——但要做好性能爆炸的心理准备。

技术选型决策逻辑

下面这张 SVG 图展示了我在项目中常备的选型流程。从需求出发,先问你是要“计算”还是“搜索”,然后逐层细化到具体技术。

密文检索技术选型决策流程 密文检索技术选型决策流程 你的核心需求? 需要计算/统计 需要搜索关键词 仅加/乘法 任意函数 PHE(Paillier、ElGamal) FHE(CKKS、BGV) 单用户/少量文档 多用户/频繁更新 对称 SSE 非对称 / 动态 SSE ⚠ 注意 实际项目中可能混合使用:先用 SSE 筛出候选文档, 再用 HE 对候选集做聚合计算。但性能瓶颈常出现在 HE 部分。

你看这个图,从根需求出发,两条路区别很明显。左边走 HE,右边走 SSE。我个人的建议是:别一上来就想着“全同态加密好屌”,先掂量一下你的计算复杂度。多数审计日志场景只需要关键词匹配,SSE 足够。

避坑清单(个人实战总结)

  • 别忽略访问模式泄露:SSE 的搜索模式会暴露哪些文档被搜到了多少次。攻击者可以通过频率分析反推查询内容。我在一个金融项目里补丁了 ORAM(不经意随机访问)才解决。
  • 同态加密的密钥长度别贪安全:有人非要设 256 位安全级别,结果一次加法慢得肉眼可见。128 位通常够用,别自找麻烦。
  • 索引更新务必测试并发:动态 SSE 的并发写入经常死锁。我曾经在生产环境遇到过,因为底层数据结构(如稀疏矩阵)没加锁,导致索引损坏。
  • 硬件加速别迷信:有些同态加密声称支持 GPU/FPGA 加速,但实际部署时驱动、精度、内存带宽都会出问题。买之前找厂商要真实 benchmark。
  • 业务逻辑不要硬套:如果你的查询经常需要排序、模糊匹配、正则,SSE 基本帮不上忙。这时候考虑一下 SQL on encrypted data(比如 CryptDB 的方案),或者干脆配合硬件 TEE。
特别警告:不要自己实现密码学原语。我现在看见有人手写 SSE 伪代码就头皮发麻。开源库(如 libsodium、Microsoft SEAL、Oblivious-C)已经踩过坑的,直接复用比重新造轮子安全百倍。

性能调试小记

我举个例子,之前做 SSE 项目,加密索引用的是布谷鸟哈希(Cuckoo Hashing)。理论写入复杂度 O(1),但实际跑起来因为冲突重哈希,经常把 CPU 打满。后来换成经典哈希表 + 链地址法,虽然空间多了点,但实际吞吐翻了三倍。

嗯,这里有个教训:别只看里的渐进复杂度,要拿真实数据集做压力测试。我个人习惯是先拿 10 万条数据跑一轮,确认没有内存泄漏和性能断崖,再上生产。