密文检索概述与基本原理
什么是密文检索
密文检索这名字听着挺唬人,说白了就是给加密数据做个搜索引擎。你想想看,普通搜索是在明文上跑关键词匹配,但数据一旦加密,服务器眼里全是乱码,怎么搜呢?
我记得早期做项目时客户提了个需求:医疗数据必须全链路加密,但医生还得能按患者姓名、诊断码查记录。传统方案是把数据下载到本地解密再搜——数据量一大,带宽和内存根本扛不住。那会儿我才意识到,密文检索不是个锦上添花的功能,而是很多合规场景的刚需。
密文检索的核心能力可以拆成三点:
- 机密性:服务器全程接触不到明文,搜索过程也不泄露搜索条件以外的信息。
- 功能性:支持等于、范围、甚至模糊匹配(取决于具体方案)。
- 效率:检索时间不能随数据量线性爆炸,最好能亚线性或对数级。
说白了,它就是在“加密”和“可检索”之间找平衡。太强的加密会导致没法搜,太弱的加密又等于没加。
核心加密模型
目前主流的密文检索方案可以归为两大类,我习惯把它们叫做“庄家模式”和“擂台模式”。
| 模型 | 英文缩写 | 密钥管理 | 典型场景 |
|---|---|---|---|
| 对称可搜索加密 | SSE | 所有操作使用同一个对称密钥 | 单用户数据备份、个人云盘 |
| 公钥可搜索加密 | PEKS | 发送方用公钥加密,接收方用私钥生成令牌 | 邮件网关、多人协作系统 |
我记得第一个SSE方案(Song等人2000年那篇)出来时,大家都觉得惊艳——但实际落地才发现,它的扫描开销是线性增长的。后来Curtmola等人提出了倒排索引的思路,把每个关键词对应的文件ID列表加密后按顺序存起来,搜索时只需定位到链表头。这种方式业界至今还在用。
而我个人踩过的坑是:别盲目选PEKS。公钥算法虽然看上去更灵活,但双线性配对的开销在单机场景下完全不值当。如果只有你自己上传、自己查询,用SSE就够了,性能差距能到两个数量级。
一点小建议:做方案选型时先问清楚——是谁加密?谁查询?能不能提前共享密钥?这些答案直接决定你应该用SSE还是PEKS。
查询流程概览
我们用一个最简单的单用户SSE模型来走一遍流程。这里我把数据拥有者和查询者都当作“客户端”同一实体。整个流程就三步:构建、搜索、解密。
- 构建阶段:客户端用对称密钥
K加密每个文件,同时为每个关键词生成一个安全索引。索引里存的是“关键词→加密的文件ID列表”,整个索引也加密后上传到服务器。 - 搜索阶段:客户端想搜某个词
w,用密钥K和w通过一个伪随机函数生成搜索令牌(也叫陷门)。服务器拿着令牌,在索引里找到对应的加密链表,顺藤摸瓜取出所有匹配的密文文件ID。 - 解密阶段:客户端收到密文文件ID,按需下载对应的密文文件,再用
K解密得到明文。
这里有个容易忽略的点:服务器在搜索过程中其实只看到了令牌和密文,它无法反推出关键词原文,也无法知道文件内容。这也是整个模型的安全基石。
曾经踩过的坑:我之前在实现SSE时,把索引当作普通加密数据直接存到关系库里,结果搜索时发现每次都要加载全表。后来改成用Key-Value存储并按令牌做哈希分区,才把延迟降下来。索引的存储结构对性能影响极大,别轻视这一步。
说到这个流程图,我一开始画的时候老是把“构建索引”和“生成令牌”放在同一个框里,后来在实际代码中拆成两个独立函数,才意识到它们在时间上和资源开销上是完全不同的阶段。一个在数据写入时执行,一个在查询时执行,千万别混在一起。
关键记忆点:搜索令牌 ≠ 密钥。令牌是密钥和关键词共同作用的结果,它只能搜索你指定的词,无法推导出其他关键词的令牌。否则整个模型就崩了。