一、FF1 算法简介:为什么需要它?

1.1 从“格式保留”这个怪需求说起

做密码学的人都知道,AES、DES 这类经典算法,加密后输出的是乱码。但实际业务中,很多时候你没法用乱码。

举个例子:你手上有 16 位信用卡卡号,数据库要存加密版本。如果用 AES 加密,出来是 32 字节的二进制串,你的表结构得大改,索引全废,业务接口也得重写。这不现实。

所以就有了格式保留加密(Format-Preserving Encryption,FPE)。说白了,就是加密后数据格式跟原来一模一样——信用卡号加密完还是 16 位数字,身份证号加密完还是 18 位带“X”的串。

核心目标:密文在语义格式上与明文相同,但内容在计算上不可区分。

1.2 FF1 的标准化之路

我最早接触 FPE 是在 2010 年左右,那时候各家实现都是自己写的,调个参数就能整出兼容性问题。

后来美国国家标准与技术研究院(NIST)看不下去了。他们在 2016 年正式发布了 SP 800-38G,把 FF1 和 FF3 定为标准算法。其中 FF1 是主力。

为什么要叫“FF”?其实是“Feistel-based FPE”的意思。FF1 用了七轮 Feistel 网络,轮函数里塞的是 AES 或 TDES。

我的一个经验:如果你在合规场景(比如 PCI DSS、GDPR 敏感字段脱敏)里做 FPE,FF1 几乎是唯一的选择。因为它是 NIST 批准的,能过审计。

1.3 标准规范有哪些?

搞 FF1 用的主要参考文档就这三份:

文档 发布机构 说明
NIST SP 800-38G NIST FF1 和 FF3 的正式定义,必读
ISO/IEC 24727-3 ISO 身份认证领域对 FF1 的引用
ANSI X9.119 ANSI 金融支付领域的 FPE 规范

嗯,我建议你在做项目前,先把 SP 800-38G 的参数字段 过一遍。因为里面有些边界条件,比如 radix 的取值范围、minlen 和 maxlen 的约束,一旦踩坑就是兼容性问题。

曾经有同事把 radix 设为 36(字母+数字)然后传了个全小写字符串做测试,结果生产环境里数据带了大写字母,加密长度算出来不对,直接崩溃。所以啊,字符集和 radix 必须严格对应。

1.4 FF1 的参数结构(知识体系图)

下面的 SVG 图把 FF1 的核心参数和标准来源串了一下。你仔细看,一层一层往下拆,就是整个算法配置的主线。

FF1 算法参数配置与标准来源 标准来源:NIST SP 800-38G 密钥与轮函数(AES/TDES) Feistel 网络(7 轮) 字符集与 radix Key / Tweak KeyLen: 128/192/256 bit 块长度 B B = ceil(u/2) / v minlen / maxlen 2 ≤ len ≤ 2^32 radix 2 ≤ radix ≤ 2^16 输出:与明文等长、格式相同的密文 注:radix 和 minlen/maxlen 之间需要满足 NIST 不等式约束,否则解密可能失败 我在项目里一般先写个参数校验函数再开始调算法

1.5 标准化流程总结:模式级与元素级

我习惯把 FF1 的参数配置分成两层:模式级配置 和 元素级配置。这样做的好处是——你在做系统集成时,可以先固定模式级,然后把元素级暴露给业务方。

  • 模式级:密钥、轮函数选择、Tweak 长度。一个系统通常只定一套。
  • 元素级:radix、minlen、maxlen、字符集映射。每类敏感字段各一套。

一个小技巧:Tweak 别用固定值。你可以把表的行 ID 或时间戳放进去做分隔,这样就算两条内容完全相同的明文,加密出来结果也不一样——嗯,你想得到,这是语义安全的基本要求。

1.6 我踩过的坑:FF1 的版本兼容

说实话,FF1 算法在 2016 年之后其实有过一次隐性修订。NIST 在 2019 年发布了 SP 800-38G Rev. 1,把 FF1 的 numRounds 从“至少 7 轮”改成了“精确 7 轮”。

为什么改?因为早期有些实现偷懒用了 6 轮,结果安全性评估没通过。我遇到过一家第三方加密机,固件里写的 FF1 用了 8 轮,跟标准 7 轮互解不了……后来才知道是他们自己拍脑袋加的。

教训:跨系统做 FF1 对接时,必须两边拿同一份参考实现(比如 NIST 官方的 FF1 Python 测试向量)互相验证一遍。否则联调时才暴露兼容问题,比重新改表结构还痛苦。

1.7 现在你该怎么用 FF1?

  1. 确定使用场景:数据库脱敏、日志脱敏、API 响应字段加密
  2. 选择底层加密算法:多数场景用 AES-128,合规要求高的用 AES-256
  3. 定义 radix 和字符集:数字就用 radix 10,数字+字母就用 radix 36
  4. 设定 Tweak:至少 8 字节,建议结合业务主键
  5. 测试向量验证:NIST 官网有供下载的 SP 800-38G 测试用例

这一章我就给你把 FF1 的历史、标准、核心参数和常见坑过完了。记得把 SVN 图上那几项参数记清楚——配置 FF1 其实就是把这些参数填对、让它们之间不打架。