您的位置:  首页 > 技术 > java语言 > 正文

使用Hutool在Java中实现FPE(Format Preserving Encryption)格式保留加密算法

2021-09-10 10:00 https://my.oschina.net/looly/blog/5254409 looly 次阅读 条评论

FPE介绍

FPE(Format Preserving Encryption) 格式保留加密是一种格式保持与明文相同的加密方式,通常用于数据脱敏。

例如对于敏感的数据信息,如电话号码(13位数字),FPE算法算法加依旧是13位数字,因此这种特性可以不用变更数据库中字段格式,有利于传播。

除了这些优点,还具有:

  • 数据长度不变。加密前长度是N,加密后长度仍然是N
  • 数据类型不变,加密前是数字类型,加密后仍然是数字类型。
  • 加密过程可逆,加密后的数据可以通过密钥解密还原原始数据。

注:此段引用自《大数据时代下的隐私保护(三)》

更详细的介绍见:

算法实现

由于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>

FF1算法实现

// 映射字符表,规定了明文和密文的字符范围

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);

FF3算法实现

// 映射字符表,规定了明文和密文的字符范围

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)

两种方式对比如下:

  • 掩码:不可逆,长度保持,字符不保持
  • FPE : 可逆, 长度保持,字符保持
  • 0
    感动
  • 0
    路过
  • 0
    高兴
  • 0
    难过
  • 0
    搞笑
  • 0
    无聊
  • 0
    愤怒
  • 0
    同情
热度排行
友情链接