3、FPE核心概念详解:数据格式保留、字符集、半径、tweak
做PAN保护这么多年,我见过不少团队在选加密方案时卡住。原因很简单——传统加密一上,数据格式就变了,业务系统根本接不住。FPE能解决这个问题,靠的就是四个核心概念:数据格式保留、字符集、半径、tweak。
说白了,这四个东西就是FPE的"四根柱子"。你理解透了,后面选算法、调参数、做工程落地,心里就有底。我一个个拆开来讲。
3.1 数据格式保留——FPE的立身之本
FPE最吸引人的地方,就是加密后数据格式不变。拿PAN来说,16位数字的卡号,加密后仍然是16位数字。不会多一位,不会少一位,更不会冒出字母或特殊符号。
为什么会这样?因为FPE在加密过程中,把明文空间和密文空间映射到同一个格式范围内。你输入的是16位数字,输出也必须是16位数字。这不是巧合,是算法设计时就定死的。
格式保留的本质:密文与明文的字符集、长度、结构完全一致。对下游系统来说,它"看起来"就是原来的数据。
我记得最早做PAN保护时,业务方最担心的就是:"加密后卡号变长了怎么办?数据库字段要不要改?"我告诉他们,FPE是格式保留的,长度、类型一个都不变。他们当场松了口气。
这个特性在金融系统里特别吃香。你想想看,核心交易系统、风控规则、对账平台,哪个不是基于PAN格式写的逻辑?格式一变,改造成本能吓死人。
- 数据库字段不用动——原来是varchar(16),加密后还是varchar(16)
- 索引不用重建——格式保留意味着索引结构不受影响
- 业务逻辑零修改——正则校验、长度判断、格式化展示,全部照旧
3.2 字符集——加密的"字母表"
字符集决定了加密时能用哪些字符。对PAN来说,字符集就是纯数字——0-9一共10个字符。但FPE不只限于数字,你可以自定义字符集。
我在项目中踩过一个坑。当时要加密一个优惠券码,业务要求输出只包含大写字母和数字,但不能包含字母'I'和'O'(怕用户混淆成1和0)。我一开始没在意,直接把标准字母数字集扔进去了,结果测试时发现生成了带I和O的券码。
后来怎么解决的?我自定义了一个字符集:ABCDEFGHJKLMNPQRSTUVWXYZ0123456789,把I和O去掉,半径变成34。嗯,这才是正确的做法。
字符集选择原则:必须覆盖业务允许的所有字符,一个都不能少;同时不能包含业务禁止的字符,一个都不能多。
常见字符集类型:
| 字符集类型 | 包含字符 | 半径 | 典型应用场景 |
|---|---|---|---|
| 纯数字 | 0-9 | 10 | PAN、身份证号、手机号 |
| 大写字母 | A-Z | 26 | 车牌号、航班号 |
| 字母数字 | 0-9, A-Z | 36 | 订单号、优惠券码 |
| 小写字母 | a-z | 26 | 用户名、短链接 |
| 全字母 | A-Z, a-z | 52 | 密钥、令牌 |
3.3 半径——字符集的"大小"
半径其实就是字符集的元素个数。数字集半径=10,字母数字集半径=36。就这么简单?嗯,但它的影响远不止数字大小。
半径直接影响两个东西:安全强度和计算性能。
- 半径越大,安全余量越足——同样的密钥长度下,更大的半径意味着更大的明文空间,暴力破解难度更高
- 半径越大,计算开销也越大——FF1算法里很多运算都和半径挂钩,半径大了循环次数和中间计算量都会涨
我建议大家在选半径时别贪大。满足业务需求就行。纯数字场景半径就是10,硬要扩成36,安全增益有限,性能损失却不小。得不偿失。
// 半径计算示例
// 纯数字PAN:16位数字,半径=10
int radix = 10;
// 字母数字优惠券码:12位,字符集=0-9+A-Z,半径=36
int radix = 36;
// 自定义字符集:去掉I和O,半径=34
String chars = "ABCDEFGHJKLMNPQRSTUVWXYZ0123456789";
int radix = chars.length();
注意:半径必须与字符集严格对应。字符集有10个字符,半径就是10。多一个字符或少一个字符,半径都要同步改。否则加解密会直接失败。
3.4 Tweak——加密的"盐"
Tweak是FPE里一个容易被忽视但极其重要的参数。它类似于分组加密中的IV(初始化向量),但又不完全一样。
Tweak的作用是什么?给同样的明文加密出不同的密文。没有tweak的话,同一个PAN每次加密结果都一样——那跟没加密有什么区别?攻击者看到两个相同的密文,就能推断出是同一个卡号。
我曾经因为tweak使用不当,差点出事故。当时在测试环境里,我图省事,把tweak设成了一个固定值。结果所有加密结果都是确定的——同一个PAN在不同时间、不同交易里,密文完全一样。幸好是在测试阶段发现的,要是上了生产,等于给攻击者送了一个"卡号指纹库"。
Tweak的正确用法:每次加密使用不同的tweak。常见的tweak来源包括:
- 交易时间戳——到毫秒级别,重复概率极低
- 交易流水号——全局唯一,天然适合做tweak
- PAN的部分位——搭配其他信息一起用
- 计数器——单调递增,保证每次不同
但要注意,tweak不是密钥。它不需要保密,甚至可以随密文一起传输。它的核心价值是增加加密结果的多样性。
Tweak vs IV的关键区别:IV在解密时需要从密文中提取或单独传输,而tweak的生成规则是加解密双方事先约定好的。解密方只要知道tweak的生成逻辑,就能还原出同样的tweak。
3.5 核心概念关系图谱
这四个概念不是孤立的。它们之间的关系,我画了一张图帮你串起来。
画这张图的时候,我想强调一个点:格式保留是目标,字符集和半径是约束,tweak是变量。没有格式保留,FPE就不叫FPE。没有字符集和半径,加密就不知道往哪个空间映射。没有tweak,加密结果就缺乏随机性,安全大打折扣。
你把这个关系理清了,后面学FF1、FF3算法时就会发现——算法的每一步都在围绕这四个概念展开。字符集决定半径,半径决定分组方式,tweak参与轮函数计算,格式保留约束输出映射。一环扣一环。
工程落地小技巧:做PAN保护时,先确认业务要求的格式约束(长度、字符类型),再据此确定字符集和半径,最后设计tweak生成策略。按这个顺序走,不容易出错。
这四个概念掌握了,FPE的骨架你就搭起来了。后面我会讲具体的算法实现和代码编写,那时候你会回来感谢现在认真理解概念的自己。嗯,先消化这些吧。