FPE安全性定义:安全目标与安全性模型
聊FPE的安全性,我们得先想清楚一个问题:到底什么才算“安全”? 在传统加密里,我们说一个方案安全,通常指攻击者猜不出明文。但FPE有个特殊之处——输出格式跟输入一模一样,而且明文空间往往特别小(比如身份证号只有18位数字,信用卡号16位数字)。空间小了,攻击者枚举的可能性就大了,所以它的安全模型跟常规分组密码不太一样。
我十年前刚开始接触FPE的时候,一直用AES的那套安全定义去套,结果做方案评审时被专家怼了。他们问我:“你明文空间才100亿种可能,IND-CPA有意义吗?” 嗯,那以后我就明白了——FPE的安全定义必须结合格式特征来重新审视。
3.1 安全目标:不可区分性 vs 消息恢复安全性
FPE的安全目标通常分两大类:不可区分性(Indistinguishability, IND) 和 消息恢复安全性(Message Recovery, MR)。说白了,一个防的是“猜出哪个明文”,另一个防的是“完全恢复明文”。
| 安全目标 | 核心思想 | 适用场景 | 常见问题 |
|---|---|---|---|
| 不可区分性(IND) | 攻击者无法区分两个等长明文的密文 | 需要保护数据语义的场景(如加密后的身份证号仍能被模糊匹配) | 明文空间太小时,IND可能被“单个区组”攻击破坏 |
| 消息恢复安全性(MR) | 攻击者无法从密文恢复出明文(哪怕空间很小) | 高安全需求场景(如金融交易摘要) | MR通常比IND更弱,容易满足,但有时不够用 |
你想想看,如果明文空间只有1000种可能,攻击者拿到一个密文,直接枚举所有明文加密比对就完了——这跟IND没关系,算的是MR。所以我在实际选型时,优先看明文空间大小:超过2^30时可以用IND-CPA;小于2^20就得考虑MR-CPA或更强的CCA。
注意: 别把IND和MR搞混。IND要求的是“密文不泄露明文分布信息”,MR只要求“无法恢复完整明文”。如果明文是邮编(6位数字),IND可能被侧信道利用,但MR依然成立。我见过有人用MR标准去审计信用卡加密方案,结果漏了格式推断攻击。
3.2 安全性模型:选择明文攻击与选择密文攻击
安全模型定义了攻击者拥有的能力。FPE领域最常见的是选择明文攻击(CPA) 和 选择密文攻击(CCA)。这两模型跟常规加密没本质区别,但FPE里有个坑——CCA模型下的解密查询可能会泄露格式特征。
3.2.1 选择明文攻击(CPA)
CPA就是攻击者可以自由选择任意明文,获得对应的密文。然后它没法直接解密密文。这模型在FPE里已经很常见了,比如FF1、FF3都能达到IND-CPA。但要注意:FF3-1之前被曝出在明文空间小于2^30时有安全缺陷,就是CPA模型下被攻破的。
- 优点: 实现简单,性能好(大多数FPE方案都能支持)。
- 缺点: 无法抵抗密文篡改攻击。攻击者改动一个数字,解密后可能得到另一个合法明文,造成业务逻辑错误。
- 我建议: 如果系统允许用户输入密文(比如解密API暴露给前端),千万不要只用CPA,否则你会被打得很惨。
3.2.2 选择密文攻击(CCA)
CCA模型允许攻击者除了加密查询外,还可以解密任意密文(除了挑战密文)。这听起来更强大,现实中也更符合攻击者场景——比如一个能调用解密接口的恶意用户。我曾经部署过一个支付系统,用的就是IND-CCA的FPE方案(基于FF1 + HPfe模式)。为什么?因为攻击者可能提交篡改过的加密卡号,如果不做CCA保护,解密出非法格式的明文后,系统可能会泄露“这个卡号存在”的信息。
核心差异: CCA比CPA多了解密模拟能力。在FPE中,解密查询可以用于判别“某密文是否对应合法格式的明文”,从而辅助区分性攻击。所以IND-CCA标准通常比IND-CPA强得多。
3.3 安全模型组合与选择指南
实际应用中,我们会把安全目标和攻击模型组合起来,形成IND-CPA、IND-CCA、MR-CPA、MR-CCA 等标准。下面这张图展示了它们之间的关系和适用场景:
我的一点经验: 别上来就追求最高强度。IND-CCA方案通常需要额外的模式(比如FPE + 认证标签),性能会比IND-CPA下降20-40%。如果系统里密文不会暴露给第三方(比如只在数据库字段加密),IND-CPA就够用了。但如果有API接口让用户传入密文、系统自动解密,那必须上IND-CCA。
3.4 常见陷阱与避坑指南
讲完理论,说两个我踩过的坑:
- 明文空间过小时,IND-CPA定义失效。 比如加密一个性别字段(0或1)——攻击者看到密文,直接加密两个可能明文就能区分,IND-CPA这里没有意义。这时候应该用MR-CPA或者干脆换用保序加密。
- 在CCA模型中忘记约束“修改密文后的格式检查”。 我曾经实现过一个FPE方案,解密时只验证格式合法就返回,没做认证。结果攻击者通过修改末位数字,得到不同的合法明文,再结合业务异常信息,硬是把用户ID猜出来了。
所以我的经验是:FPE安全模型的选择,三分看标准,七分看业务场景。拿到一个需求,先问三个问题——①明文空间多大?②密文会暴露给第三方吗?③对方能不能发起解密查询?答案出来了,模型自然就定了。
| 场景 | 推荐模型 | 为什么 |
|---|---|---|
| 数据库字段加密,不外泄 | IND-CPA | 攻击面仅限存储侧,CPA够用 |
| 公开展示部分密文(如卡号后四位加密) | IND-CPA | 展示侧不提供解密能力 |
| 提供解密API,允许用户传入任意密文 | IND-CCA | 防密文篡改和格式探测 |
| 明文空间 < 2^20,且安全需求一般 | MR-CPA | IND在极小区间失去意义 |
| 极高安全场景(如军事、金融核心) | IND-CCA+ | 额外的认证层防止任意变形 |
说白了,FPE的安全定义不是拿来炫技的,而是帮你选对方案、避开雷区。日常代码里写FPE算法时,多想想“我这里到底在防什么攻击”,比盲目套IND-CCA要实在得多。