数据脱敏的方式

108 阅读7分钟

1、了解数据脱敏之前,先了解开发,测试,生产环境的区别。

1.1开发环境

程序员进行代码的编写、调试和初步实现的环境。

数据特点:

  • 使用模拟数据

典型工具:

  • 开发工具:VS Code、IntelliJ IDEA、PyCharm 等。
  • 本地服务:MySQL、PostgreSQL(单机版)、Redis、Docker(用于轻量级容器化开发)。

1.2测试环境

用于验证代码功能、性能、兼容性等质量指标的独立环境,需要尽可能模拟生产环境的配置。

数据特点:

  • 使用脱敏后的真实数据。
  • 数据需要定期备份,但允许在测试中被修改或删除。

典型工具:

  • 测试工具:Jira(缺陷管理)、Postman(接口测试)、Selenium(自动化测试)、JMeter(性能测试)。
  • 环境管理:Kubernetes(容器编排)、Jenkins(持续集成 / 部署)。

1.3生产环境

生产环境是面向用户提供正式服务的环境,是系统的真实运行环境,直接关系到业务的稳定性和用户体验。

核心特点

  1. 功能定位

    • 正式服务提供:运行稳定的代码版本,处理真实用户请求和业务数据(如支付、交易、数据存储)。
    • 高可用性要求:需保障 7×24 小时不间断服务,避免单点故障。
  2. 配置要求

    • 硬件配置:高性能服务器或云主机,支持集群部署、负载均衡和故障转移(如多节点分布式架构)。

    • 软件环境:

      • 采用稳定版本的操作系统、中间件和数据库(避免使用开发版或测试版软件)。
      • 部署监控工具(如 Prometheus、Zabbix)、日志分析系统(如 ELK Stack)和安全防护措施(如 WAF、防火墙)。
  3. 数据特点

    • 存储真实业务数据,数据安全性和完整性至关重要(需定期备份和容灾恢复)。
    • 严格禁止直接修改生产数据,操作需通过应用层接口或审批流程执行。
  4. 访问权限

    • 仅限运维团队和授权人员访问,且需通过多重身份验证(如 VPN + 二次认证)。
    • 公网可直接访问(如 Web 服务),但需通过安全组、SSL 证书等确保通信安全。
  5. 典型工具

    • 运维工具:Ansible(配置管理)、Kubernetes(容器编排)、Docker(容器化部署)。
    • 安全工具:Nessus(漏洞扫描)、OWASP ZAP(安全测试)。

2、因为测试环境的安全性是低于生产环境的,所以我们测试的时候要保证数据的隔离防止数据的泄漏。

有以下6种常见的数据脱敏方案

2.1方案一:字符串替换

技术原理:通过正则表达式对部分字符串进行部分替换

public class StringMasker {  
  *// 手机号脱敏:13812345678 → 1385678*  
  public static String maskMobile(String mobile) {  
    return mobile.replaceAll("(\d{3})\d{4}(\d{4})", "$1****$2");  
  }  
​
  *// 身份证脱敏:110101199003077777 → 1101********7777*  
  public static String maskIdCard(String idCard) {  
    if (idCard.length() == 18) {  
      return idCard.replaceAll("(\d{4})\d{10}(\w{4})", "$1****$2");  
    }  
    return idCard; *// 处理15位旧身份证*  
  }   
}

使用正则表达式将关键字替换成*

适用场景:

image.png

优缺点分析:

  • 优点:实现简单、性能高(时间复杂度是O(n))

  • 缺点:

    • 无法恢复原始数据

    • 正则表达式需要考虑多国数据格式差异(例如美国和中国的手机号的长度以及规则都不同)

    • 存在模式被破解风险(当攻击者知道替换的模式,就可以进行撞库攻击结合多种社会手段从而获取完整数据,导致数据泄露)

      • 动态脱敏手段:每次替换位置随机、使用不同符号进行替换。
      • 不可逆脱敏:使用哈希、加密、令牌化等技术,确保脱敏后数据无法反向还原。

2.2方案二:加密算法

加密算法选型:

  • 对称加密:

    • 代表算法:AES
    • 特点:加解密速度快,密钥管理复杂
    • 适用场景:支付信息存储
  • 非对称加密:

    • 代表算法:RSA
    • 特点:速度慢,安全性高
    • 适用场景:密钥交换
  • 国密算法:

    • 代表算法:SM4
    • 特点:符合国家标准
    • 适用场景:政府/金融系统
public class AESEncryptor {  
    privatestaticfinal String ALGORITHM"AES/GCM/NoPadding";  
    privatestaticfinalint TAG_LENGTH128; // 认证标签长度  
​
    public static String encrypt(String plaintext, SecretKey key) {  
        byte[] iv = newbyte[12]; // GCM推荐12字节IV  
        SecureRandom random = new SecureRandom();  
        random.nextBytes(iv);  
​
        Cipher cipher = Cipher.getInstance(ALGORITHM);  
        cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(TAG_LENGTH, iv));  
​
        byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));  
        return Base64.getEncoder().encodeToString(iv) + ":" +  
               Base64.getEncoder().encodeToString(ciphertext);  
    }  
