第1章 FPE与Tokenization的起源与应用场景
我在刚接触数据脱敏那几年,市面上主流方案要么是直接把数据库加密了,要么就是哈希加盐。但每次把加密后的字段贴到旧系统里,都会出问题——字段长度变了、格式乱了、索引失效……说白了就是“一加密就崩”。后来我才发现,业内早就有人在用两种更聪明的办法:格式保持加密(FPE)和Tokenization。这节课咱们就先聊聊它们是怎么来的,用在哪,以及为什么值得你花时间学。
1.1 为什么需要它们?数据泄露的痛点和合规要求
先看一张图,我尽量把它们的定位说清楚:
为什么会有这两个东西?我举个例子。十多年前我做电商平台,业务要求把信用卡号存在数据库里,但明文存肯定违规。我试过AES加密,一加密字段变成16字节,原来的16位卡号没法用,业务方直接炸毛。那时候我才理解——很多老系统根本接受不了格式变化。于是FPE和Tokenization开始被重视。
1.2 FPE的起源与核心思想
FPE(Format-Preserving Encryption)最早来自密码学家的一个小想法:能不能在加密时让输出跟输入长得一样?比如输入16位信用卡号,加密后也输出16位数字。这样数据库表结构不用改,索引不用重建,历史查询也能通。
我记得最初看到NIST在2016年发布了SP 800-38G标准,里面定义了FF1和FF3两种算法。说白了,就是把一段明文切分成字符集,然后在有限域上做Feistel网络迭代。这样做的好处是密文保持了原始格式,坏处是算法实现稍微复杂点,而且密钥泄漏就全完了。我之前在一个金融项目里用过FF1,踩过一个坑——FF1要求明文长度至少2,如果只加密1个字符就会报错。所以你要么补位,要么改用FF3。
1.3 Tokenization的起源与核心思想
Tokenization跟FPE完全不是一个路子。它不加密,而是替换。用一个无意义的令牌()代替原始敏感数据,令牌和原文的映射关系存在一个安全的库里。说白了,就是把“真钱”换成“游戏币”,你拿游戏币去玩,别人永远不知道你兜里有多少真钱。
Tokenization最早在支付行业普及,因为PCI DSS标准要求存储的卡号必须“不可读”。但很多公司又想保留卡号后四位做校验,于是一套完整的服务就起来了。我记得2017年帮一家金融服务公司做数据脱敏,他们用了Tokenization之后,监管来审计,直接拿出库的访问日志就过关了,效率很高。但要注意,Tokenization本身不具备加密强度,它依赖库的安全和访问控制。如果你的库被攻破,映射关系就全泄露了。
1.4 适用场景对比表
| 特性 | FPE | Tokenization |
|---|---|---|
| 保留格式 | 是(加密后格式完全一致) | 是(可以生成指定格式的) |
| 可逆性 | 可逆(用密钥解密) | 可逆(查映射表) |
| 存储影响 | 仅需密钥,无需额外存储 | 需要存储映射表,空间随数据量线性增长 |
| 安全性依赖 | 密码算法强度 + 密钥管理 | 映射表访问控制 + 网络隔离 |
| 性能 | 计算密集型(加解密较慢) | 查询密集型(映射表查找较快) |
| 典型场景 | 数据库字段加密、日志脱敏、兼容旧系统 | 支付数据保护、云原生数据脱敏、数据共享 |
你看这个表格,两边各有千秋。但有一点我说实话:很多人觉得Tokenization更简单,因为不用写加解密代码,调个API就行。但你想想看,一旦数据量上去,库的维护成本非常高。我见过一个案例,每天新增几亿条,半年后查询性能直接雪崩。而FPE虽然计算慢一点,但密钥管理成熟后,存储成本几乎为零。
1.5 我的个人经验与避坑提示
- 先确认字段格式是否稳定。假如字段里允许带空格或特殊符号,FPE的字符集定义就要仔细。我曾在某个项目中用FPE加密邮箱地址,结果域名部分因为大小写被业务方投诉……后来不得不加一个case-folding预处理。
- Tokenization不适合超大映射表。如果库无法全部放入内存,每次查询都读磁盘,延迟就会飙升。我记得有一次优化,把按范围分片到多个Redis集群,才算搞定。
- 两者可以一起用。比如:对身份证号用FPE加密,同时生成一个用于外部共享,这样解密权限只留给内部系统,而外部只有单向的。
- 我曾经踩过一个坑:在切换到生产环境前,忘记测试FPE加密后是否还能做字符串比较。因为FPE输出虽然格式一致,但密文本身改变了,如果有依赖原始值做排序、分组、join的查询,需要提前改SQL。