对称可搜索加密(SSE)基础
聊到可搜索加密,咱们得先搞明白一件事:为什么需要它?
我最早接触这个方向是在做一个医疗数据共享项目。数据放在云上,但医院方面死活不放心——病历明文存,谁敢啊?可全加密了,医生想搜个诊断记录怎么办?下载到本地解密再搜?几百万条记录,网络带宽根本扛不住。
这时候SSE就派上用场了。说白了,它让你能在加密数据上做搜索,而且能控制哪些信息泄露给服务器。
SSE的核心思想
对称可搜索加密,核心就两件事:
- 加密索引:给每个关键词建一个加密的查找结构
- 令牌搜索:用关键词生成一个令牌,服务器拿着令牌去查索引
你想想看,整个过程数据不动,动的只有加密后的索引和令牌。服务器始终看不到明文,但它能告诉你“这个关键词对应的文件在这儿”。
方案模型:三个角色,六个算法
任何SSE方案都跑不出下面这个三角模型。我在做性能分析时发现,很多人搞不清算法边界,结果实现出来安全性有问题。
| 算法 | 输入 | 输出 | 我习惯这么理解 |
|---|---|---|---|
| KeyGen(1^λ) | 安全参数 λ | 密钥 K | 生成一把“锁” |
| BuildIndex(D, K) | 文档集合 D,密钥 K | 加密索引 I | 给每把锁配个“钥匙孔” |
| EncDoc(D, K) | 文档集合 D,密钥 K | 密文 C | 把文档本身锁进保险柜 |
| (w, K) | 关键词 w,密钥 K | 搜索令牌 τ | 生成一把“钥匙” |
| Search(I, τ, C) | 索引 I,令牌 τ,密文 C | 匹配结果 ID 集合 | 用钥匙去开对应的孔 |
| DecDoc(c_id, K) | 文档 ID,密钥 K | 明文文档 | 打开保险柜看内容 |
核心流程:一次完整的搜索
咱们走一遍一个标准SSE搜索流程。假设你有10份病历文件,想搜所有含“高血压”这个词的。
- 初始化阶段(用户端):跑KeyGen(1^λ)得到一个密钥K。用K跑BuildIndex构建索引I,用K加密所有文档得到密文C。把I和C上传到服务器。
- 搜索阶段(用户端):输入“高血压”,跑(“高血压”, K)得到令牌τ。把τ发给服务器。
- 响应阶段(服务器端):服务器拿着τ查索引I,找到匹配文档ID列表,返回给用户。
- 解密阶段(用户端):用户用K解密对应的文档。
整个过程,服务器知道什么?它知道“有人查了某个关键词,找到了这些ID,ID对应的文件大小也知道了”。但它不知道关键词是什么,更不知道文件内容。
这就是SSE的威力——只泄露“搜索模式”和“访问模式”,不泄露数据本身。
安全定义:我到底要防什么?
这部分我以前看书总觉得绕,直到有一次被审计追问“你的方案能防什么攻击”才彻底搞明白。
SSE的安全性,主要有两个层次:
选择明文攻击(IND-CKA)
简单讲:攻击者能看到加密索引和密文,但看不到搜索令牌。它能不能区分两个已知明文对应的密文?
我记得第一次写SSE代码时,天真地以为加密了就安全。结果索引结构没设计好,服务器通过计数就能猜出关键词——这就是没达到IND-CKA安全。
选择关键词攻击(IND-CKA2)
比上一个更强:攻击者不仅能看密文,还能选关键词、获取对应的搜索令牌。它能不能区分两个它没查过的关键词?
这个定义更严格。我曾经在一个项目中因为用了确定性加密,导致攻击者能通过令牌频率推断出关键词热门度——这就是没防住。
这两个定义背后依赖一个核心工具:伪随机函数(PRF)。你想想看,如果令牌生成是纯随机的,服务器拿到两个不同令牌也没法关联,安全性自然高。但现实中PRF的密钥管理又是个坑...
一张图看懂SSE体系
两个安全定义的体系化对比
我把它们整理成表格,方便你对照着看:
| 对比维度 | IND-CKA(非自适应) | IND-CKA2(自适应) |
|---|---|---|
| 攻击者能力 | 仅看加密索引和密文 | 可获取任意关键词的令牌 |
| 挑战阶段 | 攻击者选 w0, w1,挑战加密结果 | 攻击者先查询,再选 w0, w1 |
| 泄露范围 | 索引大小、文档数量 | 索引大小 + 查询模式 |
| 达到难度 | 较低,可基于标准PRF实现 | 较高,需要更强的构造(如SSE-2) |
| 典型应用 | 静态数据集、一次性搜索 | 动态数据库、持续更新场景 |
嗯,到这里SSE基础就算打完了。我记得自己当年第一次看完这些定义后,跑去写了三个小时代码,结果发现生成写成了密钥复用——被大佬一顿批。你写代码时注意,每一对(关键词, 文档ID)组合都应该有独立的PRF输入,不然安全性直接从IND-CKA2掉到毫无安全性可言。