​
    // 解密方法类似...  
}

密钥管理方案对比:

image.png

2.方案三:数据遮蔽

数据库中实现数据遮蔽:

-- 创建脱敏视图  
CREATE VIEW masked_customers AS 
SELECT   
    id,    
    CONCAT(SUBSTR(name,1,1), '***') AS name,    
    CONCAT(SUBSTR(mobile,1,3), '****',
           SUBSTR(mobile,8,4)) AS mobile  
FROM customers;  
-- 使用列级权限控制  
GRANT SELECT (id, name, mobile) ON masked_customers TO test_user;

创建数据脱敏视图,在视图中将关键字段做遮蔽。

在后面查询这些字段时就从视图中去查询。

//ShardingSphere(数据库的中间件)
rules:  //规则数组
-!MASK  //对数据进行掩码处理
tables:     //用于定义需要进行掩码处理的表结构
    user:       //表明
      columns:      //列出表中要处理的列
        phone:      //列字段
          maskAlgorithm:phone_mask      //指定要适用的算法phone_mask
maskAlgorithms:     //算法配置集合
    phone_mask:     //单个的自定义算法
      type:MD5      //使用的算法类型是MD5
      props:        //附带的配置
        salt:abcdefg123456      //加盐值(在进行哈希运算之前,把这个值加到原始数据中。这样做的目的是增加哈希结果出来的唯一性和安全性,防止哈希值被破解)

性能测试:

image.png

2.4方案四:数据替换

将原始数据和脱敏的数据保存到cache中,方便后面快速的做转换。

映射表设计:
// 使用Guava Cache实现LRU缓存  
LoadingCache<String, String> dataMapping = CacheBuilder.newBuilder()  
    .maximumSize(100000)  
    .expireAfterAccess(30, TimeUnit.MINUTES)  
    .build(new CacheLoader<String, String>() {  
        public String load(String key) {  
            return UUID.randomUUID().toString().replace("-""");  
        }  
    });  
​
public String replaceData(String original) {  
    return dataMapping.get(original);  
}
替换流程:

image.png

2.5方案五:动态脱敏

应用层实现(Spring AOP)

@Aspect  
@Component
publicclass DataMaskAspect {  
​
    @Around("@annotation(requiresMasking)")  
    public Object maskData(ProceedingJoinPoint joinPoint, RequiresMasking requiresMasking) throws Throwable {  
        Object result = joinPoint.proceed();  
        return mask(result, requiresMasking.type());  
    }  
​
    private Object mask(Object data, MaskType type) {  
        if (data instanceof User) {  
            User user = (User) data;  
            switch(type) {  
                case MOBILE:  
                    user.setMobile(MaskUtil.maskMobile(user.getMobile()));  
                    break;  
                case ID_CARD:  
                    user.setIdCard(MaskUtil.maskIdCard(user.getIdCard()));  
                    break;  
            }  
        }  
        return data;  
    }  
}

在需要做数据脱敏的字段上添加RequiresMasking注解,然后在Spring的AOP拦截器中通过工具类动态实现数据的脱敏。

数据库代理架构:

image.png

2.6方案六:K匿名化

原理:

假设医院发布的数据:

年龄性别疾病
25感冒
25发烧
25骨折

当K=3时,攻击者无法获取到具体某个人的具体信息,因为三个人具有相同特征(25岁男性)。

实现步骤:

image.png

医疗数据泛化示例:

public class KAnonymity {  
    
    // 年龄泛化:精确值→范围  
    public static String generalizeAge(int age) {  
        int range = 10// K=10  
        int lower = (age / range) * range;  
        int upper = lower + range - 1;  
        return lower + "-" + upper;  
    }  
}

假设range是K值,等于10。

generalizeAge方法中,通过一定的算法,将年龄的准确值,泛化成一个区间范围。

输入28,返回20-29。

K值选择原则:

image.png

总结:

方案安全性性能可逆性适用场景
字符串替换★★★★★★不可逆日志/展示
加密算法★★★★★★可逆支付信息存储
数据遮蔽★★★★★★部分可逆数据库查询
数据替换★★★★★★可逆测试数据生成
动态脱敏★★★★★★★动态可逆生产环境查询
K匿名化★★★★★不可逆医疗/位置数据

下图是某电商平台各方案的使用占比:

image.png

3个核心建议

  1. 数据分类分级:不同级别数据采用不同脱敏策略
  2. 定期审计:使用自动化工具扫描敏感数据泄露
  3. 最小化原则:能不收集的敏感数据坚决不收集