3、非对称可搜索加密基础:PEKS原理、安全模型

说到可搜索加密,大家第一反应可能是前面讲的对称方案(SSE)。但真正到实际落地,你会发现 SS 有个硬伤 —— 密钥分发。你想想看,如果我用对称加密把文件存到云端,想授权给另一个人搜索,就得把密钥也给他。那这个人就能解密所有数据了,根本做不到细粒度控制。

嗯,这就是 PEKS(公钥可搜索加密)登场的地方。它用公钥加密关键词,私钥生成陷门,完美分离了加密能力和搜索能力。我记得 2004 年 Boneh 那篇刚出来时,我在实验室里看了三遍才完全搞懂 …… 说白了,它把非对称加密的多用户特性和可搜索需求捏在了一起。

3.1 PEKS 到底长什么样?

PEKS 的核心是一个“四元组”算法,我习惯用下面这个表格来记忆:

算法输入输出一句话解释
KeyGen安全参数公钥 PK, 私钥 SK生成密钥对,跟普通非对称一样
PEKSPK, 关键词 w密文 Cw任何人用公钥加密关键词
TrapdoorSK, 关键词 w'陷门 Tw'私钥持有者生成搜索凭证
TestPK, Cw, Tw'0 或 1服务器判断 w 是否等于 w'

我在项目中第一次实现 Test 时,犯了很蠢的错误:双线性对配对的顺序写反了。结果怎么跑都是 0,debug 了两天 …… 所以后面我会单独放一个陷阱提示。

关键点: Test 算法只能做“是/否”判断,它看不到关键词本身。这就保证了即使服务器有恶意,也无法从密文或陷门里恢复出原始关键词。

3.2 具体的构造思路(基于双线性对)

大多数 PEKS 方案都依赖双线性对(Pairing),比如 Boneh-Franklin 那类。数学上不展开,你只需要知道:

  • 双线性映射 e 允许我们在两个加密数据上做“乘法”比较。
  • PEKS 密文 = 对关键词哈希后,用公钥“包裹”一下。
  • 陷门 = 用私钥对搜索关键词签名。
  • Test 时,e(密文里的某部分, 陷门) 等于另一个值,则匹配。

我曾经尝试过在 openssl 里硬嗑双线性对的代码,那叫一个痛苦。后来换用 PBC 库才舒服不少。这里给个小建议:选库时注意配对类型(Type A / Type F),它们的速度和曲线安全级别差很多。

# 伪代码示意(Python 风格)
def peks(pk, keyword):
    r = random()
    # C = [g^r, H(keyword)^r]  简化的结构
    return (pow(g, r), pow(H(keyword), r))

def trapdoor(sk, keyword):
    return pow(H(keyword), sk)   # 简单版陷门

def test(pk, cipher, trap):
    # 校验 e(C[0], trap) == e(C[1], g)
    return (pairing(cipher[0], trap) == pairing(cipher[1], g))
避坑指南: 我曾在测试向量里混进一个单位元,结果所有 Test 都返回 1 …… 检查后发现关键词哈希没有映射到正确群。哈希到曲线这一步千万别省。

3.3 安全模型:CKA 与适应性

PEKS 的安全模型核心是“不可区分性”。你说它为什么安全?因为攻击者就算拿到两个关键词的密文,也分不清哪个对应哪个。这跟语义安全是一个道理。

学术界通常分两个等级:

  • CKA-1(非自适应):攻击者在拿到陷门之前,只能看到密文,不能主动查询。
  • CKA-2(自适应):攻击者可以自适应地查询任意关键词的陷门,然后挑战。

别小看这个区分。我几年前评审一个方案时,发现它只在 CKA-1 下安全,作者却说“足够抵御实际攻击”。但真实场景里,用户往往会在知道一些陷门之后再去加密新数据,这就相当于自适应攻击。所以 我建议 落地时至少要求 CKA-2 安全。

特性SSE(对称)PEKS(非对称)
密钥管理需预共享密钥公钥公开,私钥自持
安全性假设伪随机函数+安全信道双线性 Diffie-Hellman 假设
搜索效率极高(哈希查表)较低(双线性对运算)
典型安全模型CKA-2(自适应)PEKS-IND-CKA-2
特别提醒: 陷门相同意味着两个关键词相同。如果服务器收集到同一个关键词的多个陷门,虽然不能知道关键词是啥,但能知道它们相等 —— 这就是“陷门链接性”。高安全场景下,你需要用“无陷门链接”的变体方案(比如通过随机数盐化)。

3.4 整体的逻辑流程

下面这张图应该能帮你串起来:

PEKS 核心流程 数据拥有者 公钥 PK + 关键词 w PEKS 加密 密文 Cw 搜索者 私钥 SK + 关键词 w' Trapdoor Tw' 云服务器 Test(Cw, Tw') 匹配? 服务器可以存储所有关键词密文,但只有拥有对应陷门才能执行 Test。 即使服务器串通其他人,也无法从密文中提取原始关键词。

3.5 性能与现实的“坑”

PEKS 理论很完美,但实际集成时我踩过几个坑:

  • 双线性对太慢。 一次配对大约在毫秒级,如果数据量上万,搜索延迟就是几秒。后来我用预计算 + 缓存优化,把重复的配对结果存下来,速度提升了 3 倍。
  • 关键词空间有限。 标准的 PEKS 只支持精确匹配。你想做模糊搜索或范围搜索?对不起,得用更复杂的方案(比如可搜索加密 + 保序加密),但那就不是纯粹的 PEKS 了。
  • 陷门重放风险。 如果服务器记住了某个陷门,它可以在任何时间重复搜索。我当时的做法是在陷门里绑定时间戳,让服务器每次验证时检查有效期。
个人经验: 我建议在原型阶段先用椭圆曲线上的双线性对(Type A),跑通流程后再切到更快的 Type F。另外,千万不要自己实现双线性对核心,直接用 MIRACL 或 RELIC 这类成熟库。

最后想强调一点:PEKS 并不是银弹。如果你的业务是一对一搜索,对称方案 SSE 往往更快更简单;如果你需要多用户授权或第三方审计,PEKS 才有优势。选择哪条路,取决于你真正面临的威胁模型。