格式保留加密(FPE)在加密数据的同时保持相同格式——信用卡号仍然是 16 位数字,社会安全号码仍然是 XXX-XX-XXXX 格式。当您需要加密数据但应用程序、数据库或支付处理商要求特定格式时,这至关重要。
什么是格式保留加密?
传统加密算法如 AES 产生的密文是二进制格式,与原始明文完全不同。如果您加密信用卡号 4111111111111111,会得到类似 a3f2b8c1d4e5... 的内容——长度和格式完全不同的十六进制字符串。
FPE 解决了这个问题。它接受特定格式的输入,并产生相同格式的输出:
输入: 4111111111111111 (16 位数字)
输出: 7392815640293847 (仍然是 16 位数字)
加密后的值是一个有效的信用卡号,可以通过 Luhn 校验,适合存储在数据库列中,并能被支付系统处理——同时具有密码学安全性。
FF1 和 FF3-1 算法
NIST 在 SP 800-38G 中标准化了两种 FPE 算法:
FF1(基于 Feistel 的格式保留加密)
- 使用 10 轮非平衡 Feistel 网络
- 支持任意进制(基数 2 到 2^16)
- 最小输入长度:6 个字符(使用默认 tweak)
- 比 FF3-1 更灵活但略慢
- 推荐用于大多数场景
FF3-1(FF3 修订版)
- 使用 8 轮平衡 Feistel 网络
- 同样支持任意进制
- 最小输入长度:8 个字符(使用默认 tweak)
- 更快但长度限制更严格
- 修订版解决了 2017 年对原始 FF3 的攻击问题
两种算法都需要:
- 对称密钥(AES 密钥:128、192 或 256 位)
- Tweak(额外输入,使相同明文产生不同密文)
理解进制(Radix)
进制是字符集使用的数制基数:
| 进制 | 字符集 | 示例用例 |
|---|---|---|
| 2 | 0, 1 | 二进制字符串 |
| 10 | 0-9 | 信用卡号、社会安全号码 |
| 26 | A-Z | 类名称的令牌 |
| 36 | 0-9, A-Z | 字母数字标识符 |
| 62 | 0-9, A-Z, a-z | 区分大小写的 ID |
对于信用卡号,进制为 10(数字 0-9)。对于字母数字数据,进制为 36 或 62。
FPE 工作原理
FPE 使用 Feistel 网络结构:
1. 将输入分为左半部分(L)和右半部分(R)
2. 每轮:
a. 使用轮密钥 + tweak 计算轮函数 F
b. 将结果与另一半进行 XOR 运算
c. 交换两半
3. 重新组合产生相同格式的输出
轮密钥从主密钥派生,tweak 确保相同明文在不同上下文中加密为不同密文(例如,不同卡号可以使用不同的 tweak)。
Tweak
Tweak 是 FPE 的重要组成部分:
- 它的作用类似于初始化向量(IV),但更灵活
- 相同密钥 + 不同 tweak = 不同密文
- 常见 tweak 来源:数据库记录 ID、交易 ID 或空字符串
- 不要求保密——可以与密文一起存储
Encrypt("4111111111111111", key, tweak="order123") → "7392815640293847"
Encrypt("4111111111111111", key, tweak="order456") → "2958471036582914"
令牌化 vs 加密
FPE 经常与令牌化混淆,但它们是不同的:
| 方面 | FPE | 令牌化 |
|---|---|---|
| 可逆性 | 是(需要密钥) | 取决于实现 |
| 密码学性质 | 是 | 否(查找表) |
| 需要密钥 | 是 | 否(需要数据库) |
| 格式保留 | 是 | 是 |
| 标准化 | NIST SP 800-38G | 无标准 |
许多支付系统使用混合方法:FPE 用于实际加密,令牌库用于额外的安全层。
PCI DSS 合规
FPE 在 PCI DSS(支付卡行业数据安全标准)中发挥重要作用:
为什么 FPE 有助于 PCI DSS
- 要求 3.4:在存储任何地方使 PAN 不可读——FPE 满足此要求
- 缩小范围:如果加密足够强,FPE 加密的数据可以排除在 PCI 范围之外
- 格式兼容性:现有系统无需修改架构即可处理加密的 PAN
- Luhn 有效输出:使用进制 10 的 FF1 可以产生 Luhn 有效的加密 PAN
PCI DSS 要求
- 使用强密码学(至少 AES-128)
- 使用 HSM 或等效密钥管理系统保护密钥
- 记录密钥管理程序
- 定期轮换密钥
实际应用场景
信用卡处理
原始 PAN: 4111111111111111
加密 PAN: 7392815640293847 (有效的 16 位数字)
数据库: 相同的 VARCHAR(16) 列,无需架构更改
医疗数据(HIPAA)
加密患者 ID、社会安全号码和医疗记录号码,同时保持数据库兼容性和格式验证规则。
遗留系统集成
当您无法修改数据库架构或应用程序逻辑来处理二进制密文时,FPE 让您透明地加密数据。
令牌化替代方案
用密码学 FPE 替换脆弱的令牌库——解密不需要数据库查找,只需要密钥。
选择 FF1 还是 FF3-1
| 标准 | FF1 | FF3-1 |
|---|---|---|
| 最小长度 | 6 个字符 | 8 个字符 |
| 速度 | 较慢 | 较快 |
| 安全边际 | 较高 | 良好(修订版) |
| 建议 | 默认选择 | 速度重要且输入 ≥ 8 个字符时 |
对于大多数应用,推荐使用 FF1,因为它有更大的安全边际和更灵活的长度要求。
实现注意事项
密钥管理
- 使用 AES-128 或 AES-256 密钥
- 在 HSM 或安全密钥管理系统中存储密钥
- 定期轮换密钥,但需要计划重新加密
Tweak 策略
- 每记录 tweak:使用数据库记录 ID——提供最大差异化
- 静态 tweak:更简单但安全差异化较少
- 空 tweak:最简单,但相同明文产生相同密文
长度约束
FF1 和 FF3-1 基于进制和密钥大小有最小和最大长度要求。对于进制 10(数字):
- FF1:最小 6 位数字
- FF3-1:最小 8 位数字
- 最大长度取决于密钥大小(大约 2^32 个块)
在线工具
使用 FPE 加密工具:
- 使用 FF1 和 FF3-1 算法进行加密和解密
- 测试不同的进制值(10、26、36、62)
- 自定义 tweak 以适应不同安全上下文
- 验证信用卡号的 Luhn 兼容输出
- 理解格式保留加密在实践中的工作原理
所有处理都在浏览器中进行——您的密钥和数据永远不会离开您的设备。