问题描述
我试图以不损害参照完整性的方式掩盖数据。
我的表“客户”具有以下数据:
客户表
Customer_ID | Customer_Name | Address | Phone | Product_ID
143 | Mandy Rutter | 2465 Crim Lane. Shawneetown,New York | 718-530-0536 | 995
142 | Rich Raymond | 2150 Linda Street,Eagleville,Pennsylvania | 267-902-9185 | 876
产品表
Product_Seq | Product_Name
995 | T-Shirt
876 | Blazer
现在,我要在客户表中屏蔽Product_ID(例如)。当我屏蔽它时,转换为 995 => xyz 和 876 => pqr
现在应该对Product表应用相同的掩码,否则我将不知道特定的customer_id的product_Name。
我尝试使用基于digest库的解决方案。如果我屏蔽了字母数字,它可以工作,但是对于整数,它不适用。
anonymize <- function(x,algo="crc32"){
unq_hashes <- vapply(unique(x),function(object) digest(object,algo=algo),FUN.VALUE="",USE.NAMES=TRUE)
unname(unq_hashes[x])
}
可以让我知道为什么吗?最近有没有用于屏蔽的软件包,可以在这样做时保持参照完整性?
我考虑过的另一个软件包是anonymizer,但看起来它只将几列视为敏感列,并且在屏蔽时将数字转换为字母数字。
我正在尝试从一个DBMS系统(一些相关表)中复制数据,在保持关系的同时匿名化某些列上的数据,并将其放入其他DBMS系统中。
解决方法
有两件事对您来说很重要
- 匿名
- 参照完整性
对于您的两个要求来说,您所链接的博客文章中的解决方案都是一个错误的选择。
匿名
仅哈希不提供匿名性。本文还提到了(但不在代码中)您可能至少想要添加盐。
只是一个例子:
像211
这样的数字将作为af9fad5f
作为CRC32哈希。如果您与之共享数据的人看到此8char(32bit)字母数字字符串,则它可能会假定这可能是CRC32哈希。散列的好处在于,您无法轻易地计算从af9fad5f
到211
的值。坏事是,大多数短单词/哈希值已经预先计算出来,可以在所谓的彩虹表(例如https://md5hashing.net/hash/crc32/af9fad5f)中轻松查找。
这基本上意味着每个人都可以在crc32哈希后面查找“明文”。 (与所有其他哈希相同)。加盐可以防止这种情况。 (当然必须保密这种盐!)
参照完整性
参照完整性得以保持。 211
将始终作为af9fad5f
作为CRC32哈希值-这是静态的,并且没有随机影响。因此,您的所有表的Product_ID都将保持不变。您需要的是什么。
但是请确保我将使用SHA256而不是CRC32。在CRC32中,所有内容都将映射到8个字符的字母数字(32位)。如果您有大量数据-哈希冲突的可能性就很大。这意味着同一张表中的两个数字/标识实际上具有相同的哈希值。使用SHA256,这几乎是不可能的。
总的来说,我认为使用匿名程序包似乎还可以。 (它没有得到积极维护-但功能似乎还可以)
install.packages("devtools")
devtools::install_github("paulhendricks/anonymizer")
# Some test data
testdata <- data.frame(t1 = c(211,11,9),t2 = c(2,3,9))
anonymizer::anonymize(testdata$t1,.algo = "sha256",.seed = 1)
anonymizer::anonymize(testdata$t2,.seed = 1)
t1
[1] "9ebb37da5a7e1db2a0ff7d0e9aa6df5b6d27a5928ce0454a9e71655cf5a16e46"
[2] "ec3e0f47c01a40969f933b9179edee184bc2d57a77e1941fc1fe773c8ac429b6"
[3] "14439a3c932d0f133ac5f5f9b147be16b4ffd854664b58fcae922084da984e2e"
t2
[1] "03a5ed142ba102af5c8e4328f54c8785310b7a8f1881b3bb9d1803261b64e91a"
[2] "0b65dd05edbd9154c3668ce294ca875e1d079967051c06238516d1a0bb233b7c"
[3] "14439a3c932d0f133ac5f5f9b147be16b4ffd854664b58fcae922084da984e2e"
与您一样,testdata$t1
和testdata$t2
的最后一个散列是相同的,因为它们都是9。
我考虑过的另一个软件包是匿名程序,但是看起来它仅将几列视为敏感列,并且在屏蔽时将数字转换为字母数字。
这是什么意思?是否要用数字值掩盖您的值? (为此,您可以在R中将字符串转换为数值)。但是至少对于产品ID,我并没有真正看到好处。
评论补充:
@Steffen,我们可以以某种方式仅将数字替换为数字吗?例如,SSN是9位数字,而我只想将其替换为另外9位数字。
是的,但对于上面概述的基于哈希的解决方案却不是很好。可能会要求您编写更多代码。这需要非常仔细地完成,因为在确保参照完整性,避免共谋和防止重新识别的同时很容易错过某些东西) 。我真的会尝试使用现有的解决方案。
您也可以看看R中的sdcMicro包。我认为它们没有用于引用完整性的部分。但是您也许可以通过以下方式来规避此问题:联接表,然后使用匿名功能(这样,例如product_id仅位于一列中),然后再次拆分为两个数据集。
我认为使用另一个工具进行匿名化也是一个好主意-看一下这个开源工具ARX – Data Anonymization Tool
如果您打算多次创建匿名数据集,那么这样的外部GUI工具的缺点可能不是一个好主意。由于您没有程序,因此可以运行。