对称可搜索加密(SSE)基础

聊到可搜索加密,咱们得先搞明白一件事:为什么需要它?

我最早接触这个方向是在做一个医疗数据共享项目。数据放在云上,但医院方面死活不放心——病历明文存,谁敢啊?可全加密了,医生想搜个诊断记录怎么办?下载到本地解密再搜?几百万条记录,网络带宽根本扛不住。

这时候SSE就派上用场了。说白了,它让你能在加密数据上做搜索,而且能控制哪些信息泄露给服务器。

SSE的核心思想

对称可搜索加密,核心就两件事:

  • 加密索引:给每个关键词建一个加密的查找结构
  • 令牌搜索:用关键词生成一个令牌,服务器拿着令牌去查索引

你想想看,整个过程数据不动,动的只有加密后的索引和令牌。服务器始终看不到明文,但它能告诉你“这个关键词对应的文件在这儿”。

方案模型:三个角色,六个算法

任何SSE方案都跑不出下面这个三角模型。我在做性能分析时发现,很多人搞不清算法边界,结果实现出来安全性有问题。

常见坑:有些实现把Setup和KeyGen合并了,严格来说这不对。KeyGen只生成密钥,Setup还需要初始化数据结构和索引。
算法 输入 输出 我习惯这么理解
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 明文文档 打开保险柜看内容
实际项目中,BuildIndex 和 EncDoc 通常并行做。我个人习惯先建索引再加密,这样出问题容易排查。

核心流程:一次完整的搜索

咱们走一遍一个标准SSE搜索流程。假设你有10份病历文件,想搜所有含“高血压”这个词的。

  1. 初始化阶段(用户端):跑KeyGen(1^λ)得到一个密钥K。用K跑BuildIndex构建索引I,用K加密所有文档得到密文C。把I和C上传到服务器。
  2. 搜索阶段(用户端):输入“高血压”,跑(“高血压”, K)得到令牌τ。把τ发给服务器。
  3. 响应阶段(服务器端):服务器拿着τ查索引I,找到匹配文档ID列表,返回给用户。
  4. 解密阶段(用户端):用户用K解密对应的文档。

整个过程,服务器知道什么?它知道“有人查了某个关键词,找到了这些ID,ID对应的文件大小也知道了”。但它不知道关键词是什么,更不知道文件内容。

这就是SSE的威力——只泄露“搜索模式”和“访问模式”,不泄露数据本身。

安全定义:我到底要防什么?

这部分我以前看书总觉得绕,直到有一次被审计追问“你的方案能防什么攻击”才彻底搞明白。

SSE的安全性,主要有两个层次:

选择明文攻击(IND-CKA)

简单讲:攻击者能看到加密索引和密文,但看不到搜索令牌。它能不能区分两个已知明文对应的密文?

我记得第一次写SSE代码时,天真地以为加密了就安全。结果索引结构没设计好,服务器通过计数就能猜出关键词——这就是没达到IND-CKA安全。

选择关键词攻击(IND-CKA2)

比上一个更强:攻击者不仅能看密文,还能选关键词、获取对应的搜索令牌。它能不能区分两个它没查过的关键词?

这个定义更严格。我曾经在一个项目中因为用了确定性加密,导致攻击者能通过令牌频率推断出关键词热门度——这就是没防住。

关键区别:IND-CKA只防“只看不搜”的对手,IND-CKA2防“能搜但不能搜全部”的对手。实际部署中,我建议直接对标IND-CKA2,省得后期补漏洞。

这两个定义背后依赖一个核心工具:伪随机函数(PRF)。你想想看,如果令牌生成是纯随机的,服务器拿到两个不同令牌也没法关联,安全性自然高。但现实中PRF的密钥管理又是个坑...

一张图看懂SSE体系

SSE 对称可搜索加密知识体系 方案参与者 用户 · 服务器 · 攻击者 核心算法 KeyGen, , Search... 安全定义 IND-CKA · IND-CKA2 参与者角色 • 用户:数据拥有者 • 服务器:不可信存储 • 攻击者:窃听/分析 算法细节 • 密钥生成 (KeyGen) • 索引构建 (BuildIndex) • 搜索 (Search) 安全层次 • 只泄露搜索模式 • 自适应查询安全 • PRF不可区分性 SSE方案设计目标 效率 + 安全性 + 可证明安全 安全定义依赖于伪随机函数(PRF)的不可区分性
我的建议:学SSE不要一上来就啃安全定义。先把三个参与者和六个算法背熟,画个流程图在自己机器上跑一遍伪代码。安全定义那些形式化证明,等到真需要写或过审计时再深挖。

两个安全定义的体系化对比

我把它们整理成表格,方便你对照着看:

对比维度 IND-CKA(非自适应) IND-CKA2(自适应)
攻击者能力 仅看加密索引和密文 可获取任意关键词的令牌
挑战阶段 攻击者选 w0, w1,挑战加密结果 攻击者先查询,再选 w0, w1
泄露范围 索引大小、文档数量 索引大小 + 查询模式
达到难度 较低,可基于标准PRF实现 较高,需要更强的构造(如SSE-2)
典型应用 静态数据集、一次性搜索 动态数据库、持续更新场景

嗯,到这里SSE基础就算打完了。我记得自己当年第一次看完这些定义后,跑去写了三个小时代码,结果发现生成写成了密钥复用——被大佬一顿批。你写代码时注意,每一对(关键词, 文档ID)组合都应该有独立的PRF输入,不然安全性直接从IND-CKA2掉到毫无安全性可言。