FPE(Format Preserving Encryption) 格式保留加密是一种格式保持与明文相同的加密方式,通常用于数据脱敏。
例如对于敏感的数据信息,如电话号码(13位数字),FPE算法算法加依旧是13位数字,因此这种特性可以不用变更数据库中字段格式,有利于传播。
除了这些优点,还具有:
注:此段引用自《大数据时代下的隐私保护(三)》
更详细的介绍见:
由于JDK(JRE)未提供的FPE实现,我们需要借助BouncyCastle
库来完成工作,首先当然是引入Hutool:
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.12</version> </dependency>
再引入BouncyCastle
库
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.69</version> </dependency>
// 映射字符表,规定了明文和密文的字符范围 BasicAlphabetMapper numberMapper = new BasicAlphabetMapper("0123456789"); // 初始化 aes 密钥(随机),长度必须是16bytes、24bytes或32bytes byte[] keyBytes = RandomUtil.randomBytes(16); final FPE fpe = new FPE(FPE.FPEMode.FF1, keyBytes, numberMapper, // Tweak是为了解决因局部加密而导致结果冲突问题,通常情况下将数据的不可变部分作为Tweak,null则使用默认长度全是0的bytes null); String phone = "13534534567"; // 加密 String encrypt = fpe.encrypt(phone); // 解密 String decrypt = fpe.decrypt(encrypt);
// 映射字符表,规定了明文和密文的字符范围 BasicAlphabetMapper numberMapper = new BasicAlphabetMapper("0123456789"); // 初始化 aes 密钥(随机) byte[] keyBytes = RandomUtil.randomBytes(16); FPE fpe = new FPE(FPE.FPEMode.FF3_1, keyBytes, numberMapper, // 此处FF3规定tweak为56bit(即7bytes) new byte[7]); String phone = "13534534567"; // 加密 String encrypt = fpe.encrypt(phone); // 解密 String decrypt = fpe.decrypt(encrypt);
相比于AES等加密算法,FPE增加BasicAlphabetMapper
,即有限字母的字典表。
Alphabet:有限字母的字典表,并规定了输出密文的范围,例如对于手机号码而言,是十进制纯数字格式的,其Alphabet包括字符'0'-'9'。对于MAC地址而言,是十六进制数字格式,其Alphabet应该包括大写英文字母的'A'-'E'和数字'0'-'9'在内的十六个字母。
注:此段引用自《大数据时代下的隐私保护(三)》
除了FPE,也可以通过掩码屏蔽方式完成数据脱敏工作,如手机号13912341234 -> 139****1234,不过这种脱敏并不可逆。
掩码屏蔽同样可以借助hutool完成:
// 139****1234 DesensitizedUtil.desensitized("13912341234", DesensitizedUtil.DesensitizedType.MOBILE_PHONE)
两种方式对比如下:
|