PostgreSQL 安全管理 数据脱敏 Anonymizer 泛化脱敏(Generalization)
1 背景知识
在 脱敏函数 中对 泛化脱敏进行了简单的介绍。这里主要详细解释如何使用泛化函数。
泛化主要是降低敏感数据的准确性。PostgreSQL 可以通过 PostgreSQL 函数 RANGE
2 如何使用泛化脱敏
这里表格中包含一些医疗数据。
# SELECT * FROM patient;
ssn | firstname | zipcode | birth | disease
-------------+-----------+---------+------------+---------------
253-51-6170 | Alice | 47012 | 1989-12-29 | Heart Disease
091-20-0543 | Bob | 42678 | 1979-03-22 | Allergy
565-94-1926 | Caroline | 42678 | 1971-07-22 | Heart Disease
510-56-7882 | Eleanor | 47909 | 1989-12-15 | Acne
098-24-5548 | David | 47905 | 1997-03-04 | Flu
118-49-5228 | Jean | 47511 | 1993-09-14 | Flu
263-50-7396 | Tim | 47900 | 1981-02-25 | Heart Disease
109-99-6362 | Bernard | 47168 | 1992-01-03 | Asthma
287-17-2794 | Sophie | 42020 | 1972-07-14 | Asthma
409-28-2014 | Arnold | 47000 | 1999-11-20 | Diabetes
(10 rows)
由于需要统计,所希望脱敏后的数据仍然保留真实性,我们可以在此表上构建一个视图,以将数据进行脱敏。
CREATE MATERIALIZED VIEW generalized_patient AS
SELECT
'REDACTED'::TEXT AS firstname,
anon.generalize_int4range(zipcode,1000) AS zipcode,
anon.generalize_daterange(birth,'decade') AS birth,
disease
FROM patient;
泛化后的数据
# SELECT * FROM generalized_patient;
firstname | zipcode | birth | disease
-----------+---------------+-------------------------+---------------
REDACTED | [47000,48000) | [1980-01-01,1990-01-01) | Heart Disease
REDACTED | [42000,43000) | [1970-01-01,1980-01-01) | Allergy
REDACTED | [42000,43000) | [1970-01-01,1980-01-01) | Heart Disease
REDACTED | [47000,48000) | [1980-01-01,1990-01-01) | Acne
REDACTED | [47000,48000) | [1990-01-01,2000-01-01) | Flu
REDACTED | [47000,48000) | [1990-01-01,2000-01-01) | Flu
REDACTED | [47000,48000) | [1980-01-01,1990-01-01) | Heart Disease
REDACTED | [47000,48000) | [1990-01-01,2000-01-01) | Asthma
REDACTED | [42000,43000) | [1970-01-01,1980-01-01) | Asthma
REDACTED | [47000,48000) | [1990-01-01,2000-01-01) | Diabetes
(10 rows)
3 泛化函数
Anonymizer 提供6 个泛化函数。每个 RANGE 类型一个。
通常,将原始值作为第一个参数,第二个参数将作为每个值的泛化区间。
3.1 对于数字类型
anon.generalize_int4range(42,5)
返回范围[40,45)
anon.generalize_int8range(12345,1000)
返回范围[12000,13000)
anon.generalize_numrange(42.32378,10)
返回范围[40,50)
3.2 对于时间类型
anon.generalize_tsrange('1904-11-07','year')
返回['1904-01-01','1905-01-01')
anon.generalize_tstzrange('1904-11-07','week')
返回['1904-11-07','1904-11-14')
anon.generalize_daterange('1904-11-07','decade')
返回[1900-01-01,1910-01-01)
Note
对于区间范围可以是:微妙,毫秒,秒,分钟,小时,日,周,年,十年,世纪和千年。
4 泛化函数的局限性
4.1 极值和信息泄露
Singling Out
是指通过极值或者异常值判断特殊数据的可能性。
例如:
# SELECT * FROM employees;
id | name | job | salary
------+----------------+------+--------
1578 | xkjefus3sfzd | NULL | 1498
2552 | cksnd2se5dfa | NULL | 2257
5301 | fnefckndc2xn | NULL | 45489
7114 | npodn5ltyp3d | NULL | 1821
在此表中,我们可以看到某个员工的薪资非常高,与平均值相去甚远,以此可以判断这个人可能是CEO 。
所以对于泛化函数脱敏,需要一个很宽的区间范围,防止识别出某个特殊个体。
k-anonymity 将可以识别这种风险并防范。
4.2 泛化函数无法在动态脱敏中使用
根据泛化函数的定义,通过泛化脱敏,数据保持不变,但是数据类型将会变为区间范围类型。
意味着不能与 动态脱敏一起使用。
4.3 k-anonymity
k-anonymity 是一个标准术语,用于描述脱敏后数据的一种属性。
k-anonymity 原则是指,任何脱敏后的个体都无法与其他个体区分开。
k 值越低,表明使用可识别的风险越高。
可以通过两个步骤评估 k-anonymity
:
4.4 Step1
首先定义作为
SECURITY LABEL FOR k_anonymity ON COLUMN patient.firstname
IS 'INDIRECT IDENTIFIER';
SECURITY LABEL FOR k_anonymity ON COLUMN patient.zipcode
IS 'INDIRECT IDENTIFIER';
SECURITY LABEL FOR k_anonymity ON COLUMN patient.birth
IS 'INDIRECT IDENTIFIER';
4.5 Step2
声明标识符
SELECT anon.k_anonymity('generalized_patient')
这个值越高越好。