数据脱敏方案调研
什么是数据脱敏
先来看看什么是数据脱敏?数据脱敏也叫数据的去隐私化,在我们给定脱敏规则和策略的情况下,对敏感数据比如 手机号、银行卡号 等信息,进行转换或者修改的一种技术手段,防止敏感数据直接在不可靠的环境下使用。
像政府、医疗行业、金融机构、移动运营商是比较早开始应用数据脱敏的,因为他们所掌握的都是用户最核心的私密数据,如果泄露后果是不可估量的。
数据脱敏的应用在生活中是比较常见的,比如我们在淘宝买东西订单详情中,商家账户信息会被用 * 遮挡,保障了商户隐私不泄露,这就是一种数据脱敏方式。
数据脱敏又分为静态数据脱敏(SDM)和 动态数据脱敏(DDM):
静态数据脱敏
静态数据脱敏(SDM):适用于将数据抽取出生产环境脱敏后分发至测试、开发、培训、数据分析等场景。
有时我们可能需要将生产环境的数据 copy 到测试、开发库中,以此来排查问题或进行数据分析,但出于安全考虑又不能将敏感数据存储于非生产环境,此时就要把敏感数据从生产环境脱敏完毕之后再在非生产环境使用。
这样脱敏后的数据与生产环境隔离,满足业务需要的同时又保障了生产数据的安全。
如上图所示,将用户的真实 姓名、手机号、身份证、银行卡号 通过 替换、无效化、乱序、对称加密 等方案进行脱敏改造。
数据脱敏方案
数据脱敏系统可以按照不同业务场景自行定义和编写脱敏规则,可以针对库表的某个敏感字段,进行数据的不落地脱敏。
脱敏系统
数据脱敏的方式有很多种,接下来以下图数据为准一个一个的演示每种方案。
原始数据
1、无效化
无效化方案在处理待脱敏的数据时,通过对字段数据值进行 截断、加密、隐藏 等方式让敏感数据脱敏,使其不再具有利用价值。一般采用特殊字符(*等)代替真值,这种隐藏敏感数据的方法简单,但缺点是用户无法得知原数据的格式,如果想要获取完整信息,要让用户授权查询。
比如我们将身份证号用 * 替换真实数字就变成了 "220724 ** 3523",非常简单。
2、随机值
随机值替换,字母变为随机字母,数字变为随机数字,文字随机替换文字的方式来改变敏感数据,这种方案的优点在于可以在一定程度上保留原有数据的格式,往往这种方法用户不易察觉的。
我们看到 name 和 idnumber 字段进行了随机化脱敏,而名字姓、氏随机化稍有特殊,需要有对应姓氏字典数据支持。
脱敏数据的特征
数据脱敏不仅要执行数据漂白,抹去数据中的敏感内容,同时也需要保持原有的数据特征、业务规则和数据关联性,保证开发、测试、培训以及大数据类业务不会受到脱敏的影响,达成脱敏前后的数据一致性和有效性:
l 保持原有数据特征
数据脱敏前后必须保证数据特征的保持,例如:身份证号码由十七位数字本体码和一位校验码组成,分别为区域地址码(6 位)、出生日期(8 位)、顺序码(3 位)和校验码(1 位)。那么身份证号码的脱敏规就需要保证脱敏后依旧保持这些特征信息。
l 保持数据之间的一致性
在不同业务中,数据和数据之间具有一定的关联性。例如:出生年月或年龄和出生日期之间的关系。同样,身份证信息脱敏后仍需要保证出生年月字段和身份证中包含的出生日期之间的一致性。
l 保持业务规则的关联性
保持数据业务规则的关联性是指数据脱敏时数据关联性以及业务语义等保持不变,其中数据关联性包括:主、外键关联性、关联字段的业务语义关联性等。特别是高度敏感的账户类主体数据往往会贯穿主体的所有关系和行为信息,因此需要特别注意保证所有相关主体信息的一致性。
l 多次脱敏之间的数据一致性
相同的数据进行多次脱敏,或者在不同的测试系统进行脱敏,需要确保每次脱敏的数据始终保持一致性,只有这样才能保障业务系统数据变更的持续一致性以及广义业务的持续一致性。
数据脱敏应用场景
一般常见的数据脱敏场景,是将生产数据或是生产数据文件按照脱敏规则,将数据不落地脱敏至测试数据库或是测试数据文件中,具体如下所示:
脱敏方案
数据脱敏的应用场景主要有2类:
- 1、接口返回数据
- 2、日志打印数据
针对上述场景的需求,数据脱敏的实现方法可以有如下3种:
- 1、基于SQL进行脱敏,保证查询到的结果就是脱敏信息:SQL需要精心设计,依赖数据库函数,性能不高。
- 2、应用层脱敏:将查询到数据根据一定的策略进行脱敏后再返回或打印日志,对应用代码有入侵,性能可控。
- 3、基于日志框架进行脱敏:使用正则表达式进行处理,对日志格式有要求,否则无法识别需要脱敏的信息。
基于SQL语句脱敏
基于SQL语句的数据脱敏,需要依赖相应的数据库函数。
如下,以MySQL数据库为例,在查询数据的时候通过函数concat(),left()和right()实现脱敏处理。
-- 通过SQL语句对查询结果进行脱敏处理
select
concat(left(mobile,3),'********') as mobile_desensitive,
concat(left(idcard,5),'*********',right(idcard,4)) as idcard_desensitive
from `user` u;
查询结果如下:
mobile_desensitive|idcard_desensitive|
------------------+------------------+
132******** |53211*********1111|
153******** |11011*********1111|
基于SQL语句的数据脱敏处理,SQL语句需要精心设计,并且需要依赖数据库函数,同时也可能存在性能瓶颈。
在数据规模可控时可以使用,否则建议使用其他方案。
应用层脱敏
数据脱敏的处理完全在应用层处理,也就说:什么数据该脱敏,如何脱敏,脱敏后如何使用完全在应用层控制。
在应用层进行数据脱敏可以应对日志打印,API接口数据返回等场景需求。
组件 sensitive-plus 提供了完整的解决方案。
字符串脱敏
// 调用工具方法对字符串进行脱敏
String mobile = "15678900987";
String sensitive = SensitiveInfoUtils.mobilePhone(mobile);
System.out.println(String.format("%s\n%s", source, sensitive));
输出:
15678900987
156****0987
对象属性脱敏
// 调用工具方法实现对象属性脱敏
String chineseName = "赵子龙";
String mobile = "13242429876";
String fixPhone = "010-32342214";
String address = "西川成都蜀国大将军府";
String idCard = "123456789012345678";
String bankCard = "6666666666666666666";
String email = "zhaozilong@chengdu.com";
String password = "1234567890";
SimpleEntity entity = SimpleEntity.builder()
.chineseName(chineseName)
.mobile(mobile)
.fixPhone(fixPhone)
.address(address)
.idCard(idCard)
.bankCard(bankCard)
.email(email)
.password(password)
.build();
Object desensitive = SensitiveInfoUtils.desensitive(entity);
System.out.println(JSON.toJSONString(desensitive));
脱敏实战
# -*- coding: utf-8 -*-
"""
@File : dask_k8s.py
@Author : wangchao
@Date : 2024/6/17 0:33
@Desc :
"""
# Local Machine
# import dask.dataframe as dd
import re
if __name__ == '__main__':
#df = dd.read_csv("./datasets/cred_example_idcol_v1.csv")
#df.x.sum().compute()
# 敏感词列表
sensitive_words = ["phone", "id", "address", "shenfen"]
# 构建正则表达式
regex_pattern = r'\b(' + '|'.join(sensitive_words) + r')\b'
def find_sensitive_words(sql_query):
# 不区分大小写
matches = re.findall(regex_pattern, sql_query, re.IGNORECASE)
return matches
def contains_star(sql_query):
return bool(re.search(r'\*', sql_query))
# 示例SQL语句
sql_query = "SELECT * FROM users WHERE id_name = 12345"
# 查找匹配的敏感词
matched_sensitive_words = find_sensitive_words(sql_query)
if matched_sensitive_words:
print("匹配到的敏感词:", matched_sensitive_words)
# 将匹配到的敏感词打印到日志中
with open("log.txt", "a") as logfile:
logfile.write(f"匹配到的敏感词:{', '.join(matched_sensitive_words)}\n")
else:
print("未匹配到敏感词")
# ------------------------- 判断是否含有特殊字符 * -------------------
# 检查是否有 "*" 字符
contains_star_char = contains_star(sql_query)
if contains_star_char:
print('检测到 "*" 字符')
# 将"*"检测结果打印到日志中
with open("log.txt", "a") as logfile:
logfile.write('检测到 "*" 字符\n')
else:
print('未检测到 "*" 字符')
# -------------------------- 判断 SQL 语句中是否包含 dml 操作 -----------
# 定义函数来检查 SQL 语句中是否包含插入数据、创建数据、更新数据的语句
def check_sql_operation(sql_query):
insert_pattern = r'\bINSERT INTO\b'
create_pattern = r'\bCREATE\b'
update_pattern = r'\bUPDATE\b'
if re.search(insert_pattern, sql_query, re.IGNORECASE):
print("SQL语句中包含插入数据的语句")
if re.search(create_pattern, sql_query, re.IGNORECASE):
print("SQL语句中包含创建数据的语句")
if re.search(update_pattern, sql_query, re.IGNORECASE):
print("SQL语句中包含更新数据的语句")
# 示例SQL语句
sql_query1 = "INSERT INTO users (name, age) VALUES ('John', 30)"
sql_query2 = "CREATE TABLE customers (id INT, name VARCHAR(255))"
sql_query3 = "UPDATE users SET age = 31 WHERE name = 'John'"
# 检查每个示例SQL语句包含的操作
check_sql_operation(sql_query1)
check_sql_operation(sql_query2)
check_sql_operation(sql_query3)
相关文章:
大厂也在用的 6种 数据脱敏方案,严防泄露数据的 “内鬼”
常用数据脱敏解决方案
一个注解优雅的实现 接口数据脱敏
如何对数据进行脱敏处理?
数据脱敏的处理方法及查询
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)