使用R屏蔽关系表中的数据

问题描述

我试图以不损害参照完整性的方式掩盖数据。

我的表“客户”具有以下数据:

客户表

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系统中。

解决方法

有两件事对您来说很重要

  1. 匿名
  2. 参照完整性

对于您的两个要求来说,您所链接的博客文章中的解决方案都是一个错误的选择。

匿名

仅哈希不提供匿名性。本文还提到了(但不在代码中)您可能至少想要添加盐。

只是一个例子:

211这样的数字将作为af9fad5f作为CRC32哈希。如果您与之共享数据的人看到此8char(32bit)字母数字字符串,则它可能会假定这可能是CRC32哈希。散列的好处在于,您无法轻易地计算从af9fad5f211的值。坏事是,大多数短单词/哈希值已经预先计算出来,可以在所谓的彩虹表(例如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$t1testdata$t2的最后一个散列是相同的,因为它们都是9。

我考虑过的另一个软件包是匿名程序,但是看起来它仅将几列视为敏感列,并且在屏蔽时将数字转换为字母数字。

这是什么意思?是否要用数字值掩盖您的值? (为此,您可以在R中将字符串转换为数值)。但是至少对于产品ID,我并没有真正看到好处。

评论补充:

@Steffen,我们可以以某种方式仅将数字替换为数字吗?例如,SSN是9位数字,而我只想将其替换为另外9位数字。

是的,但对于上面概述的基于哈希的解决方案却不是很好。可能会要求您编写更多代码。这需要非常仔细地完成,因为在确保参照完整性避免共谋防止重新识别的同时很容易错过某些东西) 。我真的会尝试使用现有的解决方案。

您也可以看看R中的sdcMicro包。我认为它们没有用于引用完整性的部分。但是您也许可以通过以下方式来规避此问题:联接表,然后使用匿名功能(这样,例如product_id仅位于一列中),然后再次拆分为两个数据集。

我认为使用另一个工具进行匿名化也是一个好主意-看一下这个开源工具ARX – Data Anonymization Tool

如果您打算多次创建匿名数据集,那么这样的外部GUI工具的缺点可能不是一个好主意。由于您没有程序,因此可以运行。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